b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

1.2 Filters

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

1.2.1 Form Data

浏览器可以提交form data,通过HTTP GET或者HTTP POST。但是非浏览器端也会用HTTP PUT, PATCH, and DELETE。Servlet API要求ServletRequest.getParameter*()方法支持只允许从POST获取参数。
spring-web模块提供FormContentFilter去拦截HTTP PUT, PATCH, and DELETE requests ,谁拥有application/x-www-form-urlencoded,从请求body里读取form data,并且包装ServletRequest去让ServletRequest.getParameter*()可以获得到。

1.2.2 Forwarded Headers

作为一个请求通过代理后,host、port和scheme也许会变,这让link能准确的链接到正确的Host、port和scheme上是一个挑战。
RFC 7239规范,定义了Forwarded HTTP header, 让代理proxy可以用来提供关于原始请求的信息。也有非标准的header,包含X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto, X-Forwarded-Ssl, and X-Forwarded-Prefix
ForwardedHeaderFilter是一个Servlet filter可以修改requestde 的host,port,scheme基于Forwarder。这个filter依赖包装request,因此他必须在其他filter前面,例如RequestContextFilter(必须是用被修改后的request,而不是原来的)
由于一个应用不知道headers是否被代理,或者被恶意client添加或修改过。出于对forwarded的安全考虑,proxy应该配置成移除不被信任Forwarded headers。你也可以配置ForwardedHeaderFilterremoveOnly=true,来移除并不使用这个headers。
异步请求
为了支持异步永清和error跳转,这个filter应该被配置DispatcherType.ASYNCDispatcherType.ERROR。如果使用Spring框架的AbstractAnnotationConfigDispatcherServletInitializer,所有的filter会被注册成拥有对应的dispatch types。
如果使用了web.xml进行配置,或者spring boot通过FilterRegistrationBean来包含DispatcherType.ASYNC DispatcherType.ERROR 需要额外添加DispatcherType.REQUEST

1.2.3 Shallow ETag

ShallowEtagHeaderFilter会创建一个shallowETAG来缓存被写入response的content和计算一个MD5的hash。下次clents同样发送时,它会比较If-None-Match,相同就返回一个304(NOT_MODIFIED)的标记。

这种策略节省网络带宽,但不节省cpu,当全response必须被计算和比较。其他策略在conroller级别,避免计算。
filter拥有writeWeakETag参数来配置filter去写弱ETags,如
W/"02a2d595e6ed9a0b24f027f2b63b134d6在RFC 7232的规范里。
为了去支持asynchronous requests,filter必须被配置成DispatcherType.ASYNC以便于在最后一步分发结束的时候生成ETag。

1.2.4 CORS配置

1.3 注解Controllers

Spring MVC支持注解驱动的@Controller@RestCOntroller
一个简单的示例
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

1.3.1 声明Declaration

@Controller是一个原注解,允许在WebApplicationContext中自动侦测。当然@Component也行。去开启@Controller你可以注册扫描
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
xml版
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

@RestController是一个复合注解,@Controller和@ResponseBody去指明Controller的每一个方法都继承了@ResponseBody的注解。

AOP代理

某些情况下,需要声明controllerr和AOP代理。如果你有@Transactional注解在@Controller上。这种情况下,我们推荐使用class-based的代理。这个会被controllers默认选中。然而如果controller必须实现一个接口不是一个Spring Context callback(例如InitializingBean,*Aware),你需要明确的配置 class-based的代理,如<tx:annotation-driven/>改成<tx:annotation-driven proxy-target-class=“true”/>。你可以用这个注解来打开@EnableTransactionManagement(proxyTargetClass = true)

1.3.2 Request Mapping 重要

你可以使用@RequestMapping注解去map requests到controllers。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
controller类上需要使用@RequestMapping来指明基本的URL
方法上通过使用@RequestMapping,集体到具体方法

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

URI patterns

  • ? 匹配一个
  • * 在一个path分隔符里匹配一个或多个字符
  • ** 匹配一个或多个path分隔符

@PathVariable

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
方法级别和类级别都可以有
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
URI 变量会被自动转成合适的类型,转不到会抛出TypeMismatchException的错误。简单类型(int、long、Date等),也支持你定义的类型,请看后面呢DataBinder
也可以用@PathVariable("customId")来明确指出具体哪个章节。

正则表达式解析

{varName:regex}来解析某个字段,
例如spring-web-3.0.5.jar会被如下的表达式解析成:spring-web,3.0.5,jar。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Pattern Comparison 模式比价

当多个模式同时命中的时候,必须找到最佳的命中。通过使用AntPathMatcher.getPatternComparator(String path)找具体的pattern。
首先最少拥有一个URI variables(加1分),一个不确定的参数(加1分),两个不确定加两分。相同分数下最长的pattern会被命中。同样的分数和长度下,拥有最多URI variables的会被命中。
默认的mapping pattern是/**是不计分的,总是排在最后兜底。同样,
/public/**也是被考虑是排在其他不拥有两个不确定符号之后的。
完整的细节请看Path Matching。

Suffix Macth 后缀匹配。

Spring MVC 默认会加.*在后缀,以便于匹配到/person的时候也匹配到/person.*。文件扩展名,可以从请求的headers,Accept字段来获取,例如/person.pdf/person.xml
使用文件扩展后缀在浏览器级别是必要的,当浏览器用Accept来标识需要的文件。目前没有比用Accept最好的选择。
文件后缀也有麻烦,有时候会造成二义性。当时用URI variables认证鉴权也会很麻烦。
可以去关闭
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Suffix Match and RFD

A reflected file download(rfd),反射文件攻击和XSS是详细的,query parameter和URI的variable可以影响response。然而,插入JavaScript 到HTML, RFD攻击依赖浏览器去切换下载和对response作为一个二次的触发。
在Spring MVC中,@ResponseBody和ResponseEntity方法是有风险的,以为可以渲染不同的content types–客户端可以通过URL的路径扩展来请求。禁止suffix pattern和使用path扩展名可以降低风险。但是这不能阻止RFD攻击。
为了阻止RFD攻击,MVC添加Content-Disposition:inline;filename=f.txthead,去建议有个修改和安全的下载文件。之歌只在URLpath包含文件扩展名的前提下。然而,当URLs被直接写在Brower的浏览器时,会潜在的低的影响。
多数的公用文件扩展有白盒列表。应用可以自定义HttpMessageConverter实现,来明确的注册文件后缀。

Consumable Media Types(Content-Type条件)

你可以基于请求的Content-Type来映射到具体的请求
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
这个consumes属性也支持否定表达式,比如!text/plain意味着非text/plain
你可以分级使用consumes属性。比如在文件级别。不像多数的请求属性,然而使用它在class level,method level会覆盖他的consumes属性。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Producible Media Types (Accept条件)

你可以通过Acceptheader来罗列一系列被接受的属性。
produces产出对应着被
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
也可以用 !text/plain
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Parameters, headers (按参数条件匹配)

可以根据参数和header来进行条件化的匹配
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

HTTP HEAD, OPTIONS

@GetMapping等同于@RequestMapping(method=HttpMethod.GET)
支持的HTTPMapping有如下
GET,HEAD,POST,PUT,PATCH,DELETE,OPTION

Custom Annotations 自定义注解

mvc 内置@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, 和 @PatchMapping。
HTTP也支持自定义注解,需要继承RequestMappingHandlerMapping,实现getCustomMethodCondition()方法。

Explicit Registrations 明确的注册

可以使用代码去动态注册一个类
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

1.3.3 Handler Methods

@RequestMapping 可以有灵活的签名,来从匹配响应的controller

Method Arguments 方法参数

JDK8的 java.util.Optional支持方法参数和有required属性注解混合使用,比如@RequestParam, @RequestHeader,和对等的required=false。
这个表描述的是一些之策controller 方法参数
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Return Values 支持的返回值

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Type Conversion 参数代表注解

一些controller的方法注解,代表了request的不同输入,但都是String-based(such as @RequestParam, @RequestHeader, @PathVariable, @MatrixVariable, and @CookieValue)。
同时也支持自定义,你可以使用WebDataBinder (see DataBinder),通过注册Formatters到
FormattingConversionService,详见Spring Field Formatting

Matrix Variables

RFC 3968中描述了name-value键值对在path分隔符间的定义。Spring MVC中,我们定义为matrix variables,形如/cars;color=red,green;year=2012).。下列是如何使用
简单的匹配
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
清晰的匹配
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
设置默认值
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
返回一个数组
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
注意要使用这种方式,你需要打开开关。在MVC java配置中,你需要Path Matching设置UrlPathHelper with removeSemicolonContent=false。xml注解中
<mvc:annotation-driven enable-matrix-variables="true"/>

@RequestParam

你可以使用@RequestParam注解去绑定Servlet request参数到一个在里的method 参数。
如下
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
默认的,方法参数中写明,就意味着required属性为ture。可以额外指定为flase。至于对非String的类型转化,请看Type Conversion
当一个@RequestParam被声明为Map<String, String> MultiValueMap<String, String>那么内容就是参数键值对。
注意@RequestParam是可选的,一般来讲处理简单的键值对。

@RequestHeader

使用这个注解来绑定request的header。形如
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
也可以使用Map<String, String>, MultiValueMap<String, String>,或者HttpHeaders argument来承接。
注意有的header是list,例如@RequestHeader("Accept")可以使用String but also String[]或List<String>来执行。

@CookieValue

HTTP的@CookieValue注解
类如有cookie
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

@ModelAttribute

主要是request级别
你可以使用@ModelAttribute一个方法参数上,然后去从一个model初始化。这个model ModelAttribute值也会http的request中取值,如果field name可以匹配的上的话。

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
一下是绑定的顺序过程

    1. 如果model早已被添加,就使用model
    1. 从HTTP session
    1. 从URL PATH variable获取,通过一个Converter
    1. 从默认的构造器
    1. 从参数构造器,其余request的参数匹配。参数的名称会被javaBeans的@ConstructorProperties获取到

处理使用通用的Modle去绑定值外,还会有Converter<String, T>方式。可以预先写好转化,把一个字符串,解析成一个对象。不过需要注册Converter
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

使用Web DataBinder

在使用Model 去获得实例后还可以使用BindingResult参数去check 参数的合法性。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
一些场景你也许直接想用model而不用 databinding如下

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
配合vailde进行验证
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

@SessionAttributes

是在HTTP Servlet session级别去存储modle模型。典型的model都会存在session里,对session下的请求都是可见的。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
在第一个请求里,放了一个petname的属性,就会被添加到model中去,并放置到session里。它会一致保留到另外的方式使用SessionStatus方法参数去清空。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

@SessionAttribute

@SessionAttribute如果你想要访问一些预置的session属性,它可能存在或者不存在。你可以使用@SessionAttribute注解在方法参数上,下列的例子就是
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
如果你想要去添加或者移除一些session属性,请把org.springframework.web.context.request.WebRequestjavax.servlet.http.HttpSession放入到controller method中。
对于临时性的存储,在session的控制流中,考虑去使用@SessionAttributes

@RequestAttribute

和SessionAttribute类似,@RequestAttribute注解去拿到预定义在请求里面的属性(比如在Servlet Filter或者HandlerInterceptor创建的)
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Redirect Attributes 重定向是属性值得传递

默认的所有的model 属性,都会被作为URL变量暴露给Redirect URL。对于保留的属性,那些可能是私有类型或者集合、数组都会自动appended为query 参数。
如果一个model instance准备把所有的属性暴露给Redirect URL,那么append 私有属性是没有问题的。但是在注解驱动的controller,model还会包含一些被额外添加的属性或者希望丢弃的属性。为了避免这些信息被全量的暴露给URL,@RequestMapping可以声明一个RedirectAttributes并且使用它去明确指出那些是被暴露给RedirectView。如果这些方法做了重定向,这个RedirectAttributes就会被使用
。否则的话全量的model会被使用。
RequestMappingHandlerAdapter提供了一个名为ignoreDefaultModelOnRedirect的flag,用来指示默认Model是否应该永远不会被使用,当存在RedirectAttributes的时候。否则所有属性都会被声明为RedirectAttributes。Spring MVC和MVC Java configuration都会默认设置为false,来保证兼容。新应用应该设置为true。
注意url template里面的变量会被redirect自动获取,不需要明确声明
自定获取
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
另一种重定向的属性传递是靠flash attribute。

Flash Attributes

flash 属性提供了request之间的属性传递。这个是重定向时最常用的。
例如Post-Redirect-Get模式,flash属性在redirect之前先被临时存储,去让重定向后的请求获得。
Spring MVC提供了两种对flash属性的支持。FlashMapFlashMapManager去存储flash属性。
flash属性总是"on",不需要明确打开。然而,如果不用的话,HTTP session就永远不会创建。对于每个请求存在inputflash,和outputflashmap。两个FlashMap实例都可以通过RequestContextUtils的静态方法获取。
注解controller典型 的需要直接和FlashMap交互。使用@RequestMapping接受参数RedirectAttributes,并使用它去存储和取回就会自动的存入inputoutputFlashMap。

匹配request到 flash attributes
flash在很多web框架都有,但是存在一个问题就是,期待的下一个请求,可能是异步需要等待很久。
为了减少这种可能,RedirectView会自动标记FlashMap 实例,通过使用path和query参数。反过来,FlashMapManager也会为即将到来的请求匹配"input" FlashMap 。

Multipart 多片传输

MultipartResolver打开后,拥有multipart/form-data的POST请求的内容,会被解析和当做寻常的参数,实例展示如何获得和上传一个文件。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
如果声明参数的类型为List<MultipartFile>,就允许多片传输用一个参数名。
@RequestParam名称被宣布成为
Map<String, MultipartFile>或者MultiValueMap<String, MultipartFile>,无需在注解annotation里具体指明名称,然后这个map会被给的multipart文件自动标识。
你可使用data binding
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
多片传输的请求也可以非浏览器的client,以restFul 语义传输。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
你可以用meat-data部分,用@RequestParam作为一个String ,你也可以从一个JSON去反序列化,类似于
@RequestBody。
使用@RequestPart注解让你HttpMessageConverter来做转化
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
也可以和@Vaild一起使用,或者是@Validated。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

@RequestBody

使用该注解能够让你从request body读和反序列化成一个对象。通过
HttpMessageConverter。下面的例子是使用@RequestBody

就是把返回值序列化成字符串

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
你可以使用Message ConvertersMVC Config去配置或者自定义消息转化。
你可以把@RequestBodyjavax.validation.Valid或@Validated一块使用,两个都是标准Bean的验证。默认的如若不合格,就会造成MethodArgumentNotValidException,他会被转化成一个400(BAD_REQUEST)的response。你也可以通过Errors or BindingResult自行进行处理
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

HttpEntity

HttpEntity 和@RequestBody差不多,但是是基于container 对象,其暴露了request请求和body下列展示的例子。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

@ResponseBody

用该注解可以使用HttpMessageConverter通过对responseBody进行处理
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
@ResponseBody可以在class级别去是用,会被所有的cotroller method所继承。和@RestController类似,@RestController就是@Controller和@ResponseBody的复合注解。
你可以把@ResponseBody和JSON一块使用

ResponseEntity

和@ResponseBody类似,但是具有status和headers。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

重要关于Jackson JSON

需要Jacksong library

JSON Views

Spring mvc 内置了Jackson’s Serialization Views,循序从一系列在Object的子集合里渲染。为了使用@ResponseBody或者 ResponseEntity controller 方法。你可以使用Jackson的@JsonView注解。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
你也可以把添加序列化的view类到model中去,如下
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

1.3.4 Model

你可以使用@ModelAttribute

  • 在一个@RequestMapping标注的方法参数上,去创建或者从一个mode获得一个对象,并且通过WebDataBinder去绑定到request。
  • 在用@Controller或者 @ControllerAdvice标注的method-level方法去帮助初始化一个对象,提供给@RequestMapping去调用。
  • 在@RequestMapping标注他的返回值为一个model。

这个部署讨论前面罗列的第二种。一个controller可以有很多@ModelAttribute的methods。所有这些方法都是在@RequestMapping方法之前执行。一个@ModelAttribute方法可以通过@ControllerAdvice被共用见下面的Controller Advice。

@ModelAttribute方法有灵活的方法签名,支持很多和@RequestMapping一样的参数签名。
标注在方法上
前面的ModeAttribue会更详细
这里的作用是将参数值(number)和返回值放入Model(acount)中
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
这里只放了acount
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

如果不特定指明属性名就会,基于Object的type,在Conventions的doc中详细阐述。你可以使用addAttribute方法明确一个name,或者在@ModelAttribute加一个name,这会为返回值生成一个return。

@ModelAttribute + @RequestMapping + method-level 让返回值会被当做model attribute。

1.3.5 DataBinder重要

@Controller或 @ControllerAdvice可以有@InitBinder方法区初始化WebDataBinder,可以做

  • bind Request parameter (或者 form or query data)到一个model object
  • 转化 String-based的request values—request params、path variables、header、cookies,到目标的controller或者method 参数
  • 格式化model队像作为String。

@InitBinder方法可以注册到controller-specificjava.bean.PropertyEditor 或者Spring Converter或者 Formatter组件。另外你可以用MVC的配置在全局的FormattingConversionService,去注册Converter and Formatter

@InitBinder 方法支持很多和@RequestMapping一样的方法,除了@ModelAttribute参数。典型的是和一个WebDataBinder 和void参数值使用
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

也可以使用dataformater
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

1.3.6 Exceptions 异常处理

注册一个异常
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
匹配多个异常使,根异常被抛出。
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

Method Arguments

@ExceptionHandler methods support the following arguments:
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

return values

b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder

REST API exceptions

@RestController 使用@ExceptionHandler 可以用
ResponseEntity来设置response的响应值

1.3.7. Controller Advice

一般@ExceptionHandler和@InitBinder和@ModelAttribute方法在@Controller声明的地方。但是如果想想去应用的全局,你应该把这些注解声明到@ControllerAdvice
或者@RestControllerAdvice
b 4.1 Spring MVC Filters过滤器详解 & request mapping注解 & Handler Methods &databinder