学习链接:https://www.liaoxuefeng.com/wiki/1252599548343744/1266265125480448
大部分内容来自此教程,以下只是我的学习笔记。
引入
Servlet是JavaEE中Web开发的基础,但是直接用Servlet来开发Web过于繁琐,就好比直接用JDBC来操作数据库。因此,在实际开发中,我们需要选用一个Servlet封装MVC框架来开发。因此引入Spring的MVC框架——Spring MVC。
Spring MVC与Spring和MVC的关系:
- MVC是一种设计模式
- Spring MVC是Spring的一个模块,专门用于构建Web应用程序,用来实现MVC
Spring MVC
配置
- 我们编写正常的
AppConfig后,只需加上@EnableWebMvc注解,就“激活”了Spring MVC。 - 除了创建
DataSource、JdbcTemplate、PlatformTransactionManager外,AppConfig需要额外创建几个用于Spring MVC的Bean。如ViewResolver - controller的注解必须为
@Controller,而不是@Component
启动
介绍最简单的方式:在web.xml中配置Spring MVC提供的DispatcherServlet 来实现。
|
|
原理:会初始化一个DispatcherServlet。在DispatcherServlet启动时,会根据AppConfig的配置创建一个WebApplicationContext的IoC容器。完成所有Bean的初始化,并将容器绑到ServletContext上。因为DispatcherServlet持有IoC容器,能从IoC容器中获取所有@Controller的Bean,因此,DispatcherServlet接收到所有HTTP请求后,根据Controller方法配置的路径,就可以正确地把请求转发到指定方法,并根据返回的ModelAndView决定如何渲染页面。
Controller 方法写法
- 注解:
@Controller - 处理请求:
@PostMapping,@GetMapping - 入参:以
@RequestParam()标注,或者HttpServletRequest、HttpServletResponse或者HttpSession - 出参:根据需要返回
ModelAndView或 其他
REST
REST(Representational State Transfer,表征状态转移)架构风格的网络服务。通常接收和返回JSON和XML格式,便于前后端分离的实现,编写基于 JSON 或 XML 响应的 RESTful Web 服务非常方便。
Jackson依赖
定义:流行的开源 Java 库,主要用于处理 JSON 数据
特点:Jackson 可以将 Java 对象转换成 JSON 格式(称为序列化),或者将 JSON 字符串转换成 Java 对象(称为反序列化)。
@RestController注解
使用@RestController替代@Controller后,每个方法自动变成API接口方法。Spring默认使用JSON作为输入和输出。
- 出参:默认返回响应体(Response Body),而不是视图(View)。这是因为
@RestController注解包含了@ResponseBody,这意味着方法的返回值将直接作为 HTTP 响应的正文返回,而不是解析为跳转路径。 - 入参:如果是
@RequestBody类型的,也会被自动序列化为Json格式
控制序列化和反序列化规则
序列化/反序列化一般会作用于对象的所有字段,如果想要对某些字段隐藏(如password),则要使用Jackson提供的@JsonIgnore和@JsonProperty注解来实现。
集成Filter
Spring MVC的DelegatingFilterProxy
当一个Filter作为Spring容器管理的Bean存在时,可以通过DelegatingFilterProxy间接地引用它并使其生效。
使用Interceptor
Spring MVC提供的一种功能类似Filter的拦截器:Interceptor。只作用于Controller拦截。
实现:
- implements HandlerInterceptor
- 选择复写
preHandle()、postHandle()和afterCompletion()方法 - 在
WebMvcConfigurer中注册所有的Interceptor
@ExceptionHandler注解
Spring MVC还提供了一个异常处理方法,即使用@ExceptionHandler注解。可以指定触发处理的异常类型,在方法体中定义当出现这些异常时需要有什么动作。如当出现某种异常时, 系统返回一个自定义的错误界面。
作用范围:仅针对当前controller类
CORS 控制跨域访问
CORS,全称Cross-Origin Resource Sharing,是HTML5规范定义的如何跨域访问资源。
默认情况下,浏览器按同源策略放行JavaScript调用API。不同源(域名、协议、端口都相同,才是同源)的目的地址默认不允许访问。如果网站A(http://a.com)要访问网站B,只有当网站B返回响应头Access-Control-Allow-Origin: http://a.com,才允许此访问。
要允许页面JavaScript访问REST API时,允许某些访问,可以通过设置CORS要实现
@CrossOrigin注解
在具体Controller类或方法上添加此注解,可以定义允许的来源地址。
CorsRegistry定义
在WebMvcConfigurer中定义一个全局CORS配置。更加推荐此方法。
Spring提供的CorsFilter
需要修改web.xml,也比较繁琐。不推荐。
国际化
指网页对于多语言多地区的本土化展示支持。有以下术语:
- 国际化 internationalization (i18n)
- 本地化 localization (l10n)
- 全球化=国家化+本地化 globalization (g11n)
在Java中,支持多语言和本地化是通过MessageFormat配合Locale实现的
Locale
浏览器的请求头会带Accept-Language头,用来指示用户浏览器设定的语言顺序。
资源文件
一般会根据语言的不同,生成不同命名的资源文件。key相同,value根据不同语句来配置。教程中的例子:
对于多语言,主文件名如果命名为messages,那么资源文件必须按如下方式命名并放入classpath中:
- 默认语言,文件名必须为
messages.properties; - 简体中文,Locale是
zh_CN,文件名必须为messages_zh_CN.properties; - 日文,Locale是
ja_JP,文件名必须为messages_ja_JP.properties;
MessageSource
创建Spring提供的MessageSource实例,它自动读取所有的.properties文件,并提供一个统一接口来实现“翻译”
异步处理
概念
- 同步:请求和返回使用的是同一个线程
- 异步:当返回用时比较长时,使用同步处理可能会耗尽线程池里的线程。异步可以支持返回使用和请求不同的线程进行处理。这样,也会提高线程池的利用率。
Servlet3.0 开始支持异步。
Spring MVC中的异步实现
web.xml配置
|
|
主要就是在dispatcher配置中增加async-supported配置(默认为false)
Controller编写
Callable返回类型,自动放入线程池中执行,等待返回值写入DeferredResult返回类型,在另一个线程中调用setResult()将返回的值写入。此方法更加灵活,可以设置超时时间、正常响应、错误响应
Filter中的配置
同理,需要在web.xml中对filter的定义增加async-supported配置
注意
异步使用的是不同线程,因此执行的事务不是同一个,在Controller中绑定的ThreadLocal信息也无法在异步线程中获取。
Servlet3.0 支持的异步在处理高并发异步请求时,效率并不高。因为其实没有用到“原生”的异步。Java提供的NIO是标准的异步,但是编程复杂性更高。因此,要实现更高性能的异步IO,一般使用Netty这样的框架(基于NIO提供了更易于使用的API)。
使用WebSocket
WebSocket是一种基于HTTP的长链接技术,连接确认后此连接不会被服务器关闭,可随时互相发消息。
实现
浏览器发送升级为WebSocket的请求头
|
|
和服务器握手成功即建立WebSocket连接。服务器也需要底层支持,Java的Servlet规范从3.1开始支持WebSocket。最新版本的Tomcat、Jetty等开源服务器均支持WebSocket。
服务端代码实现
这部分先略,用到了再补充