banner
月落星河Tsukistar

月落星河Tsukistar

浩瀚中的伟大,孤独间的渺小
github
twitter
youtube
bilibili
email

Developing POST interfaces using the SpringBoot framework

Layering of SpringBoot Projects#

SpringBoot framework projects are generally divided into five layers:

  • View Layer: Displays pages to users

  • Controller Layer: The interaction layer between front and back ends, receives front-end requests, calls methods in the Service layer, receives data returned from the Service layer, and returns it to the front end.

  • Service Layer: Contains business processing logic and some database operation interfaces

  • Mapper Layer: Also known as the DAO layer, it is the interface for database CRUD operations, containing only method names, with specific implementations in the mapper.xml file for data persistence operations on the database.

  • Entity Layer: Contains entity classes, which generally correspond to the properties in the database.

Implementing a Simple POST Interface#

A simple POST interface only requires declaring a RestController class in the Controller layer, then using the PostMapping annotation in the class to indicate that this is a POST interface and filling in the relevant methods, as shown below:

@RestController
@RequestMapping("/api")
public class CreateNumberController {
    @PostMapping("/number")
    public String createNumber(@RequestParam String param1, @RequestParam int param2) {
        // Code to handle POST request
        return "success";
    }
}

After running the program, use Postman to send a POST request to http://localhost:8000/api/number, input the corresponding request parameters, and receive the interface response:

Basic Interface Response

Connecting the Interface to Transaction Processing Logic Functions#

In actual business, interfaces are certainly not as simple as the example above; there will be certain logical processing for the received data within the program.

Next, let's outline a practical business scenario:

Requirements#

Now an interface is needed to assign project codes to projects according to certain rules. The project request content is an XML message, for example:

<?xml version="1.0" encoding="UTF-8"?>
<name>Example Project</name>
<operate>01</operate>
<source>A</source>
<status>01</status>

When the request parameter operate is 1, it indicates adding a new project code. When the request parameter source is A, B, or C, the project code is Axxxx, where "xxxx" is a four-digit sequential code consisting of the digits "0~9" and uppercase letters "A~Z" in the order: 0/1/2/3/4/5/6/7/8/9/A/B/C/D~/X/Y/Z. Two constraints are added:

① The 5th, 4th, and 3rd digits start from 000, and the 2nd digit starts from B, meaning the initial code is: AB000; the range of values for the 5th to 2nd digits is the digits "0~9" and 24 uppercase letters (excluding I and O) from A~Z, totaling 34 characters in the order of 0/1/2/3/4/5/6/7/8/9/A/B/C/D~/X/Y/Z, where "xxxx" is a 4-digit base-34 number. After the 5th digit cycles from 0 to Z, it increments the 4th digit by 1; after the 4th digit cycles, it increments the 3rd digit by 1; and after the 3rd digit cycles, it increments the 2nd digit by 1.

② The 2nd digit cannot be I or O, and also cannot be A, C, or Z. The cycle starts from B and ends at A, in the order of B/D…G/H/J/K…M/N/P…X/Y/0/1…9, totaling 31 characters.

The return value should be an XML message in the form of:

<?xml version="1.0" encoding="UTF-8"?>
<number>AB000</number>
<status>01</status>

Since it has not yet been specified how to check for duplicate codes (this will require a database query, which will be supplemented in the following sections), the requirement can be simply understood as: receiving an XML message, generating a code according to the rules, and returning the code.

At this point, both the input and output of the interface are XML messages, and relying solely on a simple Controller is no longer sufficient. It is necessary to process the input message to split the corresponding parameters, rely on the Service to process the input data, use functions to generate the required output, and finally encapsulate it into an XML message for return.

POST Interface Receiving XML Messages#

Generally speaking, when designing an interface, the thought process is top-down, that is, "the interface can receive and parse the request body → call the Service to use the data in the request body to run business logic → encapsulate the obtained results to complete the response." However, the actual development steps are: clarify which attributes and data types are included in the request and response bodies based on the requirements, construct request and response classes → add a new Service class to write the processing logic for the request class and the generation logic for the response class → add a new Controller class to create a POST interface that can receive XML messages and return XML messages after processing by the Service.

Importing Relevant Dependencies#

To handle XML messages, Gradle needs to import the jackson-dataformat-xml dependency. To ensure the project's portability and reusability, we will not introduce Lombok.

Search for the jackson-dataformat-xml dependency in the Maven repository (e.g., https://mvnrepository.com/), select Gradle, and copy the following line into the dependencies section of build.gradle:

implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2'

The Jackson library will automatically map XML elements to Java properties with the same name.

Import to Gradle

Creating Request and Response Classes#

Based on the request message, add ProjectNumberRequest and ProjectNumberResponse classes in the Controller folder, as follows:

ProjectNumberRequest.java

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

public class ProjectNumberRequest {
    private String name;
    private String operate;
    private String source;
    private String status;
    
    // Getter methods
    public String getName() {
        return this.name;
    }
    public String getOperate() {
        return this.operate;
    }
    public String getSource() {
        return this.source;
    }
    public String getStatus() {
        return this.status;
    }
    
    // Setter methods
    public void setName(String projectName) {
        this.name = projectName;
    }
    public void setOperate(String projectOperate) {
        this.operate = projectOperate;
    }
    public void setSource(String projectSource) {
        this.source = projectSource;
    }
    public void setStatus(String projectStatus) {
        this.status = projectStatus;
    }
}

ProjectNumberResponse.java

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "response")
public class ProjectNumberResponse {
    private String number;
    private String status;

    // Getter methods
    public String getNumber() {
        return this.number;
    }
    public String getStatus() {
        return this.status;
    }

    // Setter methods
    public void setNumber(String number) {
        this.number = number;
    }
    public void setStatus(String projectStatus) {
        this.status = projectStatus;
    }
}

Note: Annotations like @JacksonXmlRootElement(localName = "response") can rename the root node of the XML to response. If the annotation is not added, the root node name of the XML file will default to the class name.

Writing Business Logic#

Add the CreateNumberService class in the Service folder to handle the request body of the request message and generate the project code and project status attributes according to certain rules, converting them into an XML file to form the response body of the response message.

CreateNumberService consists of two parts: the first part is the response object generation function, which is used to create the response body object; the second part is the XML object generation function, which is used to encapsulate the response object into an XML object.

CreateNumberService.java

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.springframework.stereotype.Service;
import studio.tsukistar.demo.Controller.ProjectNumberRequest;
import studio.tsukistar.demo.Controller.ProjectNumberResponse;

import java.util.Objects;
@Service
public class CreateNumberService {
    private static final String XML_HEAD = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
    
    public String createService(ProjectNumberRequest request) { // Build response object
        ProjectNumberResponse response = new ProjectNumberResponse();
        response.setNumber( "AB000" );
        response.setStatus(request.getStatus());
        return javaBeanToXml (response);
    }
    
    public static String javaBeanToXml(Object obj) { // Convert Object to XML format
        String xml= "";
        if (Objects.isNull(obj)) {
            return xml;
        }
        
        try {
            XmlMapper xmlMapper = new XmlMapper();
            xml = xmlMapper.writeValueAsString(obj);
        } catch (Exception e) {
            return "";
        }
        
        return XML_HEAD + xml;
    }
}

Writing the Controller#

Add the CreateNumberController class in the Controller folder, setting the request body input type to XML format and returning the response message obtained after processing the request body by CreateNumberService.

CreateNumberController.java

import jakarta.annotation.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import studio.tsukistar.demo.Service.CreateNumberService;

@RestController
@RequestMapping("/api")
public class CreateNumberController {
    @Resource
    private CreateNumberService numberService;

    @PostMapping(value="/number", produces = MediaType.APPLICATION_XML_VALUE)
    public String createNumber(@RequestBody ProjectNumberRequest request) { // Code to handle POST request
        return numberService.createService(request);
    }
}

Running Tests#

After running the program, use Postman to send a POST request to http://localhost:8000/api/number, select "raw-XML" in the "Body", and fill in the request body:

<?xml version="1.0" encoding="UTF-8" ?>
<request>
    <name>Test</name>
    <operate>01</operate>
    <source>A</source>
    <status>01</status>
</request>

Click "Send" to receive the response message from the interface, as shown in the figure below:

Test Results

Summary#

Compared to last time, I have learned about the development of POST interfaces, project layering, and interactions between layers during this period, gaining a deeper understanding of the SpringBoot framework (perhaps? I hope not to go astray). The code has also been uploaded to the GitHub repository, marking a significant step forward.

Most of the development knowledge in this article comes from Bing AI. If there are any errors, I would greatly appreciate guidance from everyone.

Reference Articles#

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.