《Spring 5 官方文档》18. Web MVC 框架(二)

Spring MVC 3.1中的@RequestMapping方法的新支持类

Spring 3.1分别为@RequestMapping方法引入了一组新的支持类,分别叫做RequestMappingHandlerMapping和RequestMappingHandlerAdapter。它们被推荐使用,甚至需要利用Spring MVC 3.1中的新功能和未来。默认情况下,MVC命名空间和MVC Java配置启用新的支持类,但是如果不使用,则必须显式配置。本节介绍旧支持类和新支持类之间的一些重要区别。

在Spring 3.1之前,类型和方法级请求映射在两个单独的阶段进行了检查 – 首先由DefaultAnnotationHandlerMapping选择一个控制器,并且实际的调用方法被AnnotationMethodHandlerAdapter缩小。

使用Spring 3.1中的新支持类,RequestMappingHandlerMapping是唯一可以决定哪个方法应该处理请求的地方。将控制器方法作为从类型和方法级@RequestMapping信息派生的每个方法的映射的唯一端点的集合。

这使得一些新的可能性。一旦HandlerInterceptor或HandlerExceptionResolver现在可以期望基于对象的处理程序是HandlerMethod,它允许它们检查确切的方法,其参数和关联的注释。 URL的处理不再需要跨不同的控制器进行拆分。

还有下面几件事情已经不复存在了:

  • 首先使用SimpleUrlHandlerMapping或BeanNameUrlHandlerMapping选择控制器,然后基于@RequestMapping注释来缩小方法。
  • 依赖于方法名称作为一种落后机制,以消除两个@RequestMapping方法之间的差异,这两个方法没有明确的路径映射URL路径, 通过HTTP方法。 在新的支持类中,@RequestMapping方法必须被唯一地映射。
  • 如果没有其他控制器方法更具体地匹配,请使用单个默认方法(无显式路径映射)处理请求。 在新的支持类中,如果找不到匹配方法,则会引发404错误。

    上述功能仍然支持现有的支持类。 不过要利用新的Spring MVC 3.1功能,您需要使用新的支持类。

    URI 模版模式

    可以使用URI模板方便地访问@RequestMapping方法中URL的所选部分。

    URI模板是一个类似URI的字符串,包含一个或多个变量名称。 当您替换这些变量的值时,模板将成为一个URI。 所提出的RFC模板RFC定义了URI如何参数化。 例如,URI模板http://www.example.com/users/{userId}包含变量userId。 将fred的值分配给变量会得到http://www.example.com/users/fred。

    在Spring MVC中,您可以使用方法参数上的@PathVariable注释将其绑定到URI模板变量的值:

    @GetMapping("/owners/{ownerId}")
    public String findOwner(@PathVariable String ownerId, Model model) {
    	Owner owner = ownerService.findOwner(ownerId);
    	model.addAttribute("owner", owner);
    	return "displayOwner";
    }
    URI模板“/ owners / {ownerId}”指定变量名ownerId。 当控制器处理此请求时,ownerId的值将设置为在URI的适当部分中找到的值。 例如,当/ owner / fred出现请求时,ownerId的值为fred。
    @GetMapping("/owners/{ownerId}")
    public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {
    	// implementation omitted
    }

    或者如果URI模板变量名称与方法参数名称匹配,则可以省略该详细信息。 只要您的代码使用调试信息或Java 8上的参数编译器标记进行编译,Spring MVC将将方法参数名称与URI模板变量名称相匹配:

    @GetMapping("/owners/{ownerId}")
    public String findOwner(@PathVariable String ownerId, Model model) {
    	// implementation omitted
    }
    一个方法能够有任意数量的@PathVariable注解:
    
    @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);
    	model.addAttribute("pet", pet);
    	return "displayPet";
    }
    当在Map <String,String>参数上使用@PathVariable注释时,映射将填充所有URI模板变量。
    URI模板可以从类型和方法级别@RequestMapping注释中进行组合。 因此,可以使用/ owner / 42 / pets / 21等URL调用findPet()方法。
    @Controller
    @RequestMapping("/owners/{ownerId}")
    public class RelativePathUriTemplateController {
    
    	@RequestMapping("/pets/{petId}")
    	public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
    		// implementation omitted
    	}
    
    }
    一个@PathVariable参数可以是任何简单的类型,如int,long,Date等。如果没有这样做,Spring将自动转换为适当的类型或者抛出一个TypeMismatchException。 您还可以注册解析其他数据类型的支持。. See the section called “Method Parameters And Type Conversion”the section called “Customizing WebDataBinder initialization”.

    具有正则表达式的URI模板模式

    有时您需要更精确地定义URI模板变量。 考虑URL“/spring-web/spring-web-3.0.5.jar”。 你怎么把它分解成多个部分?

    @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) {
    	// ...
    }
    

    路径模式

    除了URI模板之外,@RequestMapping注释和所有组合的@RequestMapping变体也支持Ant样式的路径模式(例如/myPath/*.do)。 还支持URI模板变量和Ant-style glob的组合(例如/ owners / * / pets / {petId})。

    路径模式比较

    当URL匹配多个模式时,使用排序来查找最具体的匹配。

    具有较低数量URI变量和通配符的模式被认为更具体。 例如/hotels/ {hotel} / *具有1个URI变量和1个通配符,被认为比/hotels/ {hotel} / **更具体,其中1个URI变量和2个通配符。

    如果两个模式具有相同的计数,那么较长的模式被认为更具体。 例如/ foo / bar *比较长,被认为比/ foo / *更具体。

    当两个模式具有相同的计数和长度时,具有较少通配符的模式被认为更具体。 例如/hotels/ {hotel}比/hotels/ *更具体。

    下面有些额外增加的特殊的规则:

    • 默认映射模式/ **比任何其他模式都要小。 例如/ api / {a} / {b} / {c}更具体。
    • 诸如/ public / **之类的前缀模式比不包含双通配符的任何其他模式都不那么具体。 例如/ public / path3 / {a} / {b} / {c}更具体。

For 有关详细信息,请参阅AntPathMatcher中的AntPatternComparator。 请注意,可以自定义PathMatcher(参见Section 18.16.11, “Path Matching” ).

具有占位符的路径模式

@RequestMapping注释中的模式支持对本地属性和/或系统属性和环境变量的$ {…}占位符。 在将控制器映射到的路径可能需要通过配置进行定制的情况下,这可能是有用的。 有关占位符的更多信息,请参阅PropertyPlaceholderConfigurer类的javadocs。

后缀模式匹配

默认情况下,Spring MVC执行“。*”后缀模式匹配,以便映射到/ person的控制器也隐式映射到/person.*。这使得通过URL路径(例如/person.pdf,/person.xml)可以轻松地请求资源的不同表示。

后缀模式匹配可以关闭或限制为一组明确注册用于内容协商的路径扩展。通常建议通过诸如/ person / {id}之类的常见请求映射来减少歧义,其中点可能不表示文件扩展名,例如/person/joe@email.com vs /person/joe@email.com.json。此外,如下面的说明中所解释的,后缀模式匹配以及内容协商可能在某些情况下用于尝试恶意攻击,并且有充分的理由有意义地限制它们。

有关后缀模式匹配配置,请参见第18.16.11节“路径匹配”,内容协商配置第18.16.6节“内容协商”。

后缀模式匹配和RFD

反思文件下载(RFD)攻击是由Trustwave在2014年的一篇论文中首次描述的。攻击类似于XSS,因为它依赖于响应中反映的输入(例如查询参数,URI变量)。然而,不是将JavaScript插入到HTML中,如果基于文件扩展名(例如.bat,.cmd)双击,则RFD攻击依赖于浏览器切换来执行下载并将响应视为可执行脚本。

在Spring MVC @ResponseBody和ResponseEntity方法存在风险,因为它们可以呈现客户端可以通过URL路径扩展请求的不同内容类型。但是请注意,单独禁用后缀模式匹配或禁用仅用于内容协商的路径扩展都可以有效地防止RFD攻击。

为了全面保护RFD,在呈现响应体之前,Spring MVC添加了Content-Disposition:inline; filename = f.txt头来建议一个固定和安全的下载文件。只有当URL路径包含既不是白名单的文件扩展名,也没有明确注册用于内容协商的目的,这是完成的。但是,当URL直接输入浏览器时,可能会产生副作用。

许多常见的路径扩展名默认为白名单。此外,REST API调用通常不是直接用于浏览器中的URL。然而,使用自定义HttpMessageConverter实现的应用程序可以明确地注册用于内容协商的文件扩展名,并且不会为此类扩展添加Content-Disposition头。见第18.16.6节“Content Negotiation”

这是CVE-2015-5211工作的一部分。 以下是报告中的其他建议:

  • 编码而不是转义JSON响应。 这也是OWASP XSS的建议。 有关Spring的例子,请参阅spring-jackson-owasp.
  • 将后缀模式匹配配置为关闭或仅限于明确注册的后缀
  • 配置使用属性“useJaf”和“ignoreUnknownPathExtensions”设置为false的内容协商,这将导致具有未知扩展名的URL的406响应。 但是请注意,如果URL自然希望有一个结束点,这可能不是一个选择。
  • 添加X-Content-Type-Options:nosniff头到响应。 Spring Security 4默认情况下执行此操作。

矩阵变量

URI规范RFC 3986定义了在路径段中包含名称 – 值对的可能性。规格中没有使用具体术语。可以应用一般的“URI路径参数”,尽管来自Tim Berners-Lee的旧帖子的更独特的“Matrix URI”也经常被使用并且是相当熟知的。在Spring MVC中,这些被称为矩阵变量。

矩阵变量可以出现在任何路径段中,每个矩阵变量用“;”分隔(分号)。例如:“/ cars; color = red; year = 2012”。多个值可以是“,”(逗号)分隔“color = red,green,blue”,或者变量名称可以重复“color = red; color = green; color = blue”。

如果URL预期包含矩阵变量,则请求映射模式必须使用URI模板来表示它们。这确保了请求可以正确匹配,无论矩阵变量是否存在,以及它们提供什么顺序。

以下是提取矩阵变量“q”的示例:

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

@GetMapping("/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) {

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

}
由于所有路径段都可能包含矩阵变量,因此在某些情况下,您需要更具体地确定变量预期位于何处:
// GET /owners/42;q=11/pets/21;q=22

@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
		@MatrixVariable(name="q", pathVar="ownerId") int q1,
		@MatrixVariable(name="q", pathVar="petId") int q2) {

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

}
矩阵变量可以定义为可选参数,并指定一个默认值:
// GET /pets/42

@GetMapping("/pets/{petId}")
public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) {

	// q == 1

}
所有矩阵变量可以在Map中获得:
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
		@MatrixVariable MultiValueMap<String, String> matrixVars,
		@MatrixVariable(pathVar="petId"") MultiValueMap<String, String> petMatrixVars) {

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

}
请注意,为了使用矩阵变量,您必须将RequestMappingHandlerMapping的removeSemicolonContent属性设置为false。 默认设置为true。
MVC Java配置和MVC命名空间都提供了使用矩阵变量的选项。
如果您使用Java配置,使用MVC Java Config的高级自定义部分将介绍如何自定义RequestMappingHandlerMapping。
在MVC命名空间中,<mvc:annotation-driven>元素具有一个应该设置为true的enable-matrix-variables属性。 默认情况下设置为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>

转载自 并发编程网 - ifeve.com

时间: 2024-10-04 00:13:00

《Spring 5 官方文档》18. Web MVC 框架(二)的相关文章

《Spring 5官方文档》11集成测试 (二)

11.3 JDBC测试支持 org.springframework.test.jdbc是包含JdbcTestUtils的包,它是一个JDBC相关的工具方法集,意在简化标准数据库测试场景.特别地,JdbcTestUtils提供以下静态工具方法: countRowsInTable(..):统计给定表的行数. countRowsInTableWhere(..):使用提供的where语句进行筛选统计给定表的行数. deleteFromTables(..):删除特定表的全部数据. deleteFromTa

《Spring 5 官方文档》4. 资源(二)

4.6 资源依赖 如果bean本身将通过某种动态过程来确定和提供资源路径,那么bean可以使用ResourceLoader接口来加载资源. j假设以某种方式加载一个模板,其中需要的特定资源取决于用户的角色. 如果资源是静态的,那么完全消除ResourceLoader接口的使用是有意义的,只需让bean公开它需要的Resource属性,那么它们就会以你所期望的方式被注入. 什么使得它们轻松注入这些属性,是所有应用程序上下文注册和使用一个特殊的JavaBeans PropertyEditor,它可以

《Spring 5 官方文档》26. JMS(二)

26.4 接收消息 26.4.1 同步接收 虽然 JMS 通常与异步处理相关,但它也可以同步地消费消息.可重载的receive(..)方法提供了这个功能.在同步接收期间,调用线程阻塞,直到接收到消息.这可能是一个危险的操作,因为调用线程可能无限期地被阻塞.receiveTimeout属性指定了接收者等待消息的超时时间. 26.4.2 异步接收 – 消息驱动的 POJOs Spring 还可以通过使用@JmsListener注解来支持监听注解端点,并提供了一种以编程方式注册端点的开放式基础架构.

《Spring 5官方文档》翻译邀请

公司新的应用已经开始使用Spring 5,所以本月组织大家翻译<Spring 5 官方文档> SINGLE网页版  PDF版本. 如何领取 通过评论领取想要翻译的文章,每次领取一章或一节(根据内容长短),翻译完后再领取其他章节.领取完成之后,建议在一个星期内翻译完成,如果不能完成翻译,也欢迎你邀请其他同学和你一起完成翻译.请谨慎领取,并发网是非盈利组织,没办法去跟进每一篇译文的进展,所以很多文章领取了没有翻译,会导致文章长时间没人翻译. 如何提交? 翻译完成之后请登录到并发编程网后台,点击左上

《Spring 5 官方文档》18. Web MVC 框架(八)

18.8.5 LocaleChangeInterceptor 您可以通过添加LocaleChangeInterceptor到其中一个处理程序映射来启用更改区域设置(请参见第18.4节"处理程序映射").它将检测请求中的一个参数并更改区域设置.它呼吁setLocale()在LocaleResolver上下文中也存在.以下示例显示,对包含*.view名为的参数的所有资源的调用siteLanguage现在将更改语言环境.因此,例如,对以下URL的请求http://www.sf.net/hom

《Spring 5 官方文档》18. Web MVC 框架(六)

18.4处理程序映射 在以前的Spring版本中,用户需要HandlerMapping在Web应用程序上下文中定义一个或多个 bean,以将传入的Web请求映射到适当的处理程序.通过引入注释控制器,您通常不需要这样做,因为它RequestMappingHandlerMapping会@RequestMapping自动在所有@Controllerbean 上查找 注释.但是,请记住,所有HandlerMapping扩展的类AbstractHandlerMapping都具有以下可用于自定义行为的属性:

《Spring 5 官方文档》18. Web MVC 框架(七)

18.5.4 ContentNegotiatingViewResolver 这ContentNegotiatingViewResolver不会解析视图本身,而是委托给其他视图解析器,选择类似于客户端请求的表示的视图.客户端可以从服务器请求表示方式存在两种策略: 通常通过在URI中使用不同的文件扩展名为每个资源使用不同的URI.例如,URI http://www.example.com/users/fred.pdf请求用户fred的PDF表示,并http://www.example.com/use

《Spring 5 官方文档》18. Web MVC 框架(九)

18.13.2 ModelMap(ModelAndView) 该ModelMap班本质上是一种荣耀Map,可以使补充说,是要显示(或上)一个对象View坚持一个共同的命名约定.考虑以下Controller实现; 注意对象被添加到ModelAndView没有指定的任何关联的名称. public class DisplayShoppingCartController implements Controller { public ModelAndView handleRequest(HttpServl

Spring Data 官方文档》4.7 Spring Data扩展

4.7 Spring Data扩展 这部分说明Spring Data一系列的扩展功能,可以使Spring Dta使用多样的上下文.目前大部分集成是针对Spring MVC. 4.7.1 Querydsl扩展 Querydsl是一个框架,通过它的流式API构建静态类型的SQL类查询.多个Spring Data模块通过QueryDslPredicateExecutor与Querydsl集成. 例29 QueryDslPredicateExecutor接口 1 public interface Que

《Spring 5 官方文档》5. 验证、数据绑定和类型转换(一)

5 验证.数据绑定和类型转换 5.1 介绍 JSR-303/JSR-349 Bean Validation 在设置支持方面,Spring Framework 4.0支持Bean Validation 1.0(JSR-303)和Bean Validation 1.1(JSR-349),也将其改写成了Spring的Validator接口. 正如5.8 Spring验证所述,应用程序可以选择一次性全局启用Bean验证,并使其专门用于所有的验证需求. 正如5.8.3 配置DataBinder所述,应用程