你可以使用@RequestMapping
注解來將請求URL,如/appointments
等,映射到整個類上或某個特定的處理器方法上。一般來說,類級別的注解負(fù)責(zé)將一個特定(或符合某種模式)的請求路徑映射到一個控制器上,同時通過方法級別的注解來細(xì)化映射,即根據(jù)特定的HTTP請求方法(“GET”“POST”方法等)、HTTP請求中是否攜帶特定參數(shù)等條件,將請求映射到匹配的方法上。
下面這段代碼示例來自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
注解。第一次使用點(diǎn)是作用于類級別的,它指示了所有/appointments
開頭的路徑都會被映射到控制器下。get()
方法上的@RequestMapping
注解對請求路徑進(jìn)行了進(jìn)一步細(xì)化:它僅接受GET方法的請求。這樣,一個請求路徑為/appointments
、HTTP方法為GET的請求,將會最終進(jìn)入到這個方法被處理。add()
方法也做了類似的細(xì)化,而getNewForm()
方法則同時注解了能夠接受的請求的HTTP方法和路徑。這種情況下,一個路徑為appointments/new
、HTTP方法為GET的請求將會被這個方法所處理。
getForDay()
方法則展示了使用@RequestMapping
注解的另一個技巧:URI模板。(關(guān)于URI模板,請見下小節(jié))
類級別的@RequestMapping
注解并不是必須的。不配置的話則所有的路徑都是絕對路徑,而非相對路徑。以下的代碼示例來自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());
}
}
以上代碼沒有指定請求必須是GET方法還是PUT/POST或其他方法,@RequestMapping
注解默認(rèn)會映射所有的HTTP請求方法。如果僅想接收某種請求方法,請?jiān)谧⒔庵兄付ㄖ?code>@RequestMapping(method=GET)以縮小范圍。
有時,我們希望在運(yùn)行時使用AOP代理來裝飾控制器,比如當(dāng)你直接在控制器上使用@Transactional
注解時。這種情況下,我們推薦使用類級別(在控制器上使用)的代理方式。這一般是代理控制器的默認(rèn)做法。如果控制器必須實(shí)現(xiàn)一些接口,而該接口又不支持Spring Context的回調(diào)(比如InitializingBean
, *Aware
等接口),那要配置類級別的代理就必須手動配置了。比如,原來的配置文件<tx:annotation-driven/>
需要顯式配置為<tx:annotation-driven proxy-target-class="true"/>
。
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中新增了一組類用以增強(qiáng)@RequestMapping
,分別是RequestMappingHandlerMapping
和RequestMappingHandlerAdapter
。我們推薦你用一用。有部分Spring MVC 3.1之后新增的特性,這兩個注解甚至是必須的。在MVC命名空間和MVC Java編程配置方式下,這組類及其新特性默認(rèn)是開啟的。但若你使用其他配置方式,則該特性必須手動配置才能使用。本小節(jié)將簡要介紹一下,新類相比之前的一些重要變化。
在Spring 3.1之前,框架會在兩個不同的階段分別檢查類級別和方法級別的請求映射——首先,DefaultAnnotationHanlderMapping
會先在類級別上選中一個控制器,然后再通過AnnotationMethodHandlerAdapter
定位到具體要調(diào)用的方法。
[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.
現(xiàn)在有了Spring 3.1后引入的這組新類,RequestMappingHandlerMapping
成為了這兩個決策實(shí)際發(fā)生的唯一一個地方。你可以把控制器中的一系列處理方法當(dāng)成是一系列獨(dú)立的服務(wù)節(jié)點(diǎn),每個從類級別和方法級別的@RequestMapping
注解中獲取到足夠請求1路徑映射信息。
[Original] This enables some new possibilities. For once a
HandlerInterceptor
or aHandlerExceptionResolver
can now expect the Object-based handler to be aHandlerMethod
, 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
現(xiàn)在可以確定拿到的這個處理器肯定是一個HandlerMethod
類型,因此它能夠精確地了解這個方法的所有信息,包括它的參數(shù)、應(yīng)用于其上的注解等。這樣,內(nèi)部對于一個URL的處理流程再也不需要分隔到不同的控制器里面去執(zhí)行了。
[Original] There are also several things no longer possible: [Original] Select a controller first with a
SimpleUrlHandlerMapping
orBeanNameUrlHandlerMapping
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 don’t 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
來拿到負(fù)責(zé)處理請求的控制器,然后通過@RequestMapping
注解配置的信息來定位到具體的處理方法;@RequestMapping
的方法除了方法名稱擁有完全相同的URL映射和HTTP請求方法。在新版本下,@RequestMapping
注解的方法必須具有唯一的請求映射;[Original] The above features are still supported with the existing support classes. However to take advantage of new Spring MVC 3.1 features you’ll need to use the new support classes.
如果使用原來的類,以上的功能還是可以做到。但是,如果要享受Spring MVC 3.1版本帶來的方便特性,你就需要去使用新的類。
[Original] ## URI Template Patterns
[Original] URI templates can be used for convenient access to selected parts of a URL in a
@RequestMapping
method.
URI模板可以為快速訪問@RequestMapping
中指定的URL的一個特定的部分提供很大的便利。
[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 yieldshttp://www.example.com/users/fred
.
URI模板是一個類似于URI的字符串,只不過其中包含了一個或多個的變量名。當(dāng)你使用實(shí)際的值去填充這些變量名的時候,模板就退化成了一個URI。在URI模板的RFC提議中定義了一個URI是如何進(jìn)行參數(shù)化的。比如說,一個這個URI模板http://www.example.com/users/{userId}
就包含了一個變量名userId。將值fred賦給這個變量名后,它就變成了一個URI:http://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中你可以在方法參數(shù)上使用@PathVariable
注解,將其與URI模板中的參數(shù)綁定起來:
@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 nameownerId
. When the controller handles this request, the value ofownerId
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 ofownerId
isfred
.
URI模板"/owners/{ownerId}
"指定了一個變量,名為ownerId
。當(dāng)控制器處理這個請求的時候,ownerId
的值就會被URI模板中對應(yīng)部分的值所填充。比如說,如果請求的URI是/owners/fred
,此時變量ownerId
的值就是fred
. `
為了處理
@PathVariables
注解,Spring MVC必須通過變量名來找到URI模板中相對應(yīng)的變量。你可以在注解中直接聲明:@RequestMapping(path="/owners/{ownerId}}", method=RequestMethod.GET) public String findOwner(@PathVariable("ownerId") String theOwner, Model model) { // 具體的方法代碼… }
或者,如果URI模板中的變量名與方法的參數(shù)名是相同的,則你可以不必再指定一次。只要你在編譯的時候留下debug信息,Spring MVC就可以自動匹配URL模板中與方法參數(shù)名相同的變量名。
@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:
一個方法可以擁有任意數(shù)量的@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 aMap<String, String>
argument, the map is populated with all URI template variables.
當(dāng)@PathVariable
注解被應(yīng)用于Map<String, String>
類型的參數(shù)上時,框架會使用所有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 注解獲取數(shù)據(jù)。因此,像這樣的findPet()
方法可以被類似于/owners/42/pets/21
這樣的URL路由并調(diào)用到:
_@Controller_
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping("/pets/{petId}")
public void findPet(_@PathVariable_ String ownerId, _@PathVariable_ String petId, Model model) {
// 方法實(shí)現(xiàn)體這里忽略
}
}
[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 aTypeMismatchException
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
可以被應(yīng)用于所有 簡單類型 的參數(shù)上,比如int、long、Date等類型。Spring會自動地幫你把參數(shù)轉(zhuǎn)化成合適的類型,如果轉(zhuǎn)換失敗,就拋出一個TypeMismatchException
。如果你需要處理其他數(shù)據(jù)類型的轉(zhuǎn)換,也可以注冊自己的類。若需要更詳細(xì)的信息可以參考“方法參數(shù)與類型轉(zhuǎn)換”一節(jié)和“定制WebDataBinder初始化過程”一節(jié)
[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?
有時候你可能需要更準(zhǔn)確地描述一個URI模板的變量,比如說這個URL:"/spring-web/spring-web-3.0.5.jar
。你要怎么把它分解成幾個有意義的部分呢?
[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模板變量中使用正則表達(dá)式。語法是{varName:regex}
,其中第一部分定義了變量名,第二部分就是你所要應(yīng)用的正則表達(dá)式。比如下面的代碼樣例:
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String extension) {
// 代碼部分省略...
}
}
[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風(fēng)格的路徑模式(如/myPath/*.do
等)。不僅如此,還可以把URI模板變量和Ant風(fēng)格的glob組合起來使用(比如/owners/*/pets/{petId}
這樣的用法等)。
[Original] When a URL matches multiple patterns, a sort is used to find the most specific match.
當(dāng)一個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模板變量的數(shù)目和通配符數(shù)量的總和最少的那個路徑模板更準(zhǔn)確。舉個例子,/hotels/{hotel}/*
這個路徑擁有一個URI變量和一個通配符,而/hotels/{hotel}/**
這個路徑則擁有一個URI變量和兩個通配符,因此,我們認(rèn)為前者是更準(zhǔn)確的路徑模板。
[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模板數(shù)量和通配符數(shù)量總和一致,則路徑更長的那個模板更準(zhǔn)確。舉個例子,/foo/bar*
就被認(rèn)為比/foo/*
更準(zhǔn)確,因?yàn)榍罢叩穆窂礁L。
[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/*
.
如果兩個模板的數(shù)量和長度均一致,則那個具有更少通配符的模板是更加準(zhǔn)確的。比如,/hotels/{hotel}
就比/hotels/*
更精確。
[Original] There are also some additional special rules:
除此之外,還有一些其他的規(guī)則:
[Original] The default mapping pattern `/*
is less specific than any other pattern. For example
/api/{a}//{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}//{c}` is more specific.
/**
比其他所有的模式都更“不準(zhǔn)確”。比方說,/api/{a}//{c}
就比默認(rèn)的通配模式/**
要更準(zhǔn)確/public/**
)被認(rèn)為比其他任何不包括雙通配符的模式更不準(zhǔn)確。比如說,/public/path3/{a}//{c}
就比/public/**
更準(zhǔn)確[Original] For the full details see
AntPatternComparator
inAntPathMatcher
. Note that the PathMatcher can be customized (see Section 21.16.11, "Path Matching" in the section on configuring Spring MVC).
更多的細(xì)節(jié)請參考這兩個類:AntPatternComparator
和AntPathMatcher
。值得一提的是,PathMatcher類是可以配置的(見“配置Spring MVC”一節(jié)中的路徑的匹配一節(jié))。
[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 thePropertyPlaceholderConfigurer
class.
@RequestMapping
注解支持在路徑中使用占位符,以取得一些本地配置、系統(tǒng)配置、環(huán)境變量等。這個特性有時很有用,比如說控制器的映射路徑需要通過配置來定制的場景。如果想了解更多關(guān)于占位符的信息,可以參考PropertyPlaceholderConfigurer
這個類的文檔。
[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默認(rèn)采用".*"
的后綴模式匹配來進(jìn)行路徑匹配,因此,一個映射到/person
路徑的控制器也會隱式地被映射到/person.*
。這使得通過URL來請求同一資源文件的不同格式變得更簡單(比如/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/joe@email.com
vs/person/joe@email.com.json)
. 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.
你可以關(guān)閉默認(rèn)的后綴模式匹配,或者顯式地將路徑后綴限定到一些特定格式上for content negotiation purpose。我們推薦這樣做,這樣可以減少映射請求時可以帶來的一些二義性,比如請求以下路徑/person/{id}
時,路徑中的點(diǎn)號后面帶的可能不是描述內(nèi)容格式,比如/person/joe@email.com
vs /person/joe@email.com.json
。而且正如下面馬上要提到的,后綴模式通配以及內(nèi)容協(xié)商有時可能會被黑客用來進(jìn)行攻擊,因此,對后綴通配進(jìn)行有意義的限定是有好處的。
[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.
關(guān)于后綴模式匹配的配置問題,可以參考Spring MVC路徑匹配配置;關(guān)于內(nèi)容協(xié)商的配置問題,可以參考Spring MVC 內(nèi)容協(xié)商"的內(nèi)容。
[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)攻擊最先是2014年在Trustwave的一篇論文中被提出的。它與XSS攻擊有些相似,因?yàn)檫@種攻擊方式也依賴于某些特征,即需要你的輸入(比如查詢參數(shù),URI變量等)等也在輸出(response)中以某種形式出現(xiàn)。不同的是,RFD攻擊并不是通過在HTML中寫入JavaScript代碼進(jìn)行,而是依賴于瀏覽器來跳轉(zhuǎn)到下載頁面,并把特定格式(比如.bat,.cmd等)的response當(dāng)成是可執(zhí)行腳本,雙擊它就會執(zhí)行。
[Original] In Spring MVC
@ResponseBody
andResponseEntity
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
方法是有風(fēng)險的,因?yàn)樗鼈儠鶕?jù)客戶的請求——包括URL的路徑后綴,來渲染不同的內(nèi)容類型。因此,禁用后綴模式匹配或者禁用僅為內(nèi)容協(xié)商開啟的路徑文件后綴名攜帶,都是防范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更高級的保護(hù)模式,可以在Spring MVC渲染開始請求正文之前,在請求頭中增加一行配置Content-Disposition:inline;filename=f.txt
,指定固定的下載文件的文件名。這僅在URL路徑中包含了一個文件符合以下特征的拓展名時適用:該擴(kuò)展名既不在信任列表(白名單)中,也沒有被顯式地被注冊于內(nèi)容協(xié)商時使用。并且這種做法還可以有一些副作用,比如,當(dāng)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".
很多常用的路徑文件后綴默認(rèn)是被信任的。另外,REST的API一般是不應(yīng)該直接用做URL的。不過,你可以自己定制HttpMessageConverter
的實(shí)現(xiàn),然后顯式地注冊用于內(nèi)容協(xié)商的文件類型,這種情形下Content-Disposition頭將不會被加入到請求頭中。詳見Spring MVC 內(nèi)容協(xié)商。
[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.
感覺這節(jié)的翻譯質(zhì)量還有限,需要繼續(xù)了解XSS攻擊和RFD攻擊的細(xì)節(jié)再翻。
[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規(guī)范RFC 3986中允許在路徑段落中攜帶鍵值對,但規(guī)范沒有明確給這樣的鍵值對定義術(shù)語。有人叫“URI路徑參數(shù)”,也有叫“矩陣URI”的。后者是Tim Berners-Lee首先在其博客中提到的術(shù)語,被使用得要更加頻繁一些,知名度也更高些。而在Spring MVC中,我們稱這樣的鍵值對為矩陣變量。
[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"
.
矩陣變量可以在任何路徑段落中出現(xiàn),每對矩陣變量之間使用一個分號“;”隔開。比如這樣的URI:"/cars;color=red;year=2012"
。多個值可以用逗號隔開"color=red,green,blue"
,或者重復(fù)變量名多次"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模板來體現(xiàn)這一點(diǎn)。這樣才能確保請求可以被正確地映射,而不管矩陣變量在URI中是否出現(xiàn)、出現(xiàn)的次序是怎樣等。
[Original] Below is an example of extracting the matrix variable "q":
下面是一個例子,展示了我們?nèi)绾螐木仃囎兞恐蝎@取到變量“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:
由于任意路徑段落中都可以含有矩陣變量,在某些場景下,你需要用更精確的信息來指定一個矩陣變量的位置:
// 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:
你也可以聲明一個矩陣變量不是必須出現(xiàn)的,并給它賦一個默認(rèn)值:
// 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
removeSemicolonContent
property ofRequestMappingHandlerMapping
tofalse
. By default it is set totrue
.
如果要允許矩陣變量的使用,你必須把RequestMappingHandlerMapping
類的removeSemicolonContent
屬性設(shè)置為false
。該值默認(rèn)是true
的。
[Original] The MVC Java config and the MVC namespace both provide options for enabling the use of matrix variables.
MVC的Java編程配置和命名空間配置都提供了啟用矩陣變量的方式。
[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高級定制化配置”一節(jié)描述了如何對
RequestMappingHandlerMapping
進(jìn)行定制。[Original] In the MVC namespace, the
<mvc:annotation-driven>
element has anenable-matrix-variables
attribute that should be set totrue
. By default it is set tofalse
.而使用MVC的命名空間配置時,你可以把
<mvc:annotation-driven>
元素下的enable-matrix-variables
屬性設(shè)置為true
。該值默認(rèn)情況下是配置為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:
你可以指定一組可消費(fèi)的媒體類型,縮小映射的范圍。這樣只有當(dāng)請求頭中 Content-Type 的值與指定可消費(fèi)的媒體類型中有相同的時候,請求才會被匹配。比如下面這個例子:
@Controller
@RequestMapping(path = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
// 方法實(shí)現(xiàn)省略
}
[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 asAPPLICATION_JSON_VALUE
andAPPLICATION_JSON_UTF8_VALUE
.
指定可消費(fèi)媒體類型的表達(dá)式中還可以使用否定,比如,可以使用 !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 屬性提供的是方法級的類型支持。與其他屬性不同,當(dāng)在類型級使用時,方法級的消費(fèi)類型將覆蓋類型級的配置,而非繼承關(guān)系。
[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:
你可以指定一組可生產(chǎn)的媒體類型,縮小映射的范圍。這樣只有當(dāng)請求頭中 Accept 的值與指定可生產(chǎn)的媒體類型中有相同的時候,請求才會被匹配。而且,使用 produces 條件可以確保用于生成響應(yīng)(response)的內(nèi)容與指定的可生產(chǎn)的媒體類型是相同的。舉個例子:
@Controller
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// 方法實(shí)現(xiàn)省略
}
[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 theUTF-8
charset.要注意的是,通過 condition 條件指定的媒體類型也可以指定字符集。比如在上面的小段代碼中,我們還是覆寫了
MappingJackson2HttpMessageConverter
類中默認(rèn)配置的媒體類型,同時,還指定了使用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 asAPPLICATION_JSON_VALUE
andAPPLICATION_JSON_UTF8_VALUE
.
與 consumes 條件類似,可生產(chǎn)的媒體類型表達(dá)式也可以使用否定。比如,可以使用 !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 屬性提供的是方法級的類型支持。與其他屬性不同,當(dāng)在類型級使用時,方法級的消費(fèi)類型將覆蓋類型級的配置,而非繼承關(guān)系。
[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:
你可以篩選請求參數(shù)的條件來縮小請求匹配范圍,比如"myParam"
、"!myParam"
及"myParam=myValue"
等。前兩個條件用于篩選存在/不存在某些請求參數(shù)的請求,第三個條件篩選具有特定參數(shù)值的請求。下面有個例子,展示了如何使用請求參數(shù)值的篩選條件:
@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) {
// 實(shí)際實(shí)現(xiàn)省略
}
}
[Original] The same can be done to test for request header presence/absence or to match based on a specific request header value:
同樣,你可以用相同的條件來篩選請求頭的出現(xiàn)與否,或者篩選出一個具有特定值的請求頭:
@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) {
// 方法體實(shí)現(xiàn)省略
}
}
[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的值,但我們更推薦獨(dú)立使用 consumes和 produces條件來篩選各自的請求。因?yàn)樗鼈兙褪菍iT為區(qū)分這兩種不同的場景而生的。
更多建議: