Spring @RequestMapping注解详解

落花浮王杯 提交于 2019-12-09 02:21:26

Spring @RequestMapping注解详解

@RequestMapping是SpringWeb应用程序中最常被用到的注解之一。这个注解会将HTTP请求映射到MVC和REST控制器(什么是REST控制器,暂时不管)的处理方法上。

RequestMapping基础用法

要配置Web请求的映射,就需要你用上@RequestMapping注解。

The @RequestMapping annotation can be applied to class-level and/or method-level in a controller.

The class-level annotation maps a specific request path or pattern onto a controller.

You can then apply additional method-level annotations to make mappings more specific to handler methods.

下面是一个例子,@RequestMapping annotation applied to both class and methods.

@RestController
@RequestMapping("/home")
public class IndexController{
  @RequestMapping("/")
  String get()
  {
    //mapped to hostname:prort/home/
    return "Hello from get";
  }
  
  @RequestMapping("/index")
  String index(){
    //mapped to hostname:port/home/index/
    return "Hello from index";
  }
}

有了在方法级别的映射,request to /home will be handled by get(), while request to /home/index will be handled by index().

@RequestMapping With Multiple URIs

你可以为一个方法添加多个request mappings. For that, we add one @RequestMapping annotation with a list of values.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = {
        "",
        "/page",
        "page*",
        "view/*,**/msg"
    })
    String indexMultipleMapping() {
        return "Hello from index multiple mapping.";
    }
}

其中value是@RequestMapping的属性。

下面所有的URL都会被indexMulitpleMapping()方法来处理。

  • localhost:8080/home
  • localhost:8080/home/
  • localhost:8080/home/page
  • localhost:8080/home/pageabc
  • localhost:8080/home/view/
  • localhost:8080/home/view/view

@RequestMapping With @RequestParam

The @RequestParam annotation is used with @RequestMapping to bind a web request parameter to the parameter of the handler method.

The @RequestParam annotation can be used with or without a value. The value specifies the request parameter that needs to be mapped to the handler method parameter, as shown in this code snippet.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/id")
    String getIdByValue(@RequestParam("id") String personId) {
        System.out.println("ID is " + personId);
        return "Get ID from query string of URL with value element";
    }
    @RequestMapping(value = "/personId")
    String getId(@RequestParam String personId) {
        System.out.println("ID is " + personId);
        return "Get ID from query string of URL without value element";
    }
}

In Line 6 of this code, the request param id will be mapped to the personId parameter of the getIdByValue() handler method.

The value element of @RequestParam can be omitted if the request param and handler method parameter names are same, as shown in Line 11.

The required element of @RequestParam defines whether the parameter value is required or not.

请看下面这个例子。

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/name")
    String getName(@RequestParam(value = "person", required = false) String personName{
        return "Required element of request param";
    }
}

在这个例子中,required 元素的值为false, the getName() handler method will be called for both of these URLs:

  • /home/name?person=xyz
  • /home/name

The default value of the @RequestParam is used to provide a default value when the request param is not provided or is empty.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/name")
    String getName(@RequestParam(value = "person", defaultValue = "John") String personName) {
        return "Required element of request param";
    }
}

In this code, if the person request param is empty in a request, the getName() handler method will receive the default value John as its parameter.

Using @RequestMapping With HTTP Methods

@RequestMapping可以用来处理HTTP request methods, 例如:GET, PUT, POST, DELETE和PATCH.

默认情况下,all requests are assumed to be of HTTP GET type.

In order to define a request mapping with a specific HTTP method, you need to declare the HTTP method in @RequestMapping using the method element as follows.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(method = RequestMethod.GET)
    String get() {
        return "Hello from get";
    }
    @RequestMapping(method = RequestMethod.DELETE)
    String delete() {
        return "Hello from delete";
    }
    @RequestMapping(method = RequestMethod.POST)
    String post() {
        return "Hello from post";
    }
    @RequestMapping(method = RequestMethod.PUT)
    String put() {
        return "Hello from put";
    }
    @RequestMapping(method = RequestMethod.PATCH)
    String patch() {
        return "Hello from patch";
    }
}

因为"/home"是@RequestMapping加在类上的。

所以All the handler methods will handle requests coming to the same URL (/home), but will depend on the HTTP method being used.

举个例子,a POST request to “/home” will be handled by the post() method, While a DELETE request to “/home” will be handled by the delete() method.

Using @RequestMapping With Producible and Consumable

The request mapping types can be narrowed down using the produces and consumes elements of the @RequestMapping annotation.

In order to produce the object in the requested media type, you use the produces element of @RequestMapping in combination with the @ResponseBody annotation.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/prod", produces = {
        "application/JSON"
    })
    @ResponseBody
    String getProduces() {
        return "Produces attribute";
    }
    @RequestMapping(value = "/cons", consumes = {
        "application/JSON",
        "application/XML"
    })
    String getConsumes() {
        return "Consumes attribute";
    }
}

在这个代码中,the getProduces() handler method produces a JSON response. The getConsumes() handler method consumes JSON as well as XML present in requests.

@RequestMapping With Headers

The @RequestMapping annotation provides a header element to narrow down the request mapping based on headers present in the request.

You can specify the header element as myHeader = myValue,


@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/head", headers = {
        "content-type=text/plain"
    })
    String post() {
        return "Mapping applied along with headers";
    }
}

在上面的代码中,the headers attribute of the @RequestMapping annotation narrows down the mapping to the post() method. With this, the post() method will handle requests to /home/head whose content-type header specifies plain text as the value.

You can also indicate multiple header values like this:

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/head", headers = {
        "content-type=text/plain",
        "content-type=text/html"
    }) String post() {
        return "Mapping applied along with headers";
    }
}

这样一来,It implies that both text/pain as well as text/html are accepted by the post() handler method.

@RequestMapping With Request Parameters

The params element of the @RequestMapping annotation further helps to narrow down request mapping. Using the params element, you can have multiple handler methods handling requests to the same URL, but with different parameters.

看到这里,你可能有一种似曾相识的感觉。对,我们在前面提到过使用@RequestParam这个注释来传参数。这里是利用我们给定的参数来判断,到底是由那个方法来处理这个请求。

You can define params as myParams = myValue. You can also use the negation(否定) operator to specify that a particular parameter is not supported in the request.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/fetch", params = {
        "personId=10"
    })
    String getParams(@RequestParam("personId") String id) {
        return "Fetched parameter using params attribute = " + id;
    }
    @RequestMapping(value = "/fetch", params = {
        "personId=20"
    })
    String getParamsDifferent(@RequestParam("personId") String id) {
        return "Fetched parameter using params attribute = " + id;
    }
}

在上面的代码中,getParams()getParamsDifferent() 方法都会handle requests coming to the same URL (/home/fetch) but will execute depending on the params element.

For example, when the URL is /home/fetch?id=10,(我感觉这里写的有问题,应该是personId=10) the getParams() handler method will be executed with the id value 10. For the URL, localhost:8080/home/fetch?personId-=20, the getParamsDifferent() handler method gets executed with the id value 20.

Using @RequestMapping With Dynamic URIs

The @RequestMapping annotation is used in combination with the @PathVariable annotation to handle dynamic URIs. In this use case, the URI values can act as the parameter of the handler methods in the controller.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping(value = "/fetch/{id}", method = RequestMethod.GET)
    String getDynamicUriValue(@PathVariable String id) {
        System.out.println("ID is " + id);
        return "Dynamic URI parameter fetched";
    }
    @RequestMapping(value = "/fetch/{id:[a-z]+}/{name}", method = RequestMethod.GET)
    String getDynamicUriValueRegex(@PathVariable("name") String name) {
        System.out.println("Name is " + name);
        return "Dynamic URI parameter fetched using regex";
    }
}

在上面的代码中,the method getDynamicUriValue() will execute for a request to localhost:8080/home/fetch/10.

Also, the id parameter of the getDynamicUriValue() handler method will be populated with the value 10 dynamically.

The method getDynamicUriValueRegex() will execute for a request to localhost:8080/home/fetch/category/shirt. However, an exception will be thrown for a request to /home/fetch/10/shirt as it does not match the regular expression.

@PathVariable works differently from @RequestParam. You use @PathVariable to obtain the values of the query parameters from the URI. On the other hand, you use @RequestParam to obtain the parameter values from the URI template.

The @RequestMapping Default Handler Method

In the controller class, you can have default handler method that gets executed when there is a request for a default URI.

@RestController
@RequestMapping("/home")
public class IndexController {
    @RequestMapping()
    String
    default () {
        return "This is a default method for the class";
    }
}

In this code, a request to /home will be handled by the default() method as the annotation does not specify any value.

@RequestMapping Shortcuts

Spring 4.3 introduced method-level variants, also known as composed annotations of @RequestMapping.

For example, @GetMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.GET).

The method level variants are:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping

下面这个例子使用的是复合注解

@RestController
@RequestMapping("/home")
public class IndexController {
    @GetMapping("/person")
    public @ResponseBody ResponseEntity < String > getPerson() {
        return new ResponseEntity < String > ("Response from GET", HttpStatus.OK);
    }
    @GetMapping("/person/{id}")
    public @ResponseBody ResponseEntity < String > getPersonById(@PathVariable String id) {
        return new ResponseEntity < String > ("Response from GET with id " + id, HttpStatus.OK);
    }
    @PostMapping("/person")
    public @ResponseBody ResponseEntity < String > postPerson() {
        return new ResponseEntity < String > ("Response from POST method", HttpStatus.OK);
    }
    @PutMapping("/person")
    public @ResponseBody ResponseEntity < String > putPerson() {
        return new ResponseEntity < String > ("Response from PUT method", HttpStatus.OK);
    }
    @DeleteMapping("/person")
    public @ResponseBody ResponseEntity < String > deletePerson() {
        return new ResponseEntity < String > ("Response from DELETE method", HttpStatus.OK);
    }
    @PatchMapping("/person")
    public @ResponseBody ResponseEntity < String > patchPerson() {
        return new ResponseEntity < String > ("Response from PATCH method", HttpStatus.OK);
    }
}

In this code, each of the handler methods are annotated with the composed variants of @RequestMapping. Although each variant can be interchangeably used with @RequestMapping with the method attribute, It’s considered a best practice to use the composed variant.

但是这里为什么加上了一个@Requestbody,不清楚

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!