When developing Web applications using Spring MVC, Controller development is very important, although views (JSP or Thymeleaf) are also important because they are directly presented to the user. However, as the front end becomes more and more important, many companies are starting to adopt the development model of front and back end separation. So we can focus on developing controllers for now.

The following seven annotations are used to develop a controller using Spring MVC:

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

Next, we explain how to use each annotation in turn.

1. @Controller

Let’s review our new simple controller HelloController from 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(a) {
        // The logical view name returned here
        return "index"; }}Copy the code

The @controller annotation is used to declare the Controller. 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(a) default "";
}
Copy the code

It’s worth noting here that the @Controller annotation uses the @Component annotation, which we’re familiar with, to declare a Bean.

Some books say you can replace the @Controller annotation with the @Component annotation, and it works just as well, just a little less ideographic. But if you change the @Controller annotation to the @Component annotation in the code above, and then repackage it and publish it to Tomcat, Will find that access the address http://localhost:8080/spring-action-1.0-SNAPSHOT/index, submitted to the 404 error is shown below:

Will @ the Component annotation to @ Controller annotations, and then to repackage published to Tomcat, visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/index again, access to normal:

Therefore, it is recommended to use the @Controller annotation when declaring controllers in Spring MVC.

Note: Programmers should think and try a lot when reading technical books, because they are likely to be wrong.

2. @RequestMapping

The @requestMapping annotation is used to map Web requests. It can be used in two ways:

  1. Apply at the method level, as shown in the code above.
  2. Apply at the class level, when controllers are added at the class level@RequestMappingWhen you annotate, this annotation will apply to all of the handler methods on the controller, handler methods@RequestMappingAnnotations are made to classes at the level@RequestMappingAnnotated statements are supplemented.

The three parameters commonly used in @requestMapping annotations are as follows:

  1. Value: specifies the MAPPING URL, for example, index
  2. Method: specifies the mapping request type, such as GET request or POST request
  3. Produces: Specifies the media type and character set of the response returned, e.g. application/json; Charset = utf-8.

Specified method values used when org. Springframework. Web. Bind. The annotation. RequestMethod enumeration:

package org.springframework.web.bind.annotation;

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

    private RequestMethod(a) {}}Copy the code

Produces value specified when using general org. Springframework. HTTP. MediaType class of constants:

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";
Copy the code

To understand this, 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(a) {
        // The logical view name returned here
        return "index"; }}Copy the code

Repackage and deploy to Tomcat, At this time of the visit address from http://localhost:8080/spring-action-1.0-SNAPSHOT/index into http://localhost:8080/spring-action-1.0-SNAPSHOT/hel Lo /index, as shown below:

The value attribute of the @requestMapping annotation also supports accepting a String array as follows:

@RequestMapping({"/hello"."/index"})
public class HelloController {
    // Omit other code
}
Copy the code

At this time also can access through the address http://localhost:8080/spring-action-1.0-SNAPSHOT/index/index:

3. @ResponseBody

In the code above, our method is to return to the logical view of the index, and then by the parser will eventually find the runtime view/WEB – INF/classes/views/index. The JSP views, but sometimes we don’t need to return to a page, but the return data directly to the front.

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

To better understand, let’s create a new DemoAnnoController like this:

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"; }}Copy the code

Repackaged and deployed to Tomcat, visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/index, effect as shown below:

You can also place the @responseBody annotation on the method as follows:

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

4. @RequestParam

The @requestParam annotation is used to receive parameter information in the URL.

To better understand this, 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;
}
Copy the code

Repackaged and deployed to Tomcat, visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam? Id =1&name=zwwhnly, the effect is shown as follows:

Note: In the example above, the parameter names in the Url are exactly the same as the variable names in the method, so the @RequestParam annotation can be omitted, although it is recommended to keep the @RequestParam annotation for legibility of the code.

If you don’t pass parameters, visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam, then you will be prompted the following information:

Or only one parameter, visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam? If the id is 1, the following information is displayed:

This also indicates that parameters using the @requestParam annotation must be passed in the Url.

However, the @requestparam annotation provides the defaultValue attribute, which allows you to specify a defaultValue for a parameter, for example we set the defaultValue for parameter id to 1 and for parameter name to zwwhnly, And then access 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? If id=2, the effect is as follows:

However, there is an exception scenario that needs to be noticed. This is when the parameter type passed in the Url does not match the parameter type defined in the method. For example, if we pass the value of id incorrectly, To access the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam? Id =zwwhnly&name= zwwhnei you will see the following error message:

5. @PathVariable

The @PathVariable annotation is also used to receive parameter information in the URL, but is slightly different from the @requestParam annotation.

@ PathVariable annotations used to resolve in the Url path parameters, such as the zwwhnly part of https://www.cnblogs.com/zwwhnly/, and the query parameter in the @ RequestParam annotations to parse the Url, The page section such as https://i.cnblogs.com/posts?page=2.

To better understand this, 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;
}
Copy the code

Repackaged and deployed to Tomcat, visit the address http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/pathvar/zwwhnly, effect as shown below:

Note: If the @pathVariable annotation specifies the value attribute, it assumes that the placeholder name is the same as the method parameter name.

Since the method’s parameter name is exactly the same as the placeholder name, we can remove the value attribute from the @pathVariable 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;
}
Copy the code

6. @RequestBody

The @requestBody annotation allows the parameters of a request to be in the body of the request, rather than being linked directly after the address. The annotation is placed before the parameters.

To better understand this, 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();
}
Copy the code

Repackaged and deployed to Tomcat, and then use the Postman tools call interface http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/passObj, effect as shown below:

7. @RestController

@restController is a composite annotation that combines the @Controller annotation with the @responseBody annotation. 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(a) default "";
}
Copy the code

Therefore, the @RestController annotation can be used if all methods in a controller simply return data and not pages.

To better understand this, let’s take a concrete example.

First, add the following dependencies to pom.xml for converting between objects and JSON:

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

Then create a new DemoRestController 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 newDemoObj(demoObj.getId(), demoObj.getName()); }}Copy the code

Because using the @RestController annotation is equivalent to using both the @Controller annotation and the @responseBody annotation, 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 newDemoObj(demoObj.getId(), demoObj.getName()); }}Copy the code

Repackaged and deployed to Tomcat, and then use the Postman tools call interface http://localhost:8080/spring-action-1.0-SNAPSHOT/rest/getjson, effect as shown below:

8. Source code and reference

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

Craig Walls: Spring In Action (4th Edition)

Java EE Development Disruptor: Spring Boot Combat by Wang Yunfei