Spring MVC 学习总结 一共 3 篇 分别为


一、视图和视图解析器


1.  简介

  • 请求处理方法执行完成后,最终返回一个 ModelAndView对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView 对象,它包含了逻辑名和模型对象的视图

  • Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是Excel、JFreeChart 等各种表现形式的视图

  • 对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦


2.  视图

  • 视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。

  • 为了实现视图模型和具体实现技术的解耦,Spring 在org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口:

  • 视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题


3.  常用的视图实现类


4.  视图解析器

  • SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。

  • 视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。

  • 所有的视图解析器都必须实现 ViewResolver 接口:



5.   常用的视图解析器实现类

  • 程序员可以选择一种视图解析器或混用多种视图解析器。

  • 每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。

  • SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常。


6.  InternalResourceViewResolver

  • JSP 是最常见的视图技术,可以使用InternalResourceViewResolver 作为视图解析器:

  • 若项目中使用了 JSTL,则 SpringMVC 会自动把视图由InternalResourceView 转为 JstlView

  • 若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中配置国际化资源文件

<!-- 配置国际化资源文件 -->
<bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
	<property name="basename" value="i18n"></property>	
</bean>
  • 若希望直接响应通过 SpringMVC 渲染的页面,可以使用 mvc:viewcontroller标签实现

<!-- 配置直接转发的页面 -->
<!-- 可以直接相应转发的页面, 而无需再经过 Handler 的方法.  -->
<mvc:view-controller path="/success" view-name="success"/>
	
<!-- 在实际开发中通常都需配置 mvc:annotation-driven 标签
(否则无法映射原@RequestMapping)
 -->
<mvc:annotation-driven></mvc:annotation-driven>


7.  BeanNameViewResolver

  • 自定义View : HelloView.java

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;
@Component
public class HelloView implements View{
	
  @Override
  public String getContentType() {
    return "text/html";
  }

  @Override
  public void render(Map<String, ?> model, HttpServletRequest request,
    HttpServletResponse response) throws Exception {
      response.getWriter().print("hello view, time: " + new Date());
  }
	
}
  • 在spring mvc 配置文件添加

<!-- 配置视图  BeanNameViewResolver 解析器: 使用视图的名字来解析视图 -->
<!-- 通过 order 属性来定义视图解析器的优先级, order 值越小优先级越高 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <property name="order" value="100"></property>
</bean>


8.  Excel 视图

  • 若希望使用 Excel 展示数据列表,仅需要扩展SpringMVC 提供的 AbstractExcelView 或AbstractJExcel View 即可。实现 buildExcelDocument()方法,在方法中使用模型数据对象构建 Excel 文档就可以了。

  • AbstractExcelView 基于 POI API,而AbstractJExcelView 是基于 JExcelAPI 的。

  • 视图对象需要配置 IOC 容器中的一个 Bean,使用BeanNameViewResolver 作为视图解析器即可

  • 若希望直接在浏览器中直接下载 Excel 文档,则可以设置响应头 Content-Disposition 的值为attachment;filename=xxx.xls


9.  关于重定向

  • 一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理

  • 如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理

    – redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作

    – forward:success.jsp:会完成一个到 success.jsp 的转发操作

  • 内部源码:



二、 使用 Spring 的表单标签

    通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显


1. form 标签

  • 一般情况下,通过 GET 请求获取表单页面,而通过POST 请求提交表单页面,因此获取表单页面和提交表单页面的 URL 是相同的。只要满足该最佳条件的契约,<form:form> 标签就无需通过 action 属性指定表单提交的 URL

  • 可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取command 的表单 bean,如果该属性值也不存在,则会发生错误。


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” /> :显示特定表单对象属性的错误


3.  示例 

<form:form modelAttribute="contentModel" method="post">     
        
        input 标签:<form:input path="username"/><br/>
        password 标签:<form:password path="password"/><br/>
        绑定boolean的checkbox 标签:<br/>
        <form:checkbox path="testBoolean"/><br/>
        绑定Array的checkbox 标签:<br/>
        <form:checkbox path="testArray" value="arrayItem 路人甲"/>arrayItem 路人甲           
        <form:checkbox path="testArray" value="arrayItem 路人乙"/>arrayItem 路人乙           
        <form:checkbox path="testArray" value="arrayItem 路人丙"/>arrayItem 路人丙           
        <form:checkbox path="testArray" value="arrayItem 路人丁"/>arrayItem 路人丁<br/>
        绑定Array的checkboxs 标签:<br/>
        <form:checkboxes path="selectArray" items="${contentModel.testArray}"/><br/>
        绑定Map的checkboxs 标签:<br/>
        <form:checkboxes path="selectIds" items="${contentModel.testMap}"/><br/>
        绑定Integer的radiobutton 标签:<br/>
        <form:radiobutton path="radiobuttonId" value="0"/>0        
        <form:radiobutton path="radiobuttonId" value="1"/>1        
        <form:radiobutton path="radiobuttonId" value="2"/>2<br/>
        绑定Map的radiobuttons 标签:<br/>
        <form:radiobuttons path="selectId" items="${contentModel.testMap}"/><br/>
        绑定Map的select 标签:<br/>
        <form:select path="selectId" items="${contentModel.testMap}"/><br/>
        不绑定items数据直接在form:option添加的select 标签:<br/>
        <form:select path="selectId">  
           <option>请选择人员</option>
           <form:option value="1">路人甲</form:option>
           <form:option value="2">路人乙</form:option>
           <form:option value="3">路人丙</form:option>
        </form:select><br/>
        不绑定items数据直接在html的option添加的select 标签:<br/>
        <form:select path="selectId">  
           <option>请选择人员</option> 
           <option value="1">路人甲</option>
           <option value="2">路人乙</option>
           <option value="3">路人丙</option>  
        </form:select><br/>
        用form:option绑定items的select 标签:<br/>
        <form:select path="selectId">  
            <option/>请选择人员            
            <form:options items="${contentModel.testMap}"/>  
        </form:select><br/>
        textarea 标签:        
        <form:textarea path="remark"/><br/>

        <input type="submit" value="Submit" />
        
</form:form>


三、处理静态资源

  • 优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀

  • 若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理,因找不到对应处理器将导致错误。

  • 可以在 SpringMVC 的配置文件中配置 <mvc:default-servlethandler/> 的方式解决静态资源的问题:

    – <mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理

    – 一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的WEB 服务器的默认 Servlet 名称不是 default,则需要通过 defaultservlet-name属性显式指定

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

	<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="me.ziry.springmvc"></context:component-scan>

	<!-- 配置视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
	
	<!--  
	default-servlet-handler 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,
	它会对进入 DispatcherServlet 的请求进行筛查, 如果发现是没有经过映射的请求, 
	就将该请求交由 WEB 应用服务器默认的Servlet 处理. 
	如果不是静态资源的请求,才由 DispatcherServlet 继续处理

	一般 WEB 应用服务器默认的 Servlet 的名称都是 default.
	若所使用的 WEB 服务器的默认 Servlet 名称不是 default,
	则需要通过 default-servlet-name 属性显式指定
	
	-->
	<mvc:default-servlet-handler/>

	<mvc:annotation-driven ></mvc:annotation-driven>	
		
</beans>


四、 数据绑定

1.  数据绑定流程

  • Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象

  • DataBinder 调用装配在 Spring MVC 上下文中的ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中

  • 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData 对象

  • Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参


2.  数据绑定运行机制

  • Spring MVC 通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是DataBinder,运行机制如下:


3.  数据转换

  • Spring MVC 上下文中内建了很多转换器,可完成大多数 Java 类型的转换工作。 

  • ConversionService converters =

    – java.lang.Boolean -> java.lang.String :org.springframework.core.convert.support.ObjectToStringConverter@f874ca

    – java.lang.Character -> java.lang.Number : CharacterToNumberFactory@f004c9

    – java.lang.Character -> java.lang.String : ObjectToStringConverter@68a961

    – java.lang.Enum -> java.lang.String : EnumToStringConverter@12f060a

    – java.lang.Number -> java.lang.Character : NumberToCharacterConverter@1482ac5

    – java.lang.Number -> java.lang.Number : NumberToNumberConverterFactory@126c6f

    – java.lang.Number -> java.lang.String : ObjectToStringConverter@14888e8

    – java.lang.String -> java.lang.Boolean : StringToBooleanConverter@1ca6626

    – java.lang.String -> java.lang.Character : StringToCharacterConverter@1143800

    – java.lang.String -> java.lang.Enum : StringToEnumConverterFactory@1bba86e

    – java.lang.String -> java.lang.Number : StringToNumberConverterFactory@18d2c12

    – java.lang.String -> java.util.Locale : StringToLocaleConverter@3598e1

    – java.lang.String -> java.util.Properties : StringToPropertiesConverter@c90828

    – java.lang.String -> java.util.UUID : StringToUUIDConverter@a42f23

    – java.util.Locale -> java.lang.String : ObjectToStringConverter@c7e20a

    – java.util.Properties -> java.lang.String : PropertiesToStringConverter@367a7f

    – java.util.UUID -> java.lang.String : ObjectToStringConverter@112b07f ……


五、自定义类型转换器(了解就好)

1.  介绍 

  • ConversionService 是 Spring 类型转换体系的核心接口。

  • 可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC容器中定义一个 ConversionService. Spring 将自动识别出IOC 容器中的 ConversionService,并在 Bean 属性配置及Spring MVC 处理方法入参绑定等场合使用它进行数据的转换

  • 可通过 ConversionServiceFactoryBean 的 converters 属性注册自定义的类型转换器

<!-- 配置 ConversionService -->
<bean id="conversionService"
    class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <ref bean="employeeConverter"/>
        </set>
    </property>	
</bean>


2.  Spring 支持的转换器

  • Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到 ConversionServiceFactroyBean 中:

    – Converter<S,T>:将 S 类型对象转为 T 类型对象

    – ConverterFactory:将相同系列多个 “同质” Converter 封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将 String 转换为 Number 及 Number 子类(Integer、Long、Double 等)对象)可使用该转换器工厂类

    – GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换


3.  自定义转换器示例

  • EmployeeConverter.java

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
@Component
public class EmployeeConverter 
    implements Converter<String, Employee> {
@Override
public Employee convert(String source) {
  if(source != null){
    String [] vals = source.split("-");
    if(vals != null && vals.length == 4){
      String lastName = vals[0];
      String email = vals[1];
      Integer gender = Integer.parseInt(vals[2]);
      Department department = new Department();
      department.setId(Integer.parseInt(vals[3]));
      Employee employee = 
        new Employee(null, lastName, email, gender, department);
      System.out.println(source + "--convert--" + employee);
      return employee;
    }
  }
  return null;
}
}
  • springmvc.xml

<mvc:annotation-driven conversion-service="conversionService"/>

<!-- 配置 ConversionService -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <ref bean="employeeConverter"/>
        </set>
    </property>
</bean>
  • 对应Handler

@RequestMapping("/testConversionServiceConverer")
public String testConverter(
    @RequestParam("employee") Employee employee){
    System.out.println("save: " + employee);
    employeeDao.save(employee);
    return "redirect:/emps";
}


六、mvc:annotation-driven

  • <mvc:annotation-driven /> 会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter 与ExceptionHandlerExceptionResolver三个bean。

  • 还将提供以下支持:

    – 支持使用 ConversionService 实例对表单参数进行类型转换

    – 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化

    – 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证

    – 支持使用 @RequestBody 和 @ResponseBody 注解

  • 区别


七、 @InitBinder

由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定

  • @InitBinder方法不能有返回值,它必须声明为void。

  • @InitBinder方法的参数通常是是 WebDataBinder

/**
* 不自动绑定对象中的 roleSet 属性,另行处理。
*/
@InitBinder
public void initBinder(WebDataBinder binder){
    binder.setDisallowedFields("roleSet");
}


八、 数据格式化

1. 介绍

  • 对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴。

  • Spring 在格式化模块中定义了一个实现ConversionService 接口的FormattingConversionService 实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能

  • FormattingConversionService 拥有一个FormattingConversionServiceFactroyBean 工厂类,后者用于在 Spring 上下文中构造前者

  • FormattingConversionServiceFactroyBean 内部已经注册了 :

    – NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用 @NumberFormat 注解

    – JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用 @DateTimeFormat 注解

  • 装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动了。<mvc:annotation-driven/> 默认创建的ConversionService 实例即为FormattingConversionServiceFactroyBean

<mvc:annotation-driven ></mvc:annotation-driven>


2.  日期格式化

  • @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:完整日期/时间格式、-:忽略日期或时间格式

@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;


3.  数值格式化

  • @NumberFormat 可对类似数字类型的属性进行标注,它拥有两个互斥的属性:

    – style:类型为 NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)

    – pattern:类型为 String,自定义样式,如patter="#,###";

  • 示例

@NumberFormat(pattern="#,###,###.#")
private Float salary;


九、JSR 303

1. 介绍

  • JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 .

  • JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对 Bean进行验证

注解功能说明
@Null被注释的元素必须为 null
@NotNull被注释的元素必须不为 null
@AssertTrue被注释的元素必须为 true
@AssertFalse被注释的元素必须为 false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式

 

2. Hibernate Validator 扩展注解

  • Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解

注解功能说明
@Email被注释的元素必须是电子邮箱地址
@Length被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的字符串的必须非空
@Range被注释的元素必须在合适的范围内

 

十 、 Spring MVC 数据校验

1. 介绍

  • Spring 4.0 拥有自己独立的数据校验框架,同时支持 JSR303 标准的校验框架。

  • Spring 在进行数据绑定时,可同时调用校验框架完成数据校验工作。在 Spring MVC 中,可直接通过注解驱动的方式进行数据校验

  • Spring 的 LocalValidatorFactroyBean 既实现了 Spring 的Validator 接口,也实现了 JSR 303 的 Validator 接口。只要在 Spring 容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean 中。

  • Spring 本身并没有提供 JSR303 的实现,所以必须将JSR303 的实现者的 jar 包放到类路径下。

    链接:http://pan.baidu.com/s/1pLB3M6v 密码:4ude

  • <mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标注 @valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作

  • 在已经标注了 JSR303 注解的表单/命令对象前标注一个@Valid,Spring MVC 框架在将请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验

  • Spring MVC 是通过对处理方法签名的规约来保存校验结果的:前一个表单/命令对象的校验结果保存到随后的入参中,这个保存校验结果的入参必须是 BindingResult 或Errors 类型,这两个类都位于org.springframework.validation 包中

  • 需校验的 Bean 对象和其绑定结果对象或错误对象时成对出现的,它们之间不允许声明其他的入参

  • Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或getFieldErrors(String field)

  • BindingResult 扩展了 Errors 接口


2.  在目标方法中获取校验结果

  • 在表单/命令对象类的属性中标注校验注解,在处理方法对应的入参前添加 @Valid,Spring MVC 就会实施校验并将校验结果保存在被校验入参对象之后的 BindingResult 或Errors 入参中。

  • 常用方法:

    – FieldError getFieldError(String field)

    – List<FieldError> getFieldErrors()

    – Object getFieldValue(String field)

    – Int getErrorCount()


3. 在页面上显示错误

  • Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,还会将所有校验结果保存到 “隐含模型”

  • 即使处理方法的签名中没有对应于表单/命令对象的结果入参,校验结果也会保存在 “隐含对象” 中。

  • 隐含模型中的所有数据最终将通过 HttpServletRequest 的属性列表暴露给 JSP 视图对象,因此在 JSP 中可以获取错误信息

  • 在 JSP 页面上可通过 <form:errors path=“userName”>显示错误消息

  • 示例


4. 提示消息的国际化

  • 每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 FieldError 对象。

  • 当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为前缀,结合modleAttribute、属性名及属性类型名生成多个对应的消息代码:例如 User 类中的 password 属性标准了一个 @Pattern 注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4个错误代码: 

    – Pattern.user.password

    – Pattern.password

    – Pattern.java.lang.String

    – Pattern

    示例 :i18n.properties 

Pattern.user.password=提示语
Email.user.email=This is not a Email
  • 当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认的错误消息,否则使用国际化消息。

  • 若数据类型转换或数据格式转换时发生错误,或该有的参数不存在,或调用处理方法时发生错误,都会在隐含模型中创建错误消息。其错误代码前缀说明如下:

    – required:必要的参数不存在。如 @RequiredParam(“param1”)标注了一个入参,但是该参数不存在

    – typeMismatch:在数据绑定时,发生数据类型不匹配的问题

    – methodInvocation:Spring MVC 在调用处理方法时发生了错误

  • 注册国际化资源文件

<!-- 配置国际化资源文件 -->
<bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="i18n"></property>
</bean>


十一、 处理 JSON

1. 加入 jar 包:

2. 编写目标方法,使其返回 JSON 对应的对象或集合

3. 在方法上添加 @ResponseBody 注解

@ResponseBody
@RequestMapping("/testJson")
public List<User> testJson(){
    List<User> users = new ArrayList<User>();
    users.add(new User(1,"ziry", new Date()));
    users.add(new User(2,"me", new Date()));
    return users;
}	


十二、 HttpMessageConverter<T>

  • HttpMessageConverter<T> 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息

  • HttpMessageConverter<T>接口定义的方法: – 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。


  • DispatcherServlet 默认装配RequestMappingHandlerAdapter ,而RequestMappingHandlerAdapter 默认装配如下HttpMessageConverter:


  • 加入 jackson jar 包后, RequestMappingHandlerAdapter装配的 HttpMessageConverter 如下:


  • 使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:

    – 使用 @RequestBody / @ResponseBody 对处理方法进行标注

    – 使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的入参或返回值

  • 当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时, Spring 首先根据请求头或响应头的Accept 属性选择匹配的 HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错

  • @RequestBody 和 @ResponseBody 不需要成对出现

  • @RequestBody、@ResponseBody 示例


  • HttpEntity、ResponseEntity 示例


十三、 国际化概述

1. 介绍

  • 默认情况下,SpringMVC 根据 Accept-Language 参数判断客户端的本地化类型。

  • 当接受到请求时,SpringMVC 会在上下文中查找一个本地化解析器(LocalResolver),找到后使用它获取请求所对应的本地化类型信息。

  • SpringMVC 还允许装配一个动态更改本地化类型的拦截器,这样通过指定一个请求参数就可以控制单个请求的本地化类型。


2. SessionLocaleResolver & LocaleChangeInterceptor 工作原理


3. 本地化解析器和本地化拦截器

  • AcceptHeaderLocaleResolver:根据 HTTP 请求头的Accept-Language 参数确定本地化类型,如果没有显式定义本地化解析器, SpringMVC 使用该解析器。

  • CookieLocaleResolver:根据指定的 Cookie 值确定本地化类型

  • SessionLocaleResolver:根据 Session 中特定的属性确定本地化类型

  • LocaleChangeInterceptor:从请求参数中获取本次请求对应的本地化类型。


4. 示例

  • springmvc.xml 增加

<!-- 配置国际化资源文件 -->
<bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="i18n"></property>
</bean>
	
<!-- 配置 SessionLocalResolver -->
<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
	
<mvc:interceptors>
    <!-- 配置 LocaleChanceInterceptor -->
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>


  • i18n_en_US.properties 英文配置文件

i18n.user=User
i18n.password=Password


  • i18n_zh_CN.properties 中文配置文件

i18n.user=用户名
i18n.password=密码


  • test.jsp 页面


<fmt:message key="i18n.user"></fmt:message>
<fmt:message key="i18n.password"></fmt:message>	
<br>
<a href="test?locale=zh_CH">中文</a>
<br>
<a href="test?locale=en_US">英文</a>



===Spring MVC 学习总结 一共 3 篇 分别为===


注意:本文归作者所有,未经作者允许,不得转载