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:
- @Controller
- @RequestMapping
- @ResponseBody
- @RequestParam
- @PathVariable
- @RequestBody
- @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";
}
}
@Controller
The 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 @Controller
annotations are used in @Component
annotations, and @Component
annotations are not unfamiliar to us. They are used to declare a Bean.
Although some books say that you can replace @Controller
annotations with @Component
annotations, there is no difference in operation, but the ideogram is slightly less, but if you @Controller
modify the @Component
annotations 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 @Component
notes reduced to @Controller
comment, 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 @Controller
annotations 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
@RequestMapping
Annotations are used to map web requests. It has two forms of usage:
- Applied at the method level , as shown in the code above.
- Applied at the class level , when the controller adds an
@RequestMapping
annotation at the class level , this annotation will be applied to all the processor methods of the controller, and the@RequestMapping
annotation on the processor method will@RequestMapping
supplement the declaration of the annotation at the class level .
@RequestMapping
The 3 parameters commonly used in annotations are as follows:
- value: Specify the mapped URL address, such as index
- method: Specify the request type of the mapping, such as GET request, POST request, etc.
- 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:
@RequestMapping
The 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 @ResponseBody
annotations, 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 @ResponseBody
annotation 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
@RequestParam
Annotations 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
@RequestParam
comments can be omitted , but for the legibility of the code, it is recommended to keep the@RequestParam
comments.
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
@RequestParam
annotated parameters must be passed in the Url.
However, the @RequestParam
annotation 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
@PathVariable
The annotation is also used to receive the parameter information in the URL, but it is @RequestParam
slightly different from the annotation.
@PathVariable
Annotations are used to parse the path parameters in the Url, such as the zwwhnly part in https://www.cnblogs.com/zwwhnly/, and the @RequestParam
annotations 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
@PathVariable
value 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 @PathVariable
the 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
@RequestBody
The 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
@RestController
It is a combined annotation, which combines @Controller
annotations and @ResponseBody
annotations. 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, @RestController
annotations 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 @RestController
annotations is equivalent to using @Controller
annotations and @ResponseBody
annotations 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"