Spring MVC学习记录
Spring MVC
- SpringMVC 是一种基于 Java 的轻量级 Web 框架,属于 SpringFramework 的一部分。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无需实现任何接口。
- SpringMVC 支持 RESTful 编程风格的请求,并且已经成为目前最主流的 MVC 框架之一。
- 它遵循 Model-View-Controller 设计模式。它实现了核心 Spring 框架的所有基本功能,例如控制反转,依赖注入。
中央 servlet (DispatcherServlet)
为请求处理提供了一个共享算法,需要根据 Servlet 规范,使用 Java 配置或在 web.xml 中进行声明和映射。
DispatcherServlet 使用 Spring 配置来发现它在请求映射、视图解析、异常处理 等 方面需要的委托组件。
java 注册配置初始化
1 | public class MyWebApplicationInitializer implements WebApplicationInitializer { |
web.xml 注册初始化
1 | <web-app> |
上下文(Context)层次结构
DispatcherServlet 期望有一个 WebApplicationContext(普通 ApplicationContext 的扩展)用于自己的配置。WebApplicationContext 有一个与 ServletContext 和与之相关的 Servlet 的链接。它也被绑定到 ServletContext,这样应用程序就可以使用 RequestContextUtils 上的静态方法来查询 WebApplicationContext,如果他们需要访问它的话。
DispatcherServlet 委托给特殊的 Bean 来处理请求并呈现适当的响应。
一个根 WebApplicationContext 被多个 DispatcherServlet(或其他 Servlet)实例共享,每个实例都有自己的子 WebApplicationContext 配置。
根(root) WebApplicationContext 通常包含基础设施 Bean,例如需要在多个 Servlet 实例中共享的数据存储库和业务服务。这些 Bean 有效地被继承,并且可以在 Servlet 特定的子 WebApplicationContext 中被重写(也就是重新声明),该 WebApplicationContext 通常包含给定 Servlet 的本地 Bean。
我们需要配置 MVC 和 Servlet
过滤器 Filter
Form Data
浏览器只能通过 HTTP GET 或 HTTP POST 提交表单数据(form data),但非浏览器客户端也可以使用 HTTP PUT、PATCH 和 DELETE。Servlet API 要求 ServletRequest.getParameter*() 方法只支持 HTTP POST 的表单字段访问。
Fromworded Header
ForwardedHeaderFilter 是一个 Servlet 过滤器,它修改了请求,以便 a)根据 Forwarded 头信息改变 host、port 和 scheme,以及 b)删除这些头信息以消除进一步的影响。
Shallow ETag
hallowEtagHeaderFilter 通过缓存写入响应的内容并计算出 MD5 哈希值来创建一个 “shallow” ETag。客户端下次发送时,它做同样的事情,但它也将计算的值与 If-None-Match 请求头进行比较,如果两者相等,则返回 304(NOT_MODIFIED)。
这种策略可以节省网络带宽,但不能节省 CPU,因为必须为每个请求计算出完整的响应。
ETag(实体标签)是 HTTP 协议中用于标识资源版本的机制。服务器为资源(如网页、API 响应)生成一个唯一标识符(如哈希值、版本号),并在响应头中通过 ETag 字段返回给客户端。
客户端后续请求该资源时,会在请求头中通过 If-None-Match 字段携带之前获取的 ETag。服务器对比当前资源的 ETag 与客户端传递的 ETag:
若一致(资源未修改),返回 304 Not Modified,不传输资源内容;
若不一致(资源已修改),返回新资源和新 ETag。
普通 ETag 通常需要服务器生成完整的响应内容后,通过计算内容的哈希值(如 MD5)生成,属于 “深度” 计算(依赖资源的实际内容)。
而 Shallow ETag(浅 ETag) 则是在响应内容生成后,直接基于响应的元数据(如状态码、头部信息、内容长度等)或简化的内容摘要生成,无需深入计算完整内容的哈希。
Cors
详情见下文
注解式 Controller
Spring MVC 提供了一个基于注解的编程模型,其中 @Controller 和 @RestController 组件使用注解来表达请求映射、请求输入、异常处理等内容。注解的控制器具有灵活的方法签名,不需要继承基类,也不需要实现特定的接口。下面的例子显示了一个由注解定义的控制器
示例:
1 |
|
AOP 代理
请求映射
使用 @RequestMapping 注解来映射请求到 controller 方法。它有各种属性,可以通过 URL、HTTP 方法、请求参数、header 和媒体类型(meida type)进行匹配。
还有 HTTP 方法特定的 @RequestMapping 的快捷方式变体:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
示例
1 |
|
方法的参数:
- @PathVariable(“customId”):用于访问 URI 模板变量
- @RequestParam:用于访问 Servlet 请求参数,包括 multipart 文件。参数值被转换为声明的方法参数类型。
- @RequestHeader:用于访问请求 header。header 值被转换为声明的方法参数类型。
- @RequestBody:用于访问 HTTP request body。通过使用 HttpMessageConverter 实现, Body 内容被转换为声明的方法参数类型。
- @RequestAttribute:用于访问 request attribute。
返回值
- @ResponseBody:返回值通过 HttpMessageConverter 实现进行转换并写入响应。更多信息请阅读我关于 Spring 开发常用注解的专题。
CORS
出于安全考虑,浏览器禁止 AJAX 调用当前来源以外的资源。跨域资源共享(CORS)是由 大多数浏览器 实施的 W3C 规范,它让你指定哪种跨域请求被授权。
全局配置
我们可以定义一个 CorsConfig 类来配置 Cors
示例:
1 |
|
Web Security
Spring Security 项目提供了对保护 Web 应用免受恶意攻击的支持。具体可查阅我关于 Spring Security 的文章
HTTP 缓存
HTTP 缓存可以大大改善 web 应用的性能。HTTP 缓存围绕着 Cache-Control 响应头以及随后的条件请求头(如 Last-Modified 和 ETag)。Cache-Control 建议私人(如浏览器)和公共(如代理)缓存如何缓存和重新使用响应。ETag 头被用来做一个有条件的请求,如果内容没有改变,可能会产生一个没有正文的 304(NOT_MODIFIED)。ETag 可以被看作是 Last-Modified 头的一个更复杂的继承者。
CacheControl
CacheControl 提供了对配置与 Cache-Control 头相关的设置的支持,并在很多地方被作为参数接受
Controller
Controller 可以增加对 HTTP 缓存的明确支持。我们推荐这样做,因为资源的 lastModified 或 ETag 值需要在与条件请求头进行比较之前进行计算。Controller 可以为 ResponseEntity 添加 ETag 头和 Cache-Control 设置
示例:
1 |
|
如果与条件请求头的比较表明内容没有改变,前面的例子会发送一个 304(NOT_MODIFIED)响应,并带有一个空的 body。否则,ETag 和 Cache-Control 头信息将被添加到响应中。
静态资源
你应该用 Cache-Control 和有条件的响应头来提供静态资源以获得最佳性能。
详情见下文
ETag Filter
你可以使用 ShallowEtagHeaderFilter 来添加 “shallow” eTag 值,这些值是从响应内容中计算出来的,因此可以节省带宽,但不能节省 CPU 时间
MVC 配置
在 Java 配置中,你可以使用 @EnableWebMvc 注解来启用 MVC 配置
示例:
1 |
|
校验
在 Java 配置中,你可以自定义全局 Validator 实例
1 |
|
拦截器
在 Java 配置中,你可以注册拦截器来应用于传入的请求
1 |
|
静态资源
给定一个以 /resources 开头的请求,相对路径被用来寻找和提供相对于 Web 应用 root 下的 /public 或 /static 下 classpath 的静态资源。这些资源在未来一年内到期,以确保最大限度地利用浏览器的缓存,减少浏览器的 HTTP 请求。
配置:
1 |
|
REST 客户端
RestTemplate
RestTemplate 是一个执行 HTTP 请求的同步客户端。它是原始的 Spring REST 客户端,在底层的 HTTP 客户端库上暴露了一个简单的、模板式的 API。
WebClient
WebClient 是一个非阻塞的、响应式的客户端,用于执行 HTTP 请求。
