文章目录
- 1.2 Filters
- 1.3 注解Controllers
-
- 1.3.1 声明Declaration
- 1.3.2 Request Mapping 重要
- 1.3.3 Handler Methods
-
- Method Arguments 方法参数
- Return Values 支持的返回值
- Type Conversion 参数代表注解
- Matrix Variables
- @RequestParam
- @RequestHeader
- @CookieValue
- @ModelAttribute
- @SessionAttributes
- @SessionAttribute
- @RequestAttribute
- Redirect Attributes 重定向是属性值得传递
- Flash Attributes
- Multipart 多片传输
- @RequestBody
- HttpEntity
- @ResponseBody
- ResponseEntity
- 重要关于Jackson JSON
- 1.3.4 Model
- 1.3.5 DataBinder重要
- 1.3.6 Exceptions 异常处理
- 1.3.7. Controller Advice
1.2 Filters
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。你也可以配置ForwardedHeaderFilter
为 removeOnly=true
,来移除并不使用这个headers。
异步请求
为了支持异步永清和error跳转,这个filter应该被配置DispatcherType.ASYNC
和DispatcherType.ERROR
。如果使用Spring框架的AbstractAnnotationConfigDispatcherServletInitializer
,所有的filter会被注册成拥有对应的dispatch types。
如果使用了web.xml
进行配置,或者spring boot通过FilterRegistrationBean
来包含DispatcherType.ASYNC
DispatcherType.ERROR
需要额外添加DispatcherType.REQUEST
。
1.2.3 Shallow ETag
ShallowEtagHeaderFilter
会创建一个shallow
ETAG来缓存被写入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
一个简单的示例
1.3.1 声明Declaration
@Controller是一个原注解,允许在WebApplicationContext
中自动侦测。当然@Component也行。去开启@Controller你可以注册扫描
xml版
@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。
controller类上需要使用@RequestMapping来指明基本的URL
方法上通过使用@RequestMapping,集体到具体方法
URI patterns
- ? 匹配一个
- * 在一个path分隔符里匹配一个或多个字符
- ** 匹配一个或多个path分隔符
@PathVariable
方法级别和类级别都可以有
URI 变量会被自动转成合适的类型,转不到会抛出TypeMismatchException
的错误。简单类型(int、long、Date等),也支持你定义的类型,请看后面呢DataBinder
也可以用@PathVariable("customId")
来明确指出具体哪个章节。
正则表达式解析
{varName:regex}来解析某个字段,
例如spring-web-3.0.5.jar
会被如下的表达式解析成:spring-web,3.0.5,jar。
Pattern Comparison 模式比价
当多个模式同时命中的时候,必须找到最佳的命中。通过使用AntPathMatcher.getPatternComparator(String path)
找具体的pattern。
首先最少拥有一个URI variables(加1分),一个不确定的参数(加1分),两个不确定加两分。相同分数下最长的pattern会被命中。同样的分数和长度下,拥有最多URI variables的会被命中。
默认的mapping pattern是/**
是不计分的,总是排在最后兜底。同样,
/public/**
也是被考虑是排在其他不拥有两个不确定符号之后的。
完整的细节请看Path Matching。