SpringMVC知识点总结

来源:互联网 发布:淘宝女士短装长袖t恤 编辑:程序博客网 时间:2024/06/18 13:59

首先感谢尚硅谷老师的资源,这是我整理过后的笔记,希望能给各位带来帮助

由于知识点多,为了能够更加通俗易懂所以也弄了很多,

此为springmvc总结的第三篇,属于适应于特殊需求的,博客上还有前两篇

 

一、处理静态资源

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

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

比如:我现在要用jquery

<script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>

它是一个静态资源,springmvc在不配置情况下会因为是一个普通请求,因为找不到handler中对应的映射报错,所以我们需要在Spring的配置文件中配置

<!--

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>

 

二、数据类型转换

 

**自定义类型转换器

先了解数据类型绑定流程

• 1.Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给

     WebDataBinderFactory 实例,以创建 DataBinder 实例对象

• 2.DataBinder 调用装配在 Spring MVC 上下文中的ConversionService 组件

     进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中

• 3.调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,

      并最终生成数据绑定结果BindingData 对象

• 4.Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,

      将它们赋给处理方法的响应入参

 

 

知道springmvc为我们提供了哪些数据的转换

• 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 ……

 

**开始自定义类型转换器

• 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-drivenconversion-service=

“conversionService”/> 会将自定义的 ConversionService 注册到

Spring MVC 的上下文中

 

如:

需求:原有表单太过于繁琐,我们希望通过一个字符串就能填入多个内容,

         然后由后台来处理数据

写一个实现了Converter接口的类

public class EmployeeConverter implements Converter<String,Employee> {

 

@Override

public Employee convert(String source) {

    if(source != null){

       String [] vals = source.split("-");

       //GG-gg@atguigu.com-0-105

       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;

    }

}

 

 

<!--配置ConversionService -->

<bean id="conversionService"

这里的class是最简单的class,后面会有它的子类,更强           class="org.springframework.context.support.ConversionServiceFactoryBean">

       <property name="converters">

               <set>

                      <ref bean="employeeConverter"/>

               </set>

       </property>

</bean>

 

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

<bean id="conversionService"

          class="org.springframework.format.support.

         FormattingConversionServiceFactoryBean">

       <property name="converters">

               <set>

                      <ref bean="employeeConverter"/>

               </set>

       </property>

</bean>

 

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

 

**mvc:annotation-driven的介绍

前面我们一直使用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

如:设置不需要为lastName属性赋值,这种情况下你就算写了值传进来也不存,

当你的参数对象有一个属性不应该被传进来的值赋值时,如一个人有多个角色,传进来的是一个checkbox多选类型的id,没办法映射为集合,我们需要手工映射

@InitBinder

public void initBinder(WebDataBinder binder){

       binder.setDisallowedFields("lastName");

}

 

三、数据格式化

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

• Spring 在格式化模块中定义了一个实现ConversionService接口的

FormattingConversionService 实现类,该实现类扩展了GenericConversionService,

因此它既具有类型转换的功能,又具有格式化的功能

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

• FormattingConversionServiceFactroyBean 内部已经注册了 :

– NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性

   使用 @NumberFormat 注解

– JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型

   的属性使用 @DateTimeFormat 注解

• 装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动了。

<mvc:annotation-driven/> 默认创建的ConversionService 实例即为FormattingConversionServiceFactroyBean

• @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-ddhh:mm:ss.SSSZ)

– style 属性:字符串类型。通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式:S:短日期/时间格式、M:中日期/时间格式、L:长日期/时间格式、F:完整日期/时间格式、-:忽略日期或时间格式

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

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

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

 

如:

在你定义的类的属性上添加注释

@DateTimeFormat(pattern="yyyy-MM-dd")

private Date birth;

 

@NumberFormat(pattern="#,###,###.#")

private Float salary;

 

原来配置的conversionservice会影响这些注释所以我们需要把它的class变成原来class的子类

<bean id="conversionService"

          class="org.springframework.format.support.

         FormattingConversionServiceFactoryBean">

       <property name="converters">

               <set>

                      <ref bean="employeeConverter"/>

               </set>

       </property>

</bean>

 

四、数据校验

jar:

hibernate-validator-5.0.0.CR2.jar 

hibernate-validator-annotation-processor-5.0.0.CR2.jar

classmate-0.8.0.jar

jboss-logging-3.1.1.GA.jar

validation-api-1.1.0.CR1.jar

将el-api-2.2.jar,javax.el-2.2.4.jar,javax.el-api-2.2.4.jar放到tomcat的lib目录下

(先用强力删除删除掉el-api.jar)

 

1). 如何校验 ?注解 ?

①.使用 JSR 303 验证标准

②.加入 hibernate validator 验证框架的jar 包

③.在 SpringMVC 配置文件中添加 <mvc:annotation-driven />

④.需要在 bean 的属性上添加对应的注解

⑤.在目标方法 bean 类型的前面添加 @Valid 注解

2). 验证出错转向到哪一个页面 ?

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

3). 错误消息 ?如何显示, 如何把错误消息进行国际化

 

 

1)

①• 使用 JSR 303 验证标准

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

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

 

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

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

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

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

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

 

 

②.加入 hibernate validator 验证框架的 jar 包

hibernate-validator-5.0.0.CR2.jar 

hibernate-validator-annotation-processor-5.0.0.CR2.jar

classmate-0.8.0.jar

jboss-logging-3.1.1.GA.jar

validation-api-1.1.0.CR1.jar

将el-api-2.2.jar,javax.el-2.2.4.jar,javax.el-api-2.2.4.jar放到tomcat的lib目录下

(先用强力删除删除掉el-api.jar)

 

③.• 在 SpringMVC 配置文件中添加 <mvc:annotation-driven />

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

 

 

④.需要在 bean 的属性上添加对应的注解

如:

public class Employee {

 

       private Integer id;

       @NotEmpty//要求非空

       private String lastName;

 

       @Email//要求Email格式

       private String email;

        //1male, 0 female

       private Integer gender;

       private Department department;

       @Past//要求是过去的时间

       @DateTimeFormat(pattern="yyyy-MM-dd")

       private Date birth;

       @NumberFormat(pattern="#,###,###.#")

       private Float salary;

 

}

 

⑤.在目标方法 bean 类型的前面添加 @Valid 注解

@RequestMapping(value="/emp", method=RequestMethod.POST)

public String save(@Valid Employee employee,

Map<String,Object> map){

 

       System.out.println("save:" + employee);

       employeeDao.save(employee);

       return "redirect:/emps";

}

 

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

 

 

2). 验证出错转向到哪一个页面 ?

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

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

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

• BindingResult 扩展了 Errors 接口

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

• 常用方法:

 FieldErrorgetFieldError(String field)

 List<FieldError>getFieldErrors()

 ObjectgetFieldValue(String field)

 IntgetErrorCount()

@RequestMapping(value="/emp", method=RequestMethod.POST)

public String save(@Valid Employeeemployee, Errors result,

                            @Valid Departmentdepartment,BindingResult bindingResult,

                            Map<String, Object>map){

       System.out.println("save:" + employee);

 

       if(result.getErrorCount()+bindingResult.getErrorCount() > 0){

                  System.out.println("出错了!");

                  for(FieldErrorerror:result.getFieldErrors()){

                          System.out.println(error.getField() + ":" + error.getDefaultMessage());

                   }

 

       //若验证出错,则转向定制的页面

       map.put("departments"departmentDao.getDepartments());

                  return "input";

       }

 

       employeeDao.save(employee);

       return "redirect:/emps";

}

 

3). 错误消息 ?如何显示, 如何把错误消息进行国际化

• Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,

还会将所有校验结果保存到 “隐含模型

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

• 隐含模型中的所有数据最终将通过 HttpServletRequest 的属性列表暴露给 JSP 视图对象,

  因此在 JSP 中可以获取错误信息

• 在 JSP 页面上可通过 <form:errorspath=“userName”>显示错误消息如果是想在某处显示所有错误则

<form:input path="lastName"/><form:errors path="lastName"></form:errors>

在可能出错的表情上加入相应的错误可能

Email: 

<form:input path="email"/><form:errors path="email"></form:errors>

LastName: 

<form:input path="lastName"/><form:errors path="lastName"></form:errors>

 

 

 

提示消息的国际化

• 每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 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 在调用处理方法时发生了错误

• 注册国际化资源文件

 

配置i18n资源文件

注解类属性的注解类型.在该jsp下的modelAttribute.属性名=发生错误后要显示的文字

 

i18n.properties

//lastName不能为空,GBK格式下会自动转换为这个

NotEmpty.employee.lastName=^^LastName\u4E0D\u80FD\u4E3A\u7A7A.

Email.employee.email=Email\u5730\u5740\u4E0D\u5408\u6CD5

Past.employee.birth=Birth\u4E0D\u80FD\u662F\u4E00\u4E2A\u5C06\u6765\u7684\u65F6\u95F4.

typeMismatch.employee.birth=Birth\u4E0D\u662F\u4E00\u4E2A\u65E5\u671F.

i18n.user=User

i18n.password=Password

 

i18n_en_US.properties

NotEmpty.employee.lastName=^^LastName\u4E0D\u80FD\u4E3A\u7A7A.

Email.employee.email=Email\u5730\u5740\u4E0D\u5408\u6CD5

Past.employee.birth=Birth\u4E0D\u80FD\u662F\u4E00\u4E2A\u5C06\u6765\u7684\u65F6\u95F4.

typeMismatch.employee.birth=Birth\u4E0D\u662F\u4E00\u4E2A\u65E5\u671F.

i18n.user=User

i18n.password=Password

 

i18n_zh_CN-properties

NotEmpty.employee.lastName=^^LastName\u4E0D\u80FD\u4E3A\u7A7A.

Email.employee.email=Email\u5730\u5740\u4E0D\u5408\u6CD5

Past.employee.birth=Birth\u4E0D\u80FD\u662F\u4E00\u4E2A\u5C06\u6765\u7684\u65F6\u95F4.

typeMismatch.employee.birth=Birth\u4E0D\u662F\u4E00\u4E2A\u65E5\u671F.

i18n.user=\u7528\u6237\u540D

i18n.password=\u5BC6\u7801

 

 

在spring的配置文件中加入下列bean

<!-- 配置国际化资源文件 -->

<bean id="messageSource"

          class="org.springframework.context.support.ResourceBundleMessageSource">

                  <property name="basename" value="i18n"></property>

</bean>

 

 

 

 

 

 

 

 

 

 

 

 

 

 


原创粉丝点击