文章目录
- 1. SpringMVC 概述
- 2. 使用 @RequestMapping 映射请求
- 3. @PathVariable 映射 URL 绑定的占位符
- 4. REST
- 5. 请求处理方法签名
- 6. 使用 @RequestParam 绑定请求参数值
- 7. 使用 @RequestHeader 绑定请求报头的属性值
- 8. 使用 @CookieValue 绑定请求中的 Cookie 值
- 9. 使用 POJO 对象绑定请求参数值
- 10. MVC 的 Handler 方法可以接受
- 11. 处理模型数据
- 12. Spring MVC如何解析视图
- 13. 关于重定向
- 14. Spring 的表单标签
- 15. 处理静态资源
- 16. 数据绑定流程
- 17. Springmvc自带转换器类型(部分)
- 18. 自定义类型转换器
- 19. 关于 mvc:annotation-driven
- 20. @InitBinder
- 21. 数据格式化
- 22. 校验
- 23. 提示消息的国际化
- 24. 处理 JSON
- 25. HttpMessageConverter\
1. SpringMVC 概述
-
Spring 为展现层提供的基于 MVC设计理念的优秀的Web 框架,是目前最主流的MVC 框架之一
-
Spring3.0 后全面超越 Struts2,成为最优秀的 MVC框架
-
Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。
-
支持 REST 风格的 URL请求
-
采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性
2. 使用 @RequestMapping 映射请求
-
Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求 ()
-
在控制器的类定义及方法定义处都可标注
- @RequestMapping
- 类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
- 方法处:提供进一步的细分映射信息。相对于类定义处的 URL。若类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于WEB 应用的根目录**
-
DispatcherServlet 截获请求后,就通过控制器上@RequestMapping 提供的映射信息确定请求所对应的处理方法。
示例:
@Controller
public class Helloworld {
@RequestMapping("/helloworld")
public String hello() {
System.out.println("hello");
return "success";
}
}
2.1 映射请求参数、请求方法或请求头
-
@RequestMapping 除了可以使用请求 URL 映射请求外,还可以使用请求方法、请求参数及请求头映射请求
-
@RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可让请求映射更加精确化。
-
params 和 headers支持简单的表达式:
- param1: 表示请求必须包含名为 param1 的请求参数
- !param1: 表示请求不能包含名为 param1 的请求参数
- param1 != value1: 表示请求包含名为 param1 的请求参数,但其值不能为 value1
- {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
示例:
2.2 Maping支持通配符
-
Ant 风格资源地址支持 3 种匹配符:
- ?:匹配文件名中的一个字符
- *:匹配文件名中的任意字符
- **:** 匹配多层路径
-
@RequestMapping 还支持 Ant 风格的 URL:
-
/user/*/createUser: 匹配
/user/aaa/createUser、/user/bbb/createUser 等 URL
-
/user//createUser: 匹配
/user/createUser、/user/aaa/bbb/createUser 等 URL
-
/user/createUser??: 匹配
/user/createUseraa、/user/createUserbb 等 URL
-
3. @PathVariable 映射 URL 绑定的占位符
-
带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
-
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable(“xxx”) 绑定到操作方法的入参中。
4. REST
-
REST: 即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
-
资源(Resources): 网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要 获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识 别符。
-
表现层(Representation): 把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格 式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
-
状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“ 状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “ 表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动 词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
示例:
- /order/1 HTTP GET :得到 id = 1 的 order
- /order/1 HTTP DELETE:删除 id = 1的 order
- /order/1 HTTP PUT:更新id = 1的 order
- /order HTTP POST:新增 order
HiddenHttpMethodFilter:浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不支 持,Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与DELETE 请求。
5. 请求处理方法签名
- Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应人参中。
- Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。
- 必要时可以对方法及方法入参标注相应的注解( @PathVariable、@RequestParam、@RequestHeader 等)、Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理。
6. 使用 @RequestParam 绑定请求参数值
- 在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
- value:参数名
- required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
- defaultValue请求参数的默认值
7. 使用 @RequestHeader 绑定请求报头的属性值
请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中
8. 使用 @CookieValue 绑定请求中的 Cookie 值
@CookieValue 可让处理方法入参绑定某个 Cookie 值
9. 使用 POJO 对象绑定请求参数值
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
级联属性:对象中的成员属性对象
10. MVC 的 Handler 方法可以接受
哪些 ServletAPI 类型的参数
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Locale
- InputStream
- OutputStream
- Reader
- Writer
直接写在hander方法的参数部分即可
11. 处理模型数据
Spring MVC 提供了以下几种途径输出模型数据:
-
ModelAndView: 处理方法返回值类型为ModelAndView时, 方法体即可通过该对象添加模型数据
-
Map 及 Model: 入参为org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
-
@SessionAttributes: 将模型中的某个属性暂存到HttpSession 中,以便多个请求之间可以共享这个属性
-
@ModelAttribute: 方法入参标注该注解后, 入参的对象
就会放到数据模型中
11.1 ModelAndView
-
控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。
-
添加模型数据:
- MoelAndView addObject(String attributeName, Object attributeValue) (SpringMVC会把ModelAndView的model中数据放入到 request域对象中、可以使用requestScope取出)
- ModelAndView addAllObject(Map<String, ?> modelMap)
-
设置视图:
- void setView(View view)
- void setViewName(String viewName)
Springmvc无论hander返回的是什么类型,都会封装成ModelAndView
11.2 Map 及 Model
-
Spring MVC 在内部使用了一个org.springframework.ui.Model 接口存储模型数据
-
具体步骤
-
Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
-
目标方法可以添加Map类型(实际上也可以是Model类型或ModelMap类型)的参数。
-
如果方法的入参为 Map 或 Model 类 型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据
-
属性默认传递到request域里
-
11.3 @SessionAttributes
-
还是使用Map传递属性
-
若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。(当然request域中的属性还在)
-
@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是value 属性值),还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中 (实际上使用的是types 属性值)
-
@SessionAttributes(types=User.class) 会将隐含模型中所有类型 为 User.class 的属性添加到会话中。
- @SessionAttributes(value={“user1”, “user2”})
- @SessionAttributes(types={User.class, Dept.class})
- @SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
-
注意:该注解只能放在类的上面。 而不能修饰方法.
11.4 @ModelAttribute
- 在方法定义上使用 @ModelAttribute 注解:Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标注了
@ModelAttribute 的方法。
- 注意:在@ModelAttribute修饰的方法中,放入到Map时的键需要和目标方法入参类型的第一个字母小写的字符串一致!
- @ModelAttribute注解也可以来修饰目标方法POJO类型的入参,其value属性值有如下的作用:
SpringMVC会使用value属性值在implicitModel中查找对应的对象,若存在则会直接传入到目标方法的入参中。
11.5 SpringMVC确定目标方法POJO类型入参的过程
- 确定一个key:若目标方法的P0JO类型的参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写,若使用了@ModelAttribute 来修饰,则key为@ModelAttribute注解的value属性值
- 在implicitModel中查找key对应的对象,若存在,则作为入参传入
- 若implicitModel中不存在key对应的对象,则检查当前的Handler是否使用@SessionAttributes注解修饰,
若使用了该注解,且@SessionAttributes注解的value属性值中包含了key,则会从HttpSession中来获取key所对应的value值,若存在则直接传入到目标方法的入参中。若不存在则将抛出异常. - 若Handler没有标识@SessionAttributes注解或@Sess ionAttributes注解的value值中不包含key,则
会通过反射来创建P0JO类型的参数,传入为目标方法的参数 - SpringMVC 会把key和value保存到implicitModel中,进而会保存到request中.
12. Spring MVC如何解析视图
-
请求处理方法执行完成后,最终返回一个 ModelAndView对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView 对象,它包含了逻辑名和模型对象的视图
-
Spring MVC 借助视图解析器**(**ViewResolver)得到最终 的视图对象(View),最终的视图可以是 JSP ,也可能是Excel、JFreeChart 等各种表现形式的视图
-
对于最终究竟采取何种视图对象对模型数据进行渲染,s处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦
13. 关于重定向
-
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
-
如果返回的字符串中带 forward: 或 redirect: 前缀 时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理
-
redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
-
forward:success.jsp:会完成一个到 success.jsp 的转发操作
14. Spring 的表单标签
通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
14.1 form 标签
- 一般情况下,通过 GET 请求获取表单页面,而通过POST 请求提交表单页面,因此获取表单页面和提交表单
页面的 URL 是相同的。只要满足该最佳条件的契约,<form:form> 标签就无需通过 action 属性指定表单提交的 URL
- 可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取command 的表单 bean,如果该属性值也不存在,则会 发生错误。
14.2 表单标签
SpringMVC 提供了多个表单组件标签,如
-
<form:input/>、<form:select/> 等,用以绑定表单字段的属性值,它们的共有属性如下:
- path:表单字段,对应 html 元素的 name 属性,支持级联属性
- htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 true
- cssClass:表单组件对应的 CSS 样式类名
- cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式
-
form:input、form:password、form:hidden、form:textarea, 对应 HTML 表单的 text、password、hidden、textarea 标签
-
form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中
-
form:radiobuttons:单选框组标签,用于构造多个单选框
- items:可以是一个 List、String[] 或 Map
- itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
- itemLabel:指定 radio 的 label 值
- delimiter:多个单选框可以通过 delimiter 指定分隔符
-
form:checkbox:复选框组件。用于构造单个复选框
-
form:checkboxs:用于构造多个复选框。使用方式同form:radiobuttons 标签
-
form:select:用于构造下拉框组件。使用方式同form:radiobuttons 标签
-
form:option:下拉框选项组件标签。使用方式同form:radiobuttons 标签
-
form:errors:显示表单组件或数据校验所对应的错误
- <form:errors path= “ ” /> :显示表单所有的错误
- <form:errors path= “ user” /> :显示所有以 user 为前缀的属性对应的错误
- <form:errors path= “ username” /> :显示特定表单对象属性的错误
15. 处理静态资源
优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀
-
若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理,因找不到对应处理器将导致错误。
-
可以在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/> 的方式解决静态资源的问题:
-
<mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的 请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理
-
一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定
16. 数据绑定流程
-
Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
-
DataBinder 调用装配在 Spring MVC 上下文中的ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中
-
调用 Validator 组件对已经绑定了请求消息的入参对象 进行数据合法性校验,并最终生成数据绑定结果BindingData 对象
-
Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参
17. Springmvc自带转换器类型(部分)
-
java.lang.Boolean -> java.lang.String
-
java.lang.Character -> java.lang.Number
-
java.lang.Character -> java.lang.String
-
java.lang.Enum -> java.lang.String
-
java.lang.Number -> java.lang.Character
-
java.lang.Number -> java.lang.Number
-
java.lang.Number -> java.lang.String
-
java.lang.String -> java.lang.Boolean
-
java.lang.String -> java.lang.Character
-
java.lang.String -> java.lang.Enum
-
java.lang.String -> java.lang.Number
-
java.lang.String -> java.util.Locale
-
java.lang.String -> java.util.Properties
-
java.lang.String -> java.util.UUID
-
java.util.Locale -> java.lang.String
-
java.util.Properties -> java.lang.String
-
java.util.UUID -> java.lang.String
18. 自定义类型转换器
-
ConversionService 是 Spring 类型转换体系的核心接口。
-
可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC 容器中定义一个 ConversionService. Spring 将自动识别出IOC 容器中的 ConversionService,并在 Bean 属性配置及Spring MVC 处理方法入参绑定等场合使用它进行数据的转换
-
可通过 ConversionServiceFactoryBean 的 converters 属性注册自定义的类型转换器
Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactroyBean 中:
-
Converter<S,T>(一般用这种):将 S 类型对象转为 T 类型对象
-
ConverterFactory:将相同系列多个 “同质” Converter 封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将 String 转换为 Number 及 Number 子类 (Integer、Long、Double 等)对象)可使用该转换器工厂类
-
GenericConverter:会根据源类对象及目标类对象所在的宿主类 中的上下文信息进行类型转换
- <mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的 ConversionService 注册到Spring MVC 的上下文中
19. 关于 mvc:annotation-driven
- <mvc:annotation-driven /> 会自动注 册RequestMappingHandlerMapping、RequestMappingHandlerAdapter 与
ExceptionHandlerExceptionResolver 三个bean。
- 还将提供以下支持:
- 支持使用 ConversionService 实例对表单参数进行类型转换
- 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化
- 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
- 支持使用 @RequestBody 和 @ResponseBody 注解
20. @InitBinder
-
由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定
-
@InitBinder方法不能有返回值,它必须声明为void。
-
@InitBinder方法的参数通常是是 WebDataBinder
21. 数据格式化
-
对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴。
-
Spring 在格式化模块中定义了一个实现ConversionService 接口的FormattingConversionService 实现类,该实现类扩展 了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能
-
FormattingConversionService 拥有一个FormattingConversionServiceFactroyBean 工厂类,后者用于在 Spring 上下文中构造前者
-
FormattingConversionServiceFactroyBean 内部已经注册了 :
-
NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用 @NumberFormat 注解
-
JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用 @DateTimeFormat 注解
-
装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动了。<mvc:annotation-driven/> 默认创建的ConversionService 实例即为FormattingConversionServiceFactroyBean
21.1 日期格式化
- @DateTimeFormat 注解可对java.util.Date、java.util.Calendar、java.long.Long 时间类型进行标注:
- pattern 属性:类型为字符串。指定解析/格式化字段数据的模式,如:”yyyy-MM-dd hh:mm:ss”
- iso 属性:类型为 DateTimeFormat.ISO。指定解析/格式化字段数据的ISO模式,包括四种:ISO.NONE(不使用) – 默 认、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)、ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
- style 属性:字符串类型。通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式:S:短日期/时间格式、M:中日期/时间格式、L:长日期/时间格式、F:完整日期/时间格式、-:忽略日期或时间格式
21.2 数值格式化
- @NumberFormat 可对类似数字类型的属性进行标注,它拥有两个互斥的属性:
- style:类型为 NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)
- pattern:类型为 String,自定义样式,如patter="#,###";
22. 校验
22.1 JSR 303
-
JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 .
-
JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证
22.2 Hibernate Validator 扩展注解
- Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解
22.3 Spring MVC 数据校验
-
Spring 4.0 拥有自己独立的数据校验框架,同时支持 JSR 303 标准的校验框架。
-
Spring 在进行数据绑定时,可同时调用校验框架完成数据校验工作。在 Spring MVC 中,可直接通过注解驱动的方式进行数据校验
-
Spring 的 LocalValidatorFactroyBean 既实现了 Spring 的Validator 接口,也实现了 JSR 303 的 Validator 接口。只要在 Spring 容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean 中。
-
Spring 本身并没有提供 JSR303 的实现,所以必须将JSR303 的实现者的 jar 包放到类路径下。
-
<mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标 注 @valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作
-
在已经标注了 JSR303 注解的表单/命令对象前标注一个@Valid,Spring MVC 框架在将请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验
-
Spring MVC 是通过对处理方法签名的规约来保存校验结果的:前一个表单/命令对象的校验结果保存到随后的入参中,这个保存校验结果的入参必须是 BindingResult 或Errors 类型,这两个类都位于org.springframework.validation 包中
22.4 在目标方法中获取校验结果
-
在表单/命令对象类的属性中标注校验注解,在处理方法对 应的入参前添加 @Valid,Spring MVC 就会实施校验并将校验结果保存在被校验入参对象之后的 BindingResult 或Errors 入参中。
-
常用方法:
- FieldError getFieldError(String field)
- List<FieldError> getFieldErrors()
- Object getFieldValue(String field)
- Int getErrorCount()
23. 提示消息的国际化
-
每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 FieldError 对象。
-
当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为前缀,结合modleAttribute、属性名及属性类型名生成多个对应的消息代码:例如 User 类中的 password 属性标准了一个 @Pattern 注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4 个错误代码:
- Pattern.user.password
- Pattern.password
- Pattern.java.lang.String
- Pattern
-
当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认的错误消息,否则使用国际化消息。
-
若数据类型转换或数据格式转换时发生错误,或该有的参数不存在,或调用处理方法时发生错误,都会在隐含模型中创建错误消息。其错误代码前缀说明如下:
- required:必要的参数不存在。如 @RequiredParam(“param1”) 标注了一个入参,但是该参数不存在
- typeMismatch:在数据绑定时,发生数据类型不匹配的问题
- methodInvocation:Spring MVC 在调用处理方法时发生了错误
-
注册国际化资源文件
24. 处理 JSON
- 加入 jar 包
-
编写目标方法,使其返回 JSON 对应的对象或集合
-
在方法上添加 @ResponseBody 注解
25. HttpMessageConverter<T>
-
HttpMessageConverter 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息
-
HttpMessageConverter接口定义的方法:
- Boolean canRead(Class<?> clazz,MediaType mediaType): 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)
- Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型 在MediaType 中定义。
- LIst<MediaType> getSupportMediaTypes():该转换器支持的媒体类型。
- T read(Class<? extends T> clazz,HttpInputMessage inputMessage): 将请求信息流转换为 T 类型的对象。
- void write(T t,MediaType contnetType,HttpOutputMessgaeoutputMessage):将T类型的对象写到响应流中,同时指定相应的媒体类 型为 contentType。
25.1 使用 HttpMessageConverter<T>
-
使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:
- 使用 @RequestBody / @ResponseBody 对处理方法进行标注
- 使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的入参或返回值
-
当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity/ResponseEntity 时, Spring 首先根据请求头或响应头的Accept 属性选择匹配的 HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错
-
@RequestBody 和 @ResponseBody 不需要成对出现
25.2 @RequestBody、@ResponseBody 示例
26. 国际化概述
-
默认情况下,SpringMVC 根据 Accept-Language 参数判断客户端的本地化类型。
-
当接受到请求时,SpringMVC 会在上下文中查找一个本地化解析器(LocalResolver),找到后使用它获取请求 所对应的本地化类型信息。
-
SpringMVC 还允许装配一个动态更改本地化类型的拦截器,这样通过指定一个请求参数就可以控制单个请求的本地化类型。
26.1 本地化解析器和本地化拦截器
-
AcceptHeaderLocaleResolver:根据 HTTP 请求头的Accept-Language 参数确定本地化类型,如果没有显式定义本地化解析器, SpringMVC 使用该解析器。
-
CookieLocaleResolver:根据指定的 Cookie 值确定本地化类型
-
SessionLocaleResolver:根据 Session 中特定的属性确定本地化类型
-
LocaleChangeInterceptor:从请求参数中获取本次请求对应的本地化类型。
27. 文件上传
-
Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的。Spring 用Jakarta Commons FileUpload 技术实现了一个MultipartResolver 实现类:CommonsMultipartResovler
-
Spring MVC 上下文中默认没有装配 MultipartResovler,因此默认情况下不能处理文件的上传工作,如果想使用 Spring 的文件上传功能,需现在上下文中配置 MultipartResolver
27.1 配置 MultipartResolver
-
defaultEncoding: 必须和用户 JSP 的 pageEncoding 属性一致,以便正确解析表单的内容
-
为了让 CommonsMultipartResovler 正确工作,必须先 将 Jakarta Commons FileUpload 及 Jakarta Commons io的类包添加到类路径下。
27.2 文件上传示例
28. 自定义拦截器
- Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口
- preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果程序员决定该拦截器对 请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件 去处理请求,则返回false。
- postHandle():这个方法在业务处理器处理完请求后,但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对 用户请求request进行处理。
- afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
28.1 拦截器方法执行顺序
如果有一个拦截器的preHandle返回的是true,则一定会执行这个拦截器的afterCompletion释放资源
28.2 配置自定义拦截器
28.3 对指定请求启用拦截器
29. 异常处理
-
Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。
-
SpringMVC 提供的 HandlerExceptionResolver 的实现类
29.1 ExceptionHandlerExceptionResolver
-
主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
-
@ExceptionHandler 注解定义的方法优先级问题:例如发生的是NullPointerException,但是声明的异常有RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个 @ExceptionHandler注解方法,即标记了 RuntimeException 的方法
-
ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的 @ExceptionHandler 注解方法
-
在@ExceptionHandler方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象
-
@ExceptionHandler方法的入参中不能传入Map.若希望把异常信息传导页面上,需要使用ModelAndView作为返回值
-
@ExceptionHandler方法标记的异常有优先级的问题.(越具体越优先)
-
@ControllerAdvice: 如果在当前Handler中找不到@ExceptionHandler方法来出来当前方法出现的异常,则将去@ControllerAdvice标记的类中查找@ExceptionHandler标记的方法来处理异常.
29.2 ResponseStatusExceptionResolver
-
在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
-
定义一个 @ResponseStatus 注解修饰的异常类
- 若在处理器方法中抛出了上述异常: 若ExceptionHandlerExceptionResolver 不解析述异常。由于触发的异常 UnauthorizedException 带有@ResponseStatus注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。关于其他的响应码请参考 HttpStatus 枚举类型源码。
29.3 DefaultHandlerExceptionResolver
- 对一些特殊的异常进行处理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
29.4 SimpleMappingExceptionResolver
- 如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常,SpringMVC会自动将exception传入到页面中