Back to Javatutorial

Spring MVC ʹ@Controllerעⶨһ

docs/Spring全家桶/SpringMVC/SpringMVC中的常用功能.md

1.0.030.4 KB
Original Source

Spring MVC ʹ@Controllerעⶨһ

2018-07-26 14:02

<section>

[Original] The @Controller annotation indicates that a particular class serves the role of a controller. Spring does not require you to extend any controller base class or reference the Servlet API. However, you can still reference Servlet-specific features if you need to.

@ControllerעһΪĽɫڵġSpringҪȥ̳κο࣬ҲҪȥʵServletAPIȻҪĻҲȥʹκServletصԺʩ

[Original] The @Controller annotation acts as a stereotype for the annotated class, indicating its role. The dispatcher scans such annotated classes for mapped methods and detects @RequestMapping annotations (see the next section).

@ControllerעΪDZעԭͣstereotypeеĽɫDispatcherServletɨע@Controller࣬ͨ@RequestMappingעõķһСڣ

[Original] You can define annotated controller beans explicitly, using a standard Spring bean definition in the dispatchers context. However, the @Controller stereotype also allows for autodetection, aligned with Spring general support for detecting component classes in the classpath and auto-registering bean definitions for them.

ȻҲԲʹ@Controllerעʽȥ屻עbeanͨ׼Spring beanĶ巽ʽdispatherü@ControllerԭǿԱԶģSpring֧classpath·Զ⣬ԼѶbeanԶעᡣ

[Original] To enable autodetection of such annotated controllers, you add component scanning to your configuration. Use the spring-context schema as shown in the following XML snippet:

ҪмɨôܶעԶ⡣ʹXMLʾspring-context schema

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.springframework.samples.petclinic.web"/>

    <!-- ... -->

</beans>
</section>

Spring MVC ʹ@RequestMappingעӳ·

2018-07-26 15:29

ʹ@RequestMappingעURL/appointmentsȣӳ䵽ϻijضĴϡһ˵༶ע⸺һضijģʽ·ӳ䵽һϣͬʱͨעϸӳ䣬ضHTTP󷽷GETPOSTȣHTTPǷЯضӳ䵽ƥķϡ

<section>

δʾPetcareչʾSpring MVCڿʹ@RequestMappingע⣺

@Controller
@RequestMapping("/appointments")
public class AppointmentsController {

    private final AppointmentBook appointmentBook;

    @Autowired
    public AppointmentsController(AppointmentBook appointmentBook) {
        this.appointmentBook = appointmentBook;
    }

    @RequestMapping(method = RequestMethod.GET)
    public Map<String, Appointment> get() {
        return appointmentBook.getAppointmentsForToday();
    }

    @RequestMapping(path = "/{day}", method = RequestMethod.GET)
    public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
        return appointmentBook.getAppointmentsForDay(day);
    }

    @RequestMapping(path = "/new", method = RequestMethod.GET)
    public AppointmentForm getNewForm() {
        return new AppointmentForm();
    }

    @RequestMapping(method = RequestMethod.POST)
    public String add(@Valid AppointmentForm appointment, BindingResult result) {
        if (result.hasErrors()) {
            return "appointments/new";
        }
        appointmentBook.addAppointment(appointment);
        return "redirect:/appointments";
    }
}

ʾУطʹõ@RequestMappingע⡣һʹõ༶ģָʾ/appointmentsͷ·ᱻӳ䵽¡get()ϵ@RequestMappingע·˽һϸGETһ·Ϊ/appointmentsHTTPΪGET󣬽ս뵽add()ҲƵϸgetNewForm()ͬʱעܹܵHTTP·£һ·Ϊappointments/newHTTPΪGET󽫻ᱻ

getForDay()չʾʹ@RequestMappingעһɣURIģ塣URIģ壬Сڣ

@RequestMappingעⲢDZġõĻе·Ǿ··µĴʾPetClinicչʾһжĿ

@Controller
public class ClinicController {

    private final Clinic clinic;

    @Autowired
    public ClinicController(Clinic clinic) {
        this.clinic = clinic;
    }

    @RequestMapping("/")
    public void welcomeHandler() {
    }

    @RequestMapping("/vets")
    public ModelMap vetsHandler() {
        return new ModelMap(this.clinic.getVets());
    }
}

ϴûָGETPUT/POST@RequestMappingעĬϻӳеHTTP󷽷ij󷽷עָ֮@RequestMapping(method=GET)СΧ

@Controller棨AOP

ʱϣʱʹAOPװο統ֱڿʹ@Transactionalעʱ£Ƽʹ༶ڿʹãĴʽһǴĬʵһЩӿڣýӿֲ֧Spring ContextĻصInitializingBean, *AwareȽӿڣҪ༶Ĵͱֶˡ磬ԭļ<tx:annotation-driven/>ҪʽΪ<tx:annotation-driven proxy-target-/>

Spring MVC 3.1֧@RequestMappingһЩ

They are recommended for use and even required to take advantage of new features in Spring MVC 3.1 and going forward.

Spring 3.1һǿ@RequestMappingֱRequestMappingHandlerMapping``RequestMappingHandlerAdapterƼһáвSpring MVC 3.1֮ԣעDZġMVCռMVC Java÷ʽ£༰Ĭǿġʹ÷ʽԱֶòʹáСڽҪһ£֮ǰһЩҪ仯

Spring 3.1֮ǰܻͬĽ׶ηֱ༶ͷӳ䡪ȣDefaultAnnotationHanlderMapping༶ѡһȻͨAnnotationMethodHandlerAdapterλҪõķ

[Original] With the new support classes in Spring 3.1, the RequestMappingHandlerMapping is the only place where a decision is made about which method should process the request. Think of controller methods as a collection of unique endpoints with mappings for each method derived from type and method-level @RequestMapping information.

Spring 3.1࣬RequestMappingHandlerMappingΪʵʷΨһһط԰ѿеһϵдһϵжķڵ㣬ÿ༶ͷ@RequestMappingעлȡ㹻1·ӳϢ

[Original] This enables some new possibilities. For once a HandlerInterceptor or a HandlerExceptionResolver can now expect the Object-based handler to be a HandlerMethod, which allows them to examine the exact method, its parameters and associated annotations. The processing for a URL no longer needs to be split across different controllers.

µĴʽµĿԡ֮ǰHandlerInterceptor``HandlerExceptionResolverڿȷõ϶һHandlerMethodܹͣȷ˽ϢIJӦϵעȡڲһURLĴҲҪָͬĿȥִˡ

[Original] There are also several things no longer possible: [Original] _Select a controller first with a SimpleUrlHandlerMapping or BeanNameUrlHandlerMapping and then narrow the method based on @RequestMapping annotations. [Original] _Rely on method names as a fall-back mechanism to disambiguate between two @RequestMapping methods that dont have an explicit path mapping URL path but otherwise match equally, e.g. by HTTP method. In the new support classes @RequestMapping methods have to be mapped uniquely. [Original] * Have a single default method (without an explicit path mapping) with which requests are processed if no other controller method matches more concretely. In the new support classes if a matching method is not found a 404 error is raised.

ͬʱҲһЩ仯Щûôˣ

  • ͨSimpleUrlHandlerMapping``BeanNameUrlHandlerMappingõĿȻͨ@RequestMappingעõϢλĴ
  • Ϊѡı׼˵ע@RequestMappingķ˷ӵȫͬURLӳHTTP󷽷°汾£@RequestMappingעķΨһӳ䣻
  • һĬϷû·ӳ䣩·޷ӳ䵽¸ȷķȥʱΪṩĬϴ°汾У޷ΪһҵʵĴôһ404󽫱׳

[Original] The above features are still supported with the existing support classes. However to take advantage of new Spring MVC 3.1 features youll need to use the new support classes.

ʹԭ࣬ϵĹܻǿǣҪSpring MVC 3.1汾ķԣҪȥʹµࡣ

[Original] ## URI Template Patterns

URIģ

[Original] URI templates can be used for convenient access to selected parts of a URL in a @RequestMapping method.

URIģΪٷ@RequestMappingָURLһضIJṩܴı

[Original] A URI Template is a URI-like string, containing one or more variable names. When you substitute values for these variables, the template becomes a URI. The proposed RFC for URI Templates defines how a URI is parameterized. For example, the URI Template http://www.example.com/users/{userId} contains the variable userId. Assigning the value fred to the variable yields http://www.example.com/users/fred.

URIģһURIַֻаһıʹʵʵֵȥЩʱģ˻һURIURIģRFCжһURIνвġ˵һURIģhttp://www.example.com/users/{userId}Ͱһ_userId_ֵ_fred_ͱһURIhttp://www.example.com/users/fred

[Original] In Spring MVC you can use the @PathVariable annotation on a method argument to bind it to the value of a URI template variable:

Spring MVCڷʹ@PathVariableע⣬URIģеIJ

@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model model) {
    Owner owner = ownerService.findOwner(ownerId);
    model.addAttribute("owner", owner);
    return "displayOwner";
}

[Original] The URI Template "/owners/{ownerId}" specifies the variable name ownerId. When the controller handles this request, the value of ownerId is set to the value found in the appropriate part of the URI. For example, when a request comes in for /owners/fred, the value of ownerId is fred.

URIģ"/owners/{ownerId}"ָһΪownerIdʱownerIdֵͻᱻURIģжӦֵֵ䡣˵URI/owners/fredʱownerIdֵfred. `

Ϊ˴@PathVariablesע⣬Spring MVCͨҵURIģӦıעֱ

@RequestMapping(path="/owners/{ownerId}}", method=RequestMethod.GET)
public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {
    // ķ롭
}

ߣURIģеı뷽IJͬģԲָһΡֻҪڱʱdebugϢSpring MVCͿԶƥURLģ뷽ͬı

@RequestMapping(path="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model model) {
    // ķ롭
}

[Original] A method can have any number of @PathVariable annotations:

һӵ@PathVariableע⣺

@RequestMapping(path="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)
public String findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
    Owner owner = ownerService.findOwner(ownerId);
    Pet pet = owner.getPet(petId);
    model.addAttribute("pet", pet);
    return "displayPet";
}

[Original] When a @PathVariable annotation is used on a Map<String, String> argument, the map is populated with all URI template variables.

@PathVariableעⱻӦMap<String, String>͵IJʱܻʹURIģmap

[Original] A URI template can be assembled from type and path level @RequestMapping annotations. As a result the findPet() method can be invoked with a URL such as /owners/42/pets/21.

URIģԴ༶ͷ @RequestMapping עȡݡˣfindPet()Ա/owners/42/pets/21URL·ɲõ

_@Controller_
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

    @RequestMapping("/pets/{petId}")
    public void findPet(_@PathVariable_ String ownerId, _@PathVariable_ String petId, Model model) {
        // ʵ
    }

}

[Original] 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 the section called "Method Parameters And Type Conversion" and the section called "Customizing WebDataBinder initialization".

@PathVariableԱӦ __ IJϣintlongDate͡SpringԶذѲתɺʵͣתʧܣ׳һTypeMismatchExceptionҪ͵תҲעԼࡣҪϸϢԲοתһWebDataBinderʼ̡һ

ʽURIģ

[Original] Sometimes you need more precision in defining URI template variables. Consider the URL "/spring-web/spring-web-3.0.5.jar". How do you break it down into multiple parts?

ʱҪ׼ȷһURIģı˵URL"/spring-web/spring-web-3.0.5.jarҪôֽɼIJأ

[Original] 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:

@RequestMappingע֧URIģʹʽ﷨{varName:regex}еһֶ˱ڶ־ҪӦõʽĴ

@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
    public void handle(@PathVariable String version, @PathVariable String extension) {
        // 벿ʡ...
    }
}

Path Patterns÷׵ζ

[Original] In addition to URI templates, the @RequestMapping annotation also supports Ant-style path patterns (for example, /myPath/*.do). A combination of URI template variables and Ant-style globs is also supported (e.g. /owners/*/pets/{petId}).

URIģ⣬@RequestMappingע⻹֧Ant·ģʽ/myPath/*.doȣˣ԰URIģAntglobʹã/owners/*/pets/{petId}÷ȣ

·ʽƥ(Path Pattern Comparison)

[Original] When a URL matches multiple patterns, a sort is used to find the most specific match.

һURLͬʱƥģ壨patternʱǽҪһ㷨ƥһ

[Original] A pattern with a lower count of URI variables and wild cards is considered more specific. For example /hotels/{hotel}/* has 1 URI variable and 1 wild card and is considered more specific than /hotels/{hotel}/** which as 1 URI variable and 2 wild cards.

URIģĿͨܺٵǸ·ģ׼ȷٸӣ/hotels/{hotel}/*·ӵһURIһͨ/hotels/{hotel}/**·ӵһURIͨˣΪǰǸ׼ȷ·ģ塣

[Original] If two patterns have the same count, the one that is longer is considered more specific. For example /foo/bar* is longer and considered more specific than /foo/*.

ģURIģͨܺһ£·Ǹģ׼ȷٸӣ/foo/bar*ͱΪ/foo/*׼ȷΪǰߵ·

[Original] When two patterns have the same count and length, the pattern with fewer wild cards is considered more specific. For example /hotels/{hotel} is more specific than /hotels/*.

ģͳȾһ£ǸиͨģǸ׼ȷġ磬/hotels/{hotel}ͱ/hotels/*ȷ

[Original] There are also some additional special rules:

֮⣬һЩĹ

[Original] _The default mapping pattern /*_is less specific than any other pattern. For example/api/{a}/{b}/{c} is more specific.

[Original] _A prefix pattern such as /public/*_is less specific than any other pattern that doesn't contain double wildcards. For example/public/path3/{a}/{b}/{c} is more specific.

  • Ĭϵͨģʽ/**еģʽ׼ȷȷ˵/api/{a}/{b}/{c}ͱĬϵͨģʽ/**Ҫ׼ȷ
  • ǰ׺ͨ/public/**)Ϊκβ˫ͨģʽ׼ȷ˵/public/path3/{a}/{b}/{c}ͱ/public/**׼ȷ

[Original] For the full details see AntPatternComparator in AntPathMatcher. Note that the PathMatcher can be customized (see Section 21.16.11, "Path Matching" in the section on configuring Spring MVC).

ϸοࣺAntPatternComparator``AntPathMatcherֵһǣPathMatcherǿõģSpring MVCһе·ƥһ)

ռλ·ģʽpath patterns

[Original] 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 PropertyPlaceholderConfigurer class.

@RequestMappingע֧·ʹռλȡһЩáϵͳáȡʱã˵ӳ·ҪͨƵij˽ռλϢԲοPropertyPlaceholderConfigurerĵ

Suffix Pattern Matching

׺ģʽƥ

[Original] By default Spring MVC performs ".*" suffix pattern matching so that a controller mapped to /person is also implicitly mapped to /person.*. This makes it easy to request different representations of a resource through the URL path (e.g. /person.pdf, /person.xml).

Spring MVCĬϲ".*"ĺ׺ģʽƥ·ƥ䣬ˣһӳ䵽/person·ĿҲʽرӳ䵽/person.*ʹͨURLͬһԴļIJͬʽø򵥣/person.pdf``/person.xml

[Original] Suffix pattern matching can be turned off or restricted to a set of path extensions explicitly registered for content negotiation purposes. This is generally recommended to minimize ambiguity with common request mappings such as /person/{id} where a dot might not represent a file extension, e.g. /person/[email protected] vs /person/[email protected]). Furthermore as explained in the note below suffix pattern matching as well as content negotiation may be used in some circumstances to attempt malicious attacks and there are good reasons to restrict them meaningfully.

ԹرĬϵĺ׺ģʽƥ䣬ʽؽ·׺޶һЩضʽfor content negotiation purposeƼԼӳʱԴһЩԣ·/person/{id}ʱ·еĵźĿܲݸʽ/person/[email protected] vs /person/[email protected]Ҫᵽģ׺ģʽͨԼЭʱܻᱻڿйˣԺ׺ͨ޶кôġ

[Original] See Section 21.16.11, "Path Matching" for suffix pattern matching configuration and also Section 21.16.6, "Content Negotiation" for content negotiation configuration.

ں׺ģʽƥ⣬ԲοSpring MVC·ƥЭ̵⣬ԲοSpring MVC Э"ݡ

׺ģʽƥRFD

[Original] Reflected file download (RFD) attack was first described in a paper by Trustwave in 2014. The attack is similar to XSS in that it relies on input (e.g. query parameter, 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 if double-clicked based on the file extension (e.g. .bat, .cmd).

RFD(Reflected file download)2014TrustwaveһƪбġXSSЩƣΪֹʽҲijЩҪ루ѯURIȣҲresponseijʽ֡ͬǣRFDͨHTMLдJavaScriptУתҳ棬ضʽ.bat.cmdȣresponseǿִнű˫ͻִС

[Original] In Spring MVC @ResponseBody and ResponseEntity methods are at risk because they can render different content types which clients can request including via URL path extensions. Note however that neither disabling suffix pattern matching nor disabling the use of path extensions for content negotiation purposes alone are effective at preventing RFD attacks.

Spring MVC@ResponseBody``ResponseEntityзյģΪǻݿͻ󡪡URL·׺Ⱦͬ͡ˣú׺ģʽƥ߽ýΪЭ̿·ļ׺ЯǷRFDЧʽ

[Original] For comprehensive protection against RFD, 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 filename. This is done only if the URL path contains a file extension that is neither whitelisted nor explicitly registered for content negotiation purposes. However it may potentially have side effects when URLs are typed directly into a browser.

ҪRFD߼ıģʽSpring MVCȾʼ֮ǰͷһContent-Disposition:inline;filename=f.txt̶ָļļURL·аһļչʱãչȲбУҲûбʽرעЭʱʹáһЩã磬URLֶͨʱ

[Original] Many common path extensions are whitelisted by default. Furthermore REST API calls are typically not meant to be used as URLs directly in browsers. Nevertheless applications that use custom HttpMessageConverter implementations can explicitly register file extensions for content negotiation and the Content-Disposition header will not be added for such extensions. See Section 21.16.6, "Content Negotiation".

ܶೣõ·ļ׺ĬDZεġ⣬RESTAPIһDzӦֱURLġԼHttpMessageConverterʵ֣ȻʽעЭ̵ļͣContent-Dispositionͷᱻ뵽ͷСSpring MVC Э

[Original] This was originally introduced as part of work for CVE-2015-5211. Below are additional recommendations from the report:

  • Encode rather than escape JSON responses. This is also an OWASP XSS recommendation. For an example of how to do that with Spring see spring-jackson-owasp.
  • Configure suffix pattern matching to be turned off or restricted to explicitly registered suffixes only.
  • Configure content negotiation with the properties "useJaf" and "ignoreUnknownPathExtensions" set to false which would result in a 406 response for URLs with unknown extensions. Note however that this may not be an option if URLs are naturally expected to have a dot towards the end.
  • Add X-Content-Type-Options: nosniff header to responses. Spring Security 4 does this by default.

оڵķޣҪ˽XSSRFDϸٷ

[Original] The URI specification RFC 3986 defines the possibility of including name-value pairs within path segments. There is no specific term used in the spec. The general "URI path parameters" could be applied although the more unique "Matrix URIs", originating from an old post by Tim Berners-Lee, is also frequently used and fairly well known. Within Spring MVC these are referred to as matrix variables.

ԭURI淶RFC 3986·Яֵԣ淶ûȷļֵԶ˽СURI·ҲнURIġTim Berners-Lee䲩ᵽʹõҪƵһЩ֪ҲЩSpring MVCУdzļֵΪ

[Original] Matrix variables can appear in any path segment, each matrix variable separated with a ";" (semicolon). For example: "/cars;color=red;year=2012". Multiple values may be either "," (comma) separated "color=red,green,blue" or the variable name may be repeated "color=red;color=green;color=blue".

κ·г֣ÿԾ֮ʹһֺš;URI"/cars;color=red;year=2012"ֵöŸ"color=red,green,blue"ظ"color=red;color=green;color=blue"

[Original] If a URL is expected to contain matrix variables, the request mapping pattern must represent them with a URI template. This ensures the request can be matched correctly regardless of whether matrix variables are present or not and in what order they are provided.

һURLпҪô·ӳϾҪʹURIģһ㡣ȷԱȷӳ䣬ܾURIǷֵ֡Ĵȡ

[Original] Below is an example of extracting the matrix variable "q":

һӣչʾδӾлȡqֵ

// GET /pets/42;q=11;r=22

@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
public void findPet(@PathVariable String petId, @MatrixVariable int q) {

    // petId == 42
    // q == 11

}

[Original] Since all path segments may contain matrix variables, in some cases you need to be more specific to identify where the variable is expected to be:

·жԺоijЩ£ҪøȷϢָһλã

// GET /owners/42;q=11/pets/21;q=22

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
public void findPet(
    @MatrixVariable(name="q", pathVar="ownerId") int q1,
    @MatrixVariable(name="q", pathVar="petId") int q2) {

    // q1 == 11
    // q2 == 22

}

[Original] A matrix variable may be defined as optional and a default value specified:

ҲһDZֵģһĬֵ

// GET /pets/42

@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) {

    // q == 1

}

[Original] All matrix variables may be obtained in a Map:

ҲͨһMap洢еľ

// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
public void findPet(
    @MatrixVariable Map<String, String> matrixVars,
    @MatrixVariable(pathVar="petId") Map<String, String> petMatrixVars) {

    // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
    // petMatrixVars: ["q" : 11, "s" : 23]

}

[Original] Note that to enable the use of matrix variables, you must set the removeSemicolonContentproperty of RequestMappingHandlerMapping to false. By default it is set to true.

ҪʹãRequestMappingHandlerMapping``removeSemicolonContentΪfalseֵĬtrueġ

[Original] The MVC Java config and the MVC namespace both provide options for enabling the use of matrix variables.

MVCJavaúռöṩþķʽ

[Original] If you are using Java config, The Advanced Customizations with MVC Java Config section describes how the RequestMappingHandlerMapping can be customized.

ʹJava̵ķʽMVC Java߼ƻáһζRequestMappingHandlerMappingжơ

[Original] In the MVC namespace, the <mvc:annotation-driven> element has an enable-matrix-variables attribute that should be set to true. By default it is set to false.

ʹMVCռʱ԰<mvc:annotation-driven>Ԫµenable-matrix-variablesΪtrueֵĬΪfalseġ

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven enable-matrix-variables="true"/>

</beans>

ѵý

[Original] 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 media type. For example:

ָһѵýͣСӳķΧֻеͷ Content-Type ֵָѵýͬʱŻᱻƥ䡣ӣ

@Controller
@RequestMapping(path = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
    // ʵʡ
}

[Original] 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.

ָý͵ıʽлʹ÷񶨣磬ʹ !text/plain ƥͷ Content-Type в text/plain ͬʱMediaTypeлһЩAPPLICATION_JSON_VALUE``APPLICATION_JSON_UTF8_VALUEȣƼʹǡ

[Original] The consumes condition is supported on the type and on the method level. Unlike most other conditions, when used at the type level, method-level consumable types override rather than extend type-level consumable types.

consumes ṩǷ֧֡ԲͬͼʹʱͽͼãǼ̳йϵ

ý

[Original] 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 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:

ָһýͣСӳķΧֻеͷ Accept ֵָýͬʱŻᱻƥ䡣ңʹ produces ȷӦresponseָĿýͬġٸӣ

@Controller
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
    // ʵʡ
}

[Original] Be aware that the media type specified in the produces condition can also optionally specify a character set. For example, in the code snippet above we specify the same media type than the default one configured in MappingJackson2HttpMessageConverter, including the UTF-8charset.

Ҫעǣͨ condition ָýҲַָСδУǻǸдMappingJackson2HttpMessageConverterĬõýͣͬʱָʹUTF-8ַ

[Original] 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 as APPLICATION_JSON_VALUE and APPLICATION_JSON_UTF8_VALUE.

consumes ƣýͱʽҲʹ÷񶨡磬ʹ !text/plain ƥͷ Accept в text/plain ͬʱMediaTypeлһЩAPPLICATION_JSON_VALUE``APPLICATION_JSON_UTF8_VALUEȣƼʹǡ

[Original] The produces condition is supported on the type and on the method level. Unlike most other conditions, when used at the type level, method-level producible types override rather than extend type-level producible types.

produces ṩǷ֧֡ԲͬͼʹʱͽͼãǼ̳йϵ

ͷֵ

[Original] You can narrow request matching through request parameter conditions such as "myParam", "!myParam", or "myParam=myValue". The first two test for request parameter presence/absence and the third for a specific parameter value. Here is an example with a request parameter value condition:

ɸѡСƥ䷶Χ"myParam"``"!myParam"``"myParam=myValue"ȡǰɸѡ/ijЩ󣬵ɸѡضֵиӣչʾʹֵɸѡ

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

    @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")
    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
        // ʵʵʡ
    }

}

[Original] The same can be done to test for request header presence/absence or to match based on a specific request header value:

ͬͬɸѡͷij񣬻ɸѡһضֵͷ

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

    @RequestMapping(path = "/pets", method = RequestMethod.GET, headers="myHeader=myValue")
    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
        // ʵʡ
    }

}

[Original] Although you can match to Content-Type and Accept header values using media type wild cards (for example "content-type=text/*" will match to "text/plain" and "text/html"), it is recommended to use the consumes and produces conditions respectively instead. They are intended specifically for that purpose.

ܣʹý͵ͨ _"content-type=text/*"_ƥͷ Content-Type _Accept_ֵǸƼʹ consumes _produces_ɸѡԵΪǾרΪֲͬijġ

</section>