Introduction to Spring (13): Spring MVC common annotation explanation

Introduction to Spring (13): Spring MVC common annotation explanation

When using Spring MVC to develop web applications, the development of Controller Controller is very important, although the view (JSP or Thymeleaf) is also very important because it is directly presented to the user, but because the front-end is becoming more and more important now, Many companies have begun to adopt a development model that separates front and back ends, so we can focus on developing controllers for the time being.

Using Spring MVC to develop controllers mainly uses the following 7 annotations:

  1. @Controller
  2. @RequestMapping
  3. @ResponseBody
  4. @RequestParam
  5. @PathVariable
  6. @RequestBody
  7. @RestController

Next, we explain the usage of each annotation in turn.

1. @Controller

First review the new simple controller HelloController in the previous blog:

package chapter05.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloController {
    @RequestMapping(value = "index", method = RequestMethod.GET)
    public String hello() {
        // 
        return "index";
    }
}
 

@ControllerThe function of the annotation here is to declare the controller, and its source code is as follows:

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    String value() default "";
}
 

It is worth noting here that @Controllerannotations are used in @Componentannotations, and @Componentannotations are not unfamiliar to us. They are used to declare a Bean.

Although some books say that you can replace @Controllerannotations with @Componentannotations, there is no difference in operation, but the ideogram is slightly less, but if you @Controllermodify the @Componentannotations in the above code to annotations, and then repackage and publish to Tomcat, you will find the access address http://localhost :8080/spring-action-1.0-SNAPSHOT/index, the following 404 error is reported:

The @Componentnotes reduced to @Controllercomment, and then re-packaged and released to Tomcat, visit http address again://localhost: When 8080/spring-action-1.0- SNAPSHOT/index, access to normal:

Therefore, it is recommended to use @Controllerannotations when declaring controllers in Spring MVC .

Note: programmers should think more and try more when reading technical books, because the explanations in the books are likely to be wrong.

2. @RequestMapping

@RequestMappingAnnotations are used to map web requests. It has two forms of usage:

  1. Applied at the method level , as shown in the code above.
  2. Applied at the class level , when the controller adds an @RequestMappingannotation at the class level , this annotation will be applied to all the processor methods of the controller, and the @RequestMappingannotation on the processor method will @RequestMappingsupplement the declaration of the annotation at the class level .

@RequestMappingThe 3 parameters commonly used in annotations are as follows:

  1. value: Specify the mapped URL address, such as index
  2. method: Specify the request type of the mapping, such as GET request, POST request, etc.
  3. produces: Specifies the media type and character set of the response returned, such as application/json;charset=UTF-8.

Use the org.springframework.web.bind.annotation.RequestMethod enumeration when specifying the method value:

package org.springframework.web.bind.annotation;

public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;

    private RequestMethod() {
    }
}
 

The constants under the org.springframework.http.MediaType class are generally used when specifying the values of produces:

public static final String APPLICATION_JSON_VALUE = "application/json";
public static final MediaType APPLICATION_JSON_UTF8 = valueOf("application/json;charset=UTF-8");
public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";
 

For a better understanding, we add the following code to the HelloController class:

package chapter05.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping(value = "index", method = RequestMethod.GET)
    public String hello() {
        // 
        return "index";
    }
}
 

Repackaged and deployed to Tomcat, the access address at this time has changed from http://localhost:8080/spring-action-1.0-SNAPSHOT/index to http://localhost:8080/spring-action-1.0- SNAPSHOT/hello/index, as shown below:

@RequestMappingThe value attribute of the annotation also supports accepting an array of type String, as shown below:

@RequestMapping({"/hello", "/index"})
public class HelloController {
    // 
}
 

At this time, it can also be accessed through the address http://localhost:8080/spring-action-1.0-SNAPSHOT/index/index:

3. @ResponseBody

In the above code, our method is to return the logical view name index, and then the view parser finally finds the runtime view of/WEB-INF/classes/views/index.jsp, but sometimes we don t need to return a page, and It returns the data directly to the front end.

At this point, we can use @ResponseBodyannotations, which can be placed before the return value or on the method to put the return value in the response body instead of returning a page.

For a better understanding, we create a new DemoAnnoController controller as follows:

package chapter05.controller;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/anno")
public class DemoAnnoController {
    @RequestMapping(value = "/index", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
    public @ResponseBody
    String index(HttpServletRequest request) {
        return "url:" + request.getRequestURI() + " can access";
    }
}
 

Repackage and deploy to Tomcat, access the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/index, the effect is as follows:

You can also put the @ResponseBodyannotation on the method, as shown below:

@RequestMapping(value = "/index", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String index(HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access";
}
 

4. @RequestParam

@RequestParamAnnotations are used to receive parameter information in the URL.

For a better understanding, we add the following method to the DemoAnnoController controller:

@RequestMapping(value = "/requestParam", method = RequestMethod.GET, produces = "text/plain;charset=UTF-8")
@ResponseBody
public String passRequestParam(@RequestParam("id") Long id, @RequestParam("name") String name, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,id: " + id + ",name=" + name;
}
 

Repackage and deploy to Tomcat, access the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=1&name=zwwhnly, the effect is as follows:

Note: In the above example, the parameter name in the Url is exactly the same as the variable name in the method, so the @RequestParamcomments can be omitted , but for the legibility of the code, it is recommended to keep the @RequestParamcomments.

If you do not pass parameters and visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam, the following information will be prompted:

Or just pass one of the parameters and visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=1, the following information will be prompted:

This also shows that the @RequestParamannotated parameters must be passed in the Url.

However, the @RequestParamannotation provides the defaultValue attribute, which can specify the default value for the parameter. For example, we set the default value 1 for the parameter id and the default value zwwhnly for the parameter name, and then visit the address http://localhost:8080/spring-action-1.0- SNAPSHOT/anno/requestParam, the effect is as follows:

Or visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=2, the effect is as follows:

However, there is still an abnormal scenario that needs attention, that is, the parameters passed in the Url do not match the parameter types defined in the method. For example, if we pass the value of id incorrectly, visit the address http://localhost:8080/spring-action-1.0 -SNAPSHOT/anno/requestParam?id=zwwhnly&name=zwwhnly, you will see the following error message:

5. @PathVariable

@PathVariableThe annotation is also used to receive the parameter information in the URL, but it is @RequestParamslightly different from the annotation.

@PathVariableAnnotations are used to parse the path parameters in the Url, such as the zwwhnly part in https://www.cnblogs.com/zwwhnly/, and the @RequestParamannotations are used to parse the query parameters in the Url, such as https://i.cnblogs.com/The page part in posts?page=2.

For a better understanding, we add the following method to the DemoAnnoController controller:

@RequestMapping(value = "/pathvar/{str}", produces = "text/plain;charset=UTF-8")
public @ResponseBody
String demoPathVar(@PathVariable("str") String str, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,str: " + str;
}
 

Repackage and deploy to Tomcat, access the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/pathvar/zwwhnly, the effect is as follows:

Note: If the @PathVariablevalue attribute is specified in the annotation, it will assume that the name of the placeholder is the same as the parameter name of the method.

Because the parameter name of the method is exactly the same as the name of the placeholder, we can remove @PathVariablethe value attribute of the annotation:

@RequestMapping(value = "/pathvar/{str}", produces = "text/plain;charset=UTF-8")
public @ResponseBody
String demoPathVar(@PathVariable String str, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,str: " + str;
}
 

6. @RequestBody

@RequestBodyThe annotation allows the parameters of the request to be in the request body instead of being directly linked after the address, and the annotation is liberated before the parameters.

For a better understanding, we add the following method to the DemoAnnoController controller:

@RequestMapping(value = "/obj", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String passObj(@RequestBody DemoObj demoObj, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,demoObj id " + demoObj.getId() +
            " demoObj name:" + demoObj.getName();
}
 

Repackage and deploy to Tomcat, and then use the Postman tool to call the interface http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/passObj, the effect is as follows:

7. @RestController

@RestControllerIt is a combined annotation, which combines @Controllerannotations and @ResponseBodyannotations. The source code is as follows:

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Controller;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    String value() default "";
}
 

Therefore, if all methods in a controller only return data instead of pages, @RestControllerannotations can be used .

For a better understanding, let's give a specific example.

1. add the following dependencies in pom.xml for conversion between objects and json:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9</version>
</dependency>
 

Then the new controller DemoRestController is as follows:

package chapter05.controller;

import chapter05.model.DemoObj;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rest")
public class DemoRestController {
    @RequestMapping(value = "/getjson", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DemoObj getjson(@RequestBody DemoObj demoObj) {
        return new DemoObj(demoObj.getId(), demoObj.getName());
    }
}
 

Because using @RestControllerannotations is equivalent to using @Controllerannotations and @ResponseBodyannotations at the same time , the above code is equivalent to the following code:

package chapter05.controller;

import chapter05.model.DemoObj;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@ResponseBody
@RequestMapping("/rest")
public class DemoRestController {
    @RequestMapping(value = "/getjson", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DemoObj getjson(@RequestBody DemoObj demoObj) {
        return new DemoObj(demoObj.getId(), demoObj.getName());
    }
}
 

Repackage and deploy to Tomcat, and then use the Postman tool to call the interface http://localhost:8080/spring-action-1.0-SNAPSHOT/rest/getjson, the effect is as follows:

8. Source code and reference

Source address: github.com/zwwhnly/spr... Welcome to download.

Craig Walls "Spring Actual Combat (4th Edition)"

Wang Yunfei "The Disruptor of Java EE Development: Spring Boot Actual Combat"