原理:ssm187集
Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到 ConversionServiceFactoryBean 中:
实现Converter接口,写一个自定义的类型转换器;
/*** 两个泛型* S:Source * T:Target * 将s转为t*/
public class MyStringToEmployeeConverter implements Converter<String, Employee> {@AutowiredDepartmentDao departmentDao;/*** 自定义转换规则* 目标将 empAdmin-admin@qq-1-101 转换成Employee对象*/@Overridepublic Employee convert(String source) {System.out.println("页面提交的将要转换的字符串:"+source); empAdmin-admin@qq-1-101Employee employee = new Employee();ains("-")){String[] split = source.split("-");employee.setLastName(split[0]);employee.setEmail(split[1]);employee.setGender(Integer.parseInt(split[2]));employee.Department(Integer.parseInt(split[3])));System.out.println("转换之后的employee对象是:"+employee);}return employee;}
}
将这个Converter配置在ConversionService中
Converter是ConversionService中的组件;
1、你的Converter得放进ConversionService 中;
2、将WebDataBinder中的ConversionService设置成我们这个加了自定义类型转换器的ConversionService;
<!-- 告诉SpringMVC别用默认的ConversionService,而用我自定义的ConversionService、可能有我们自定义的Converter; --><!-- 以后写自定义类型转换器的时候,就使用FormattingConversionServiceFactoryBean来注册;既具有类型转换还有格式化功能 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><!--converters转换器中添加我们自定义的类型转换器 --><property name="converters"><set><bean class="com.zbponent.MyStringToEmployeeConverter"></bean></set></property>
</bean>
告诉SpringNMVC使用这个ConversionService
<!-- conversion-service="conversionService":告诉SpringMVC使用我们自己配置的类型转换组件 -->
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
debug分析:
自定义类型转换器之前:
自定义类型转换器之后:源码上WebDataBinder上的ConversionService组件就替换了;
ssm190集视频(以下待补带理解)
分析关于配置mvc:default-servlet-handler和mvc:annotation-driven
HandlerMapping:
- 动态能访问:
DefaultAnnotationHandlerMapping中的handlerMap中保存了每一个资源的映射信息;- 静态不能访问:
就是handlerMap中没有保存静态资源映射的请求,
HandlerAdapter:方法执行的适配器:
AnnotationMethodHandlerAdapter:帮我们执行目标方法;过时的;
HandlerMapping中变化:
- 动态不能访问:DefaultAnnotationHandlerMapping没有了;用SimpleUrlHandlerMapping替换了,他的作用就是将所有请求直接交给tomcat;
- 静态能访问的原因:SimpleUrlHandlerMapping把所有请求都映射给tomcat
HandlerAdapter:
AnnotationMethodHandlerAdapter没有了
HandlerMapping变化:
RequestMappingHandlerMapping:动态资源可以访问
handleMethods属性保存了每一个请求用哪个方法来处理;
SimpleUrlHandlerMapping:将请求直接交给tomcat;有他,静态资源就没问题;
HandlerAdapter:
原来的AnnotationMethodHandlerAdapter;被换成RequestMappingHandlerAdapter;
*对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴。
FormattingConversionService
实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能FormattingConversionServiceFactroyBean
工厂类,后者用于在 Spring 上下文中构造前者,FormattingConversionServiceFactroyBean 内部已经注册了 : @NumberFormat
注解@DateTimeFormat
注解@DateTimeFormat
注解可对 java.util.Date、java.util.Calendar、java.long.Long 时间类型进行标注: pattern 属性
:类型为字符串。指定解析/格式化字段数据的模式,如:”yyyy-MM-dd hh:mm:ss
”代码示例:将表单中输入的字符串解析成格式化字段数据
前台表单项:
birth:<form:input path="birth"/><br/><!-- 输入类型为2021-3-26 -->
在Employee类增加日期对象属性并标注@DateTimeFormat注解:
//规定页面提交的日期格式
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
注意:如果使用@DateTimeFormat注解标注,则框架默认支持的格式为斜线方式。1990/09/09
@NumberFormat
可对类似数字类型的属性进行标注,它拥有两个互斥的属性: pattern
:类型为 String,自定义样式,如pattern="#,###
";实例代码:
Salary : <form:input path="salary"/>
@NumberFormat(pattern="#,###,###.#")
private double salary ;
对于一些很重要的数据,如果只是做前端校验是不安全的,必须要加上后端的校验。
在后端的校验方法:
可以写程序将每一个数据取出进行校验,如果失败直接来到添加页面,提示重新填写。(不推荐)
SpringMVC:可以JSR-303(Java Specification Requests的第303条规范)来做数据校验
JSR303:规范 ------- 实现:Hibernate Validator(第三方校验框架)
- JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中
- JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证
Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解
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 包中
- 需校验的 Bean 对象和其绑定结果对象或错误对象时成对出现的,它们之间不允许声明其他的入参
- Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或 getFieldErrors(String field)
- BindingResult 扩展了 Errors 接口
在目标方法中获取校验结果
在表单/命令对象类的属性中标注校验注解,在处理方法对应的入参前添加 @Valid,Spring MVC 就会实施校验并将校验结果保存在被校验入参对象之后的 BindingResult 或 Errors 入参中。
常用方法:
- FieldError getFieldError(String field)
- List<FieldError> getFieldErrors()
- Object getFieldValue(String field)
- Int getErrorCount()
在页面上显示错误
- Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,还会将所有校验结果保存到 “隐含模型”
- 即使处理方法的签名中没有对应于表单/命令对象的结果入参,校验结果也会保存在 “隐含对象” 中。
- 隐含模型中的所有数据最终将通过 HttpServletRequest 的属性列表暴露给 JSP 视图对象,因此在 JSP 中可以获取错误信息
- 在 JSP 页面上可通过 <form:errors path=“userName”> 显示错误消息
导入校验框架的jar包
hibernate-validator-5.0.0.CR2dist
- hibernate-validator-5.0.0.CR2.jar
- hibernate-validator-annotation-processor-5.0.0.CR2.jar
hibernate-validator-5.0.0.CR2distlibrequired (EL就不需要加了)
- classmate-0.8.0.jar
- jboss-logging-3.1.1.GA.jar
- validation-api-1.1.0.CR1.jar
注意:有几个带el的jar不导入;tomcat中有;如果tomcat的版本是7.0以下;tomcat7.0以上el表达式比较强大;如果是7.0以下将带el的几个jar放在tomcat的lib文件夹下;
在验证属性上增加验证注解
public class Employee {private Integer id;@NotEmpty@Length(min=6,max=18)private String lastName;@Emailprivate String email;//规定页面提交的日期格式@DateTimeFormat(pattern="yyyy-MM-dd")@Past//表示只能是过去的某个日期private Date birth;
}
在SpringMVC封装对象的时候,告诉SpringMVC这个javaBean需要校验
控制器方法:
/*** 保存员工信息* @param employee* @return*/
@RequestMapping(value="/emp",method=RequestMethod.POST)
//增加@Valid注解,验证失败会报错。
public String addEmp(@Valid Employee employee){System.out.println("新增的Employee信息"+employee);employeeDao.save(employee);//重定向到查询所有员工的请求return "redirect:/emps";
}
获取校验结果:给需要校验的javaBean后面紧跟一个BindingResult。这个BindingResult就是封装前一个bean的校验结果
/*** 保存员工信息* @param employee* @return*/
@RequestMapping(value="/emp",method=RequestMethod.POST)
//增加@Valid注解。如果没有BindingResult,验证失败会报400
public String addEmp(@Valid Employee employee,BindingResult result,Model model){System.out.println("新增的Employee信息"+employee);System.out.println("校验结果为:"+result);System.out.println("*************************************");//获取是否有校验错误boolean hasErrors = result.hasErrors();if(hasErrors){List<FieldError> errors = FieldErrors();Map<String,Object> errorsMap = new HashMap<>();for(FieldError fieldError : errors){System.out.println("错误消息提示:"DefaultMessage());System.out.println("错误的字段是:"Field());errorsMap.Field(), DefaultMessage());}//将错误信息保存到请求域中model.addAttribute("errorInfo", errorsMap);return "add";}else{employeeDao.save(employee);//重定向到查询所有员工的请求return "redirect:/emps";}
}
前台打印错误消息
方法一:使用Spring的表单标签(form:errors取出错误信息)
<form:form action="${ctp }/emp" method="post" modelAttribute="employee">lastName:<form:input path="lastName"/><form:errors path="lastName"></form:errors><br/>email:<form:input path="email"/><form:errors path="email"></form:errors><br/>birth:<form:input path="birth"/><form:errors path="birth"></form:errors><br/>
</form:form>
方法二:将错误信息放到请求域中
<form:form action="${ctp }/emp" method="post" modelAttribute="employee">lastName:<form:input path="lastName"/>${errorInfo.lastName }<br/>email:<form:input path="email"/>${ail }<br/>birth:<form:input path="birth"/>${errorInfo.birth }<br/>
</form:form>
每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 FieldError 对象。
当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为
前缀
,结合 modleAttribute、属性名及属性类型名
生成多个对应的消息代码:例如 Employee类中的 email属性标准了一个 @email注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4 个错误代码:
表示如果是隐含模型中employee对象的email属性字段发生了@Email校验错误,就会生成 ail 所有的email属性只要发生了@Email错误 - Email.java.lang.String; 校验规则.属性类型
只要是String类型发生了@Email错误- Email;
只要发生了@Email校验错误
当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看 WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认的错误消息,否则使用国际化消息。
若数据
类型转换
或数据格式转换
时发生错误,或该有的参数不存在
,或调用处理方法时发生错误
,都会在隐含模型中创建错误消息。其错误代码前缀说明如下:
- required:必要的参数不存在。如 @RequiredParam(“param1”) 标注了一个入参,但是该参数不存在
- typeMismatch:在数据绑定时,发生数据类型不匹配的问题
- methodInvocation:Spring MVC 在调用处理方法时发生了错误
注册国际化资源文件
1、先编写国际化配置文件
errors_en_US.properties
#精确优先
#ail=email incorrect!~~
Email=email buzhengque~~~
NotEmpty=must not empty~~
#占位符 动态传入
Length.java.lang.String=length incorrect ,must between {2} and {1} ~~
Past=must a past time~~~
typeMismatch.birth=birth geshi buzhengque
动态传入消息参数
{0}:永远都是当前属性名;
{1},{2}:参数的字典序。如下所示 {1} 代码的是 max 的值,{2} 代表的是 min 的值
errors_zh_CN.properties
ail=邮箱不对!~~
NotEmpty=不能为空~~
Length.java.lang.String=长度不对~~
Past=时间必须是过去的~~~
typeMismatch.birth=生日的格式不正确
2、让SpringMVC管理国际化资源文件;
<!-- 管理国际化资源文件 -->
<bean id="messageSource" class="t.support.ResourceBundleMessageSource"><!-- basename指定基础名 --><property name="basename" value="errors"></property>
</bean>
3、add.jsp页面获取错误信息
lastName:<form:input path="lastName"/><form:errors path="lastName"></form:errors><br/>email:<form:input path="email"/><form:errors path="email"></form:errors><br/>birth:<form:input path="birth"/><form:errors path="birth"></form:errors><br/>
注意:如果注解已经有 message 属性
了,那么这个字段将会失去国际化功能,每次输出的都是这个message信息
@NotEmpty(message="不能为空")
@Length(min=6,max=18,message="长度")
private String lastName;
本文发布于:2024-02-01 10:10:07,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170675340935896.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |