Use composed @RequestMapping variants in the reference manual

Issue: SPR-13995
This commit is contained in:
Sam Brannen 2016-06-07 18:06:14 +02:00
parent c121f460b1
commit 01d234f9f3
1 changed files with 68 additions and 67 deletions

View File

@ -785,7 +785,7 @@ to the value of a URI template variable:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
@GetMapping("/owners/{ownerId}")
public String findOwner(**@PathVariable** String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
@ -807,20 +807,21 @@ template variable by name. You can specify it in the annotation:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
@GetMapping("/owners/{ownerId}")
public String findOwner(**@PathVariable("ownerId")** String theOwner, Model model) {
// implementation omitted
}
----
Or if the URI template variable name matches the method argument name you can omit that
detail. As long as your code is not compiled without debugging information, Spring MVC
will match the method argument name to the URI template variable name:
detail. As long as your code is compiled with debugging information or the `-parameters`
compiler flag on Java 8, Spring MVC will match the method argument name to the URI
template variable name:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
@GetMapping("/owners/{ownerId}")
public String findOwner(**@PathVariable** String ownerId, Model model) {
// implementation omitted
}
@ -832,7 +833,7 @@ A method can have any number of `@PathVariable` annotations:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)
@GetMapping("/owners/{ownerId}/pets/{petId}")
public String findPet(**@PathVariable** String ownerId, **@PathVariable** String petId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
Pet pet = owner.getPet(petId);
@ -844,7 +845,7 @@ A method can have any number of `@PathVariable` annotations:
When a `@PathVariable` annotation is used on a `Map<String, String>` argument, the map
is populated with all URI template variables.
A URI template can be assembled from type and path level __@RequestMapping__
A URI template can be assembled from type and method level __@RequestMapping__
annotations. As a result the `findPet()` method can be invoked with a URL such as
`/owners/42/pets/21`.
@ -863,7 +864,7 @@ annotations. As a result the `findPet()` method can be invoked with a URL such a
}
----
A `@PathVariable` argument can be of __any simple type__ such as int, long, Date, etc.
A `@PathVariable` argument can be of __any simple type__ such as `int`, `long`, `Date`, etc.
Spring automatically converts to the appropriate type or throws a
`TypeMismatchException` if it fails to do so. You can also register support for parsing
additional data types. See <<mvc-ann-typeconversion>> and <<mvc-ann-webdatabinder>>.
@ -876,24 +877,24 @@ Sometimes you need more precision in defining URI template variables. Consider t
The `@RequestMapping` annotation supports the use of regular expressions in URI template
variables. The syntax is `{varName:regex}` where the first part defines the variable
name and the second - the regular expression.For example:
name and the second - the regular expression. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String extension) {
// ...
}
public void handle(@PathVariable String version, @PathVariable String extension) {
// ...
}
----
[[mvc-ann-requestmapping-patterns]]
==== Path Patterns
In addition to URI templates, the `@RequestMapping` annotation also supports Ant-style
path patterns (for example, `/myPath/{asterisk}.do`). A combination of URI template variables and
Ant-style globs is also supported (e.g. `/owners/{asterisk}/pets/{petId}`).
In addition to URI templates, the `@RequestMapping` annotation and all _composed_
`@RequestMapping` variants also support Ant-style path patterns (for example,
`/myPath/{asterisk}.do`). A combination of URI template variables and Ant-style globs is
also supported (e.g. `/owners/{asterisk}/pets/{petId}`).
[[mvc-ann-requestmapping-pattern-comparison]]
@ -923,7 +924,7 @@ can be customized (see <<mvc-config-path-matching>> in the section on configurin
[[mvc-ann-requestmapping-placeholders]]
==== Path Patterns with Placeholders
Patterns in `@RequestMapping` annotations support ${...} placeholders against local
Patterns in `@RequestMapping` annotations support `${...}` placeholders against local
properties and/or system properties and environment variables. This may be useful in
cases where the path a controller is mapped to may need to be customized through
configuration. For more information on placeholders, see the javadocs of the
@ -1030,7 +1031,7 @@ Below is an example of extracting the matrix variable "q":
----
// GET /pets/42;q=11;r=22
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
@GetMapping("/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) {
// petId == 42
@ -1047,7 +1048,7 @@ specific to identify where the variable is expected to be:
----
// GET /owners/42;q=11/pets/21;q=22
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable(name="q", pathVar="ownerId") int q1,
@MatrixVariable(name="q", pathVar="petId") int q2) {
@ -1065,7 +1066,7 @@ A matrix variable may be defined as optional and a default value specified:
----
// GET /pets/42
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
@GetMapping("/pets/{petId}")
public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) {
// q == 1
@ -1080,7 +1081,7 @@ All matrix variables may be obtained in a Map:
----
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable MultiValueMap<String, String> matrixVars,
@MatrixVariable(pathVar="petId"") MultiValueMap<String, String> petMatrixVars) {
@ -1131,21 +1132,20 @@ to `false`.
[[mvc-ann-requestmapping-consumes]]
==== Consumable Media Types
You can narrow the primary mapping by specifying a list of consumable media types. The
request will be matched only if the __Content-Type__ request header matches the specified
request will be matched only if the `Content-Type` request header matches the specified
media type. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Controller
@RequestMapping(path = "/pets", method = RequestMethod.POST, **consumes="application/json"**)
@PostMapping(path = "/pets", **consumes = "application/json"**)
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
}
----
Consumable media type expressions can also be negated as in __!text/plain__ to match to
all requests other than those with __Content-Type__ of __text/plain__. Also consider
Consumable media type expressions can also be negated as in `!text/plain` to match to
all requests other than those with `Content-Type` of `text/plain`. Also consider
using constants provided in `MediaType` such as `APPLICATION_JSON_VALUE` and
`APPLICATION_JSON_UTF8_VALUE`.
@ -1161,7 +1161,7 @@ rather than extend type-level consumable types.
[[mvc-ann-requestmapping-produces]]
==== Producible Media Types
You can narrow the primary mapping by specifying a list of producible media types. The
request will be matched only if the __Accept__ request header matches one of these
request will be matched only if the `Accept` request header matches one of these
values. Furthermore, use of the __produces__ condition ensures the actual content type
used to generate the response respects the media types specified in the __produces__
condition. For example:
@ -1169,8 +1169,7 @@ condition. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Controller
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, **produces = MediaType.APPLICATION_JSON_UTF8_VALUE**)
@GetMapping(path = "/pets/{petId}", **produces = MediaType.APPLICATION_JSON_UTF8_VALUE**)
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// implementation omitted
@ -1186,8 +1185,8 @@ the `UTF-8` charset.
====
Just like with __consumes__, producible media type expressions can be negated as in
__!text/plain__ to match to all requests other than those with an __Accept__ header
value of __text/plain__. Also consider using constants provided in `MediaType` such
`!text/plain` to match to all requests other than those with an `Accept` header
value of `text/plain`. Also consider using constants provided in `MediaType` such
as `APPLICATION_JSON_VALUE` and `APPLICATION_JSON_UTF8_VALUE`.
[TIP]
@ -1212,7 +1211,7 @@ example with a request parameter value condition:
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, **params="myParam=myValue"**)
@GetMapping(path = "/pets/{petId}", **params = "myParam=myValue"**)
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
@ -1230,7 +1229,7 @@ specific request header value:
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(path = "/pets", method = RequestMethod.GET, **headers="myHeader=myValue"**)
@GetMapping(path = "/pets", **headers = "myHeader=myValue"**)
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
@ -1253,15 +1252,17 @@ respectively instead. They are intended specifically for that purpose.
`@RequestMapping` methods mapped to "GET" are also implicitly mapped to "HEAD",
i.e. there is no need to have "HEAD" explicitly declared. An HTTP HEAD request
is processed as if it was an HTTP GET except instead of writing the body only
is processed as if it were an HTTP GET except instead of writing the body only
the number of bytes are counted and the "Content-Length" header set.
`@RequestMapping` method have built-in support for HTTP OPTIONS. By default an
`@RequestMapping` methods have built-in support for HTTP OPTIONS. By default an
HTTP OPTIONS request is handled by setting the "Allow" response header to the
HTTP methods explicitly declared on all `@RequestMapping` methods with matching
URL patterns. When no HTTP methods are explicitly declared the "Allow" header
is set to "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS". Ideally always declare the
HTTP method(s) an `@RequestMapping` method is intended to handle.
HTTP method(s) that an `@RequestMapping` method is intended to handle, or alternatively
use one of the dedicated _composed_ `@RequestMapping` variants (see
<<mvc-ann-requestmapping-composed>>).
Although not necessary an `@RequestMapping` method can be mapped to and handle
either HTTP HEAD or HTTP OPTIONS, or both.
@ -1272,9 +1273,9 @@ either HTTP HEAD or HTTP OPTIONS, or both.
[[mvc-ann-methods]]
=== Defining @RequestMapping handler methods
An `@RequestMapping` handler method can have a very flexible signatures. The supported
`@RequestMapping` handler methods can have very flexible signatures. The supported
method arguments and return values are described in the following section. Most
arguments can be used in arbitrary order with the only exception of `BindingResult`
arguments can be used in arbitrary order with the only exception being `BindingResult`
arguments. This is described in the next section.
[NOTE]
@ -1378,7 +1379,7 @@ sample won't work:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(method = RequestMethod.POST)
@PostMapping
public String processSubmit(**@ModelAttribute("pet") Pet pet**, Model model, **BindingResult result**) { ... }
----
@ -1388,7 +1389,7 @@ this working you have to reorder the parameters as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(method = RequestMethod.POST)
@PostMapping
public String processSubmit(**@ModelAttribute("pet") Pet pet**, **BindingResult result**, Model model) { ... }
----
@ -1468,7 +1469,7 @@ The following code snippet shows the usage:
// ...
@RequestMapping(method = RequestMethod.GET)
@GetMapping
public String setupForm(**@RequestParam("petId") int petId**, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
@ -1500,7 +1501,7 @@ be bound to the value of the HTTP request body. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/something", method = RequestMethod.PUT)
@PutMapping("/something")
public void handle(@RequestBody String body, Writer writer) throws IOException {
writer.write(body);
}
@ -1572,14 +1573,14 @@ or the MVC Java config.
[[mvc-ann-responsebody]]
==== Mapping the response body with the @ResponseBody annotation
The `@ResponseBody` annotation is similar to `@RequestBody`. This annotation can be put
The `@ResponseBody` annotation is similar to `@RequestBody`. This annotation can be placed
on a method and indicates that the return type should be written straight to the HTTP
response body (and not placed in a Model, or interpreted as a view name). For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/something", method = RequestMethod.PUT)
@GetMapping("/something")
@ResponseBody
public String helloWorld() {
return "Hello World";
@ -1598,7 +1599,7 @@ section and <<rest-message-conversion,Message Converters>>.
It's a very common use case to have Controllers implement a REST API, thus serving only
JSON, XML or custom MediaType content. For convenience, instead of annotating all your
`@RequestMapping` methods with `@ResponseBody`, you can annotate your Controller Class
`@RequestMapping` methods with `@ResponseBody`, you can annotate your controller Class
with `@RestController`.
{api-spring-framework}/web/bind/annotation/RestController.html[`@RestController`]
@ -1707,8 +1708,8 @@ i.e., with or without an attribute name.
The `@ModelAttribute` annotation can be used on `@RequestMapping` methods as well. In
that case the return value of the `@RequestMapping` method is interpreted as a model
attribute rather than as a view name. The view name is derived from view name
conventions instead much like for methods returning void -- see <<mvc-coc-r2vnt>>.
attribute rather than as a view name. The view name is then derived based on view name
conventions instead, much like for methods returning `void` -- see <<mvc-coc-r2vnt>>.
[[mvc-ann-modelattrib-method-args]]
@ -1727,7 +1728,7 @@ form field individually.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@ModelAttribute Pet pet**) { }
----
@ -1749,9 +1750,9 @@ using an URI template variable and a type converter. Here is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/accounts/{account}", method = RequestMethod.PUT)
@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) {
// ...
}
----
@ -1774,7 +1775,7 @@ following the `@ModelAttribute` argument:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
if (result.hasErrors()) {
@ -1807,7 +1808,7 @@ public Account findAccount(@PathVariable String accountId) {
return accountRepository.findOne(accountId);
}
@RequestMapping(path="update", method=POST)
@PostMapping("update")
public String update(@Valid AccountUpdateForm form, BindingResult result,
**@ModelAttribute(binding=false)** Account account) {
@ -1823,7 +1824,7 @@ subsequently reported back to the user:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) {
new PetValidator().validate(pet, result);
@ -1842,7 +1843,7 @@ annotation:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(**@Valid @ModelAttribute("pet") Pet pet**, BindingResult result) {
if (result.hasErrors()) {
@ -2079,8 +2080,8 @@ binding directly within your controller class. `@InitBinder` identifies methods
initialize the `WebDataBinder` that will be used to populate command and form object
arguments of annotated handler methods.
Such init-binder methods support all arguments that `@RequestMapping` supports, except
for command/form objects and corresponding validation result objects. Init-binder
Such init-binder methods support all arguments that `@RequestMapping` methods support,
except for command/form objects and corresponding validation result objects. Init-binder
methods must not have a return value. Thus, they are usually declared as `void`.
Typical arguments include `WebDataBinder` in combination with `WebRequest` or
`java.util.Locale`, allowing code to register context-specific editors.
@ -2209,7 +2210,7 @@ the view class or interface to be used:
@RestController
public class UserController {
@RequestMapping(path = "/user", method = RequestMethod.GET)
@GetMapping("/user")
@JsonView(User.WithoutPasswordView.class)
public User getUser() {
return new User("eric", "7!jd#h23");
@ -2261,7 +2262,7 @@ to the model:
@Controller
public class UserController extends AbstractController {
@RequestMapping(path = "/user", method = RequestMethod.GET)
@GetMapping("/user")
public String getUser(Model model) {
model.addAttribute("user", new User("eric", "7!jd#h23"));
model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class);
@ -2309,7 +2310,7 @@ is an example of such a controller method:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(method=RequestMethod.POST)
@PostMapping
public Callable<String> processUpload(final MultipartFile file) {
return new Callable<String>() {
@ -3006,7 +3007,7 @@ through `Model` nor `RedirectAttributes`. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/files/{path}", method = RequestMethod.POST)
@PostMapping("/files/{path}")
public String upload(...) {
// ...
return "redirect:files/{path}";
@ -3178,7 +3179,7 @@ application/atom+xml is shown below.
private List<SampleContent> contentList = new ArrayList<SampleContent>();
@RequestMapping(path="/content", method=RequestMethod.GET)
@GetMapping("/content")
public ModelAndView getContent() {
ModelAndView mav = new ModelAndView();
mav.setViewName("content");
@ -3326,7 +3327,7 @@ Spring MVC also provides a mechanism for building links to controller methods. F
@RequestMapping("/hotels/{hotel}")
public class BookingController {
@RequestMapping("/bookings/{booking}")
@GetMapping("/bookings/{booking}")
public String getBooking(@PathVariable Long booking) {
// ...
@ -3791,7 +3792,7 @@ use `MultipartHttpServletRequest` or `MultipartFile` in the method parameters:
@Controller
public class FileUploadController {
@RequestMapping(path = "/form", method = RequestMethod.POST)
@PostMapping("/form")
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) {
@ -3820,7 +3821,7 @@ the method parameter:
@Controller
public class FileUploadController {
@RequestMapping(path = "/form", method = RequestMethod.POST)
@PostMapping("/form")
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("file") Part file) {
@ -3878,7 +3879,7 @@ multipart:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping(path = "/someUrl", method = RequestMethod.POST)
@PostMapping("/someUrl")
public String onSubmit(**@RequestPart("meta-data") MetaData metadata,
@RequestPart("file-data") MultipartFile file**) {
@ -3937,7 +3938,7 @@ may be more convenient to directly set the status of the response and optionally
error content to the body of the response.
You can do that with `@ExceptionHandler` methods. When declared within a controller such
methods apply to exceptions raised by `@RequestMapping` methods of that contoroller (or
methods apply to exceptions raised by `@RequestMapping` methods of that controller (or
any of its sub-classes). You can also declare an `@ExceptionHandler` method within an
`@ControllerAdvice` class in which case it handles exceptions from `@RequestMapping`
methods from many controllers. Below is an example of a controller-local
@ -4487,14 +4488,14 @@ This involves calculating a lastModified `long` and/or an Etag value for a given
comparing it against the `'If-Modified-Since'` request header value, and potentially returning
a response with status code 304 (Not Modified).
As described in <<mvc-ann-httpentity>>, Controllers can interact with the request/response using
As described in <<mvc-ann-httpentity>>, controllers can interact with the request/response using
`HttpEntity` types. Controllers returning `ResponseEntity` can include HTTP caching information
in responses like this:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping("/book/{id}")
@GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id) {
Book book = findBook(id);