添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

You can use the @RequestMapping annotation to map requests to controllers methods. It has various attributes to match by URL, HTTP method, request parameters, headers, and media types. You can use it at the class level to express shared mappings or at the method level to narrow down to a specific endpoint mapping.

There are also HTTP method specific shortcut variants of @RequestMapping :

The shortcuts are Custom Annotations that are provided because, arguably, most controller methods should be mapped to a specific HTTP method versus using @RequestMapping , which, by default, matches to all HTTP methods. A @RequestMapping is still needed at the class level to express shared mappings.

@RequestMapping cannot be used in conjunction with other @RequestMapping annotations that are declared on the same element (class, interface, or method). If multiple @RequestMapping annotations are detected on the same element, a warning will be logged, and only the first mapping will be used. This also applies to composed @RequestMapping annotations such as @GetMapping , @PostMapping , etc. @PostMapping @ResponseStatus(HttpStatus.CREATED) public void add(@RequestBody Person person) { // ...

PathPattern — a pre-parsed pattern matched against the URL path also pre-parsed as PathContainer . Designed for web use, this solution deals effectively with encoding and path parameters, and matches efficiently.

AntPathMatcher — match String patterns against a String path. This is the original solution also used in Spring configuration to select resources on the classpath, on the filesystem, and other locations. It is less efficient and the String path input is a challenge for dealing effectively with encoding and other issues with URLs.

PathPattern is the recommended solution for web applications and it is the only choice in Spring WebFlux. It was enabled for use in Spring MVC from version 5.3 and is enabled by default from version 6.0. See MVC config for customizations of path matching options.

PathPattern supports the same pattern syntax as AntPathMatcher . In addition, it also supports the capturing pattern, e.g. {*spring} , for matching 0 or more path segments at the end of a path. PathPattern also restricts the use of ** for matching multiple path segments such that it’s only allowed at the end of a pattern. This eliminates many cases of ambiguity when choosing the best matching pattern for a given request. For full pattern syntax please refer to PathPattern and AntPathMatcher .

Some example patterns:

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
	// ...
@GetMapping("/owners/{ownerId}/pets/{petId}")
fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
	// ...
	@GetMapping("/pets/{petId}")
	public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
		// ...
	@GetMapping("/pets/{petId}")
	fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
		// ...

URI variables are automatically converted to the appropriate type, or TypeMismatchException is raised. Simple types (int, long, Date, and so on) are supported by default and you can register support for any other data type. See Type Conversion and DataBinder.

You can explicitly name URI variables (for example, @PathVariable("customId")), but you can leave that detail out if the names are the same and your code is compiled with the -parameters compiler flag.

The syntax {varName:regex} declares a URI variable with a regular expression that has syntax of {varName:regex}. For example, given URL "/spring-web-3.0.5.jar", the following method extracts the name, version, and file extension:

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
	// ...
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
fun handle(@PathVariable name: String, @PathVariable version: String, @PathVariable ext: String) {
	// ...

URI path patterns can also have embedded ${…​} placeholders that are resolved on startup by using PropertySourcesPlaceholderConfigurer against local, system, environment, and other property sources. You can use this, for example, to parameterize a base URL based on some external configuration.

Both help to sort patterns with more specific ones on top. A pattern is more specific if it has a lower count of URI variables (counted as 1), single wildcards (counted as 1), and double wildcards (counted as 2). Given an equal score, the longer pattern is chosen. Given the same score and length, the pattern with more URI variables than wildcards is chosen.

The default mapping pattern (/**) is excluded from scoring and always sorted last. Also, prefix patterns (such as /public/**) are considered less specific than other pattern that do not have double wildcards.

For the full details, follow the above links to the pattern Comparators.

Starting in 5.3, by default Spring MVC no longer performs .* suffix pattern matching where a controller mapped to /person is also implicitly mapped to /person.*. As a consequence path extensions are no longer used to interpret the requested content type for the response — for example, /person.pdf, /person.xml, and so on.

Using file extensions in this way was necessary when browsers used to send Accept headers that were hard to interpret consistently. At present, that is no longer a necessity and using the Accept header should be the preferred choice.

Over time, the use of file name extensions has proven problematic in a variety of ways. It can cause ambiguity when overlain with the use of URI variables, path parameters, and URI encoding. Reasoning about URL-based authorization and security (see next section for more details) also becomes more difficult.

To completely disable the use of path extensions in versions prior to 5.3, set the following:

Having a way to request content types other than through the "Accept" header can still be useful, e.g. when typing a URL in a browser. A safe alternative to path extensions is to use the query parameter strategy. If you must use file extensions, consider restricting them to a list of explicitly registered extensions through the mediaTypes property of ContentNegotiationConfigurer.

A reflected file download (RFD) attack is similar to XSS in that it relies on request input (for example, a query parameter and a URI variable) being reflected in the response. However, instead of inserting JavaScript into HTML, an RFD attack relies on the browser switching to perform a download and treating the response as an executable script when double-clicked later.

In Spring MVC, @ResponseBody and ResponseEntity methods are at risk, because they can render different content types, which clients can request through URL path extensions. Disabling suffix pattern matching and using path extensions for content negotiation lower the risk but are not sufficient to prevent RFD attacks.

To prevent RFD attacks, prior to rendering the response body, Spring MVC adds a Content-Disposition:inline;filename=f.txt header to suggest a fixed and safe download file. This is done only if the URL path contains a file extension that is neither allowed as safe nor explicitly registered for content negotiation. However, it can potentially have side effects when URLs are typed directly into a browser.

Many common path extensions are allowed as safe by default. Applications with custom HttpMessageConverter implementations can explicitly register file extensions for content negotiation to avoid having a Content-Disposition header added for those extensions. See Content Types.

See CVE-2015-5211 for additional recommendations related to RFD.

@PostMapping(path = "/pets", consumes = "application/json") (1)
public void addPet(@RequestBody Pet pet) {
	// ...
@PostMapping("/pets", consumes = ["application/json"]) (1)
fun addPet(@RequestBody pet: Pet) {
	// ...

The consumes attribute also supports negation expressions — for example, !text/plain means any content type other than text/plain.

You can declare a shared consumes attribute at the class level. Unlike most other request-mapping attributes, however, when used at the class level, a method-level consumes attribute overrides rather than extends the class-level declaration.

@GetMapping(path = "/pets/{petId}", produces = "application/json") (1)
@ResponseBody
public Pet getPet(@PathVariable String petId) {
	// ...
@GetMapping("/pets/{petId}", produces = ["application/json"]) (1)
@ResponseBody
fun getPet(@PathVariable petId: String): Pet {
	// ...

The media type can specify a character set. Negated expressions are supported — for example, !text/plain means any content type other than "text/plain".

You can declare a shared produces attribute at the class level. Unlike most other request-mapping attributes, however, when used at the class level, a method-level produces attribute overrides rather than extends the class-level declaration.

You can narrow request mappings based on request parameter conditions. You can test for the presence of a request parameter (myParam), for the absence of one (!myParam), or for a specific value (myParam=myValue). The following example shows how to test for a specific value:

@GetMapping(path = "/pets/{petId}", params = "myParam=myValue") (1)
public void findPet(@PathVariable String petId) {
	// ...
@GetMapping("/pets/{petId}", params = ["myParam=myValue"]) (1)
fun findPet(@PathVariable petId: String) {
	// ...
@GetMapping(path = "/pets/{petId}", headers = "myHeader=myValue") (1)
public void findPet(@PathVariable String petId) {
	// ...
@GetMapping("/pets/{petId}", headers = ["myHeader=myValue"]) (1)
fun findPet(@PathVariable petId: String) {
	// ...
You can match Content-Type and Accept with the headers condition, but it is better to use
consumes and produces
instead.

@GetMapping (and @RequestMapping(method=HttpMethod.GET)) support HTTP HEAD transparently for request mapping. Controller methods do not need to change. A response wrapper, applied in jakarta.servlet.http.HttpServlet, ensures a Content-Length header is set to the number of bytes written (without actually writing to the response).

By default, HTTP OPTIONS is handled by setting the Allow response header to the list of HTTP methods listed in all @RequestMapping methods that have matching URL patterns.

For a @RequestMapping without HTTP method declarations, the Allow header is set to GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS. Controller methods should always declare the supported HTTP methods (for example, by using the HTTP method specific variants: @GetMapping, @PostMapping, and others).

You can explicitly map the @RequestMapping method to HTTP HEAD and HTTP OPTIONS, but that is not necessary in the common case.

Spring MVC supports the use of composed annotations for request mapping. Those are annotations that are themselves meta-annotated with @RequestMapping and composed to redeclare a subset (or all) of the @RequestMapping attributes with a narrower, more specific purpose.

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, and @PatchMapping are examples of composed annotations. They are provided because, arguably, most controller methods should be mapped to a specific HTTP method versus using @RequestMapping, which, by default, matches to all HTTP methods. If you need an example of how to implement a composed annotation, look at how those are declared.

@RequestMapping cannot be used in conjunction with other @RequestMapping annotations that are declared on the same element (class, interface, or method). If multiple @RequestMapping annotations are detected on the same element, a warning will be logged, and only the first mapping will be used. This also applies to composed @RequestMapping annotations such as @GetMapping, @PostMapping, etc.

Spring MVC also supports custom request-mapping attributes with custom request-matching logic. This is a more advanced option that requires subclassing RequestMappingHandlerMapping and overriding the getCustomMethodCondition method, where you can check the custom attribute and return your own RequestCondition.

You can programmatically register handler methods, which you can use for dynamic registrations or for advanced cases, such as different instances of the same handler under different URLs. The following example registers a handler method:

@Autowired public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) (1) throws NoSuchMethodException { RequestMappingInfo info = RequestMappingInfo .paths("/user/{id}").methods(RequestMethod.GET).build(); (2) Method method = UserHandler.class.getMethod("getUser", Long.class); (3) mapping.registerMapping(info, handler, method); (4) @Autowired fun setHandlerMapping(mapping: RequestMappingHandlerMapping, handler: UserHandler) { (1) val info = RequestMappingInfo.paths("/user/{id}").methods(RequestMethod.GET).build() (2) val method = UserHandler::class.java.getMethod("getUser", Long::class.java) (3) mapping.registerMapping(info, handler, method) (4)

While the main purpose of @HttpExchange is to abstract HTTP client code with a generated proxy, the HTTP Interface on which such annotations are placed is a contract neutral to client vs server use. In addition to simplifying client code, there are also cases where an HTTP Interface may be a convenient way for servers to expose their API for client access. This leads to increased coupling between client and server and is often not a good choice, especially for public API’s, but may be exactly the goal for an internal API. It is an approach commonly used in Spring Cloud, and it is why @HttpExchange is supported as an alternative to @RequestMapping for server side handling in controller classes.

For example:

class PersonController implements PersonService { public Person getPerson(@PathVariable Long id) { // ... @ResponseStatus(HttpStatus.CREATED) public void add(@RequestBody Person person) { // ... class PersonController : PersonService { override fun getPerson(@PathVariable id: Long): Person { // ... @ResponseStatus(HttpStatus.CREATED) override fun add(@RequestBody person: Person) { // ...

@HttpExchange and @RequestMapping have differences. @RequestMapping can map to any number of requests by path patterns, HTTP methods, and more, while @HttpExchange declares a single endpoint with a concrete HTTP method, path, and content types.

For method parameters and returns values, generally, @HttpExchange supports a subset of the method parameters that @RequestMapping does. Notably, it excludes any server-side specific parameter types. For details, see the list for @HttpExchange and @RequestMapping.

Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™ are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.