Learn spring MVC from scratch -- binding of request parameters

2, Binding of request parameters

2.1 preparation

In this section, we will use classes on servlet requests such as HttpServletRequest and HttpServletResponse. Servlet API package dependency needs to be introduced. It is necessary to note that the java EE specification was renamed Jakarta EE in 2018. Accordingly, the package name we used before was renamed jakarta.xx from javax.xx. In order to adapt to the new standard, we updated the latest version of spring 5.3.13 and introduced Jakarta. Servlet API.

<properties>
    <spring.version>5.3.13</spring.version>
    <thymeleaf.version>3.0.12.RELEASE</thymeleaf.version>
    <servlet-api.version>4.0.4</servlet-api.version>
    <annotation-api.version>1.3.5</annotation-api.version>
</properties>
<dependencies>
    <!--servlet api-->
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>${servlet-api.version}</version>
        <scope>provided</scope>
    </dependency>
    <!-- Spring rely on -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- thymeleaf-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf</artifactId>
        <version>${thymeleaf.version}</version>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
        <version>${thymeleaf.version}</version>
    </dependency>

    <!--annotation-->
    <dependency>
        <groupId>jakarta.annotation</groupId>
        <artifactId>jakarta.annotation-api</artifactId>
        <version>${annotation-api.version}</version>
    </dependency>
</dependencies>
  • Possible problems

    • @The Resource annotation cannot be import ed, or the injection is empty

      Add the dependency of the annotation API and confirm the version number

    • Unable to start Tomcat org.apache.catalina.LifecycleException: subcontainer startup failed

      Solution: confirm whether there are multiple spring web components of different versions in the deployed war package, and clean up the redundant jar package.

      https://blog.csdn.net/AIMINdeCSDN/article/details/103590010

2.2 three methods of parameter binding

2.2.1 obtaining parameters through servlet API

We can add parameters HttpServletRequest and HttpServletResponse to the controller method, and then obtain the request parameters through the getParameter() method. The example code is as follows:

  • Controller layer

Create a GET request / user with QueryParam parameter id and request id

GET /user?id=00112233
@Controller
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping(value = "/user")
    @ResponseBody
    public String getUser(HttpServletRequest request, HttpServletResponse response) {
        String id = request.getParameter("id");
        return userService.getUserName(id);
    }
}
  • Service layer

Here, we use hashmap to simulate the dao layer query database operation. The user with query id 00112233 is "zhangsan"

@Service
public class UserService {
    private final Map<String, String> userMap = new HashMap<String, String>(){{
        put("00112233", "Zhang San");
        put("00112234", "Yan Si");
    }};

    public String getUserName(String userId) {
        return userMap.get(userId);
    }
}

We use postman to test the interface, and you can see

Let's briefly introduce the common methods

// 1. Get QueryParam parameter
// Specifies the parameter value of the parameter name, and returns null if it does not exist
request.getParameter(String paramter);
// Get all parameters. If multiple parameters are connected with &, for ex amp le, id = 00112233 & name = Zhangsan
request.getQueryString();

// 2. Get url path parameters
// Get the exact match with the "URL pattern" in the Servlet
request.getServletPath()
    

2.2.2 obtain by annotation (recommended)

Due to the use of spring MVC, parameters are generally obtained through annotations. Common annotations are as follows:

  • @PathVariable get path parameters
    • value: the name of the binding URL path parameter
    • name: same as value
    • requried: required parameter; the default value is true; required.
  • @RequestParam get QueryParam parameter
    • value: parameter name in binding request
    • name: same as value
    • requried: required parameter; the default value is true; required.
    • defaultValue: the default value when the parameter is not transferred.
  • @RequestBody gets the body request body parameters, which can be serialized into an object

Let's demonstrate this by modifying the User example above:

Add pojo object User

@Getter
@Setter
@ToString
public class User {
    private String id;

    private String name;
}

Controller layer three requests

  1. Query a user: GET /user?id=00112233
  2. Add multiple users: POST /users
  3. Delete a user: DELETE /user/{user_id}
@Controller
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping(value = "/user")
    @ResponseBody
    public String getUser(@RequestParam(value = "id") String id) {
        return userService.getUserName(id);
    }

    @RequestMapping(value = "/users")
    @ResponseBody
    public String getUser(@RequestBody List<User> users) {
        System.out.println(users);
        return "success";
    }

    @RequestMapping(value = "/user/{user_id}")
    @ResponseBody
    public String deleteUser(@PathVariable(value = "user_id") String userId) {
        System.out.println(userId);
        return "success";
    }
}

Because we use the post request and serialize the parameters into list < user > objects, we plan to use json for serialization and deserialization, so we introduce the json serialization dependency jackson

Introducing jackson dependency into pom.xml

<jackson.version>2.13.0</jackson.version>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>
  • be careful

    If the request discovery response code is 415, jackson may not be introduced, so the related serialization dependency must be introduced.

In order to test the above three interfaces, the requests are constructed as follows:

  1. GET /user?id=00112233

  2. POST /users

    [
        {
            "id": 11223344,
            "name": "Zhang San"
        },
        {
            "id": 55667788,
            "name": "Li Si"
        }
    ]
    
  3. DELETE /user/00112233

The test results using postman tool are as follows:

2.2.3 QueryParam parameter binding with the same name

springmvc provides a mechanism for binding QueryParam parameters with the same name. For QueryParam parameters, springmvc will automatically find parameters with the same name on the Controller method or properties with the same name on the entity class for binding. A simple example is as follows:

We modified the previous HelloController and added two interfaces as follows:

  1. Query the specified user name: GET /hello?userName=ZhangSan
  2. Query the specified user: get / Hello? Id = 00112233 & name = Zhangsan
@Controller
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    public String helloUser(String userName) {
        return "Hi, " + userName;
    }

    @RequestMapping("/hello/user")
    @ResponseBody
    public String helloUser(User user) {
        System.out.println("hello world");
        return "Hi, " + user.getName();
    }
}

In the above example, we annotated String userName with @ RequestParam. The test results are as follows:

In the first example, our request parameter is userName=ZhangSan, but without @ RequestParam annotation, ZhangSan can also be bound to userName; Similarly, the name value requested in the second example can also be bound to user.name. The following two examples show the binding mechanism with the same name:

You can see that the above userName and user.getName() values are null, and you can see the parameter binding mechanism of spring MVC with the same name. The value attributes of @ RquestParam and @ PathVariable solve the problem of inconsistent front and rear parameters. The parameters of the front end are generally underlined Kernel style (user_name), and the back end is generally small hump style (userName). Moreover, the parameter binding mechanism with the same name is not easy to maintain, so it is generally recommended to bind parameters through annotations.

Keywords: Java JavaEE Spring Spring MVC

Added by b-ware on Sun, 05 Dec 2021 23:40:47 +0200