点滴记载,点滴进步,愿自己更上一层楼。加油!!!
所有代码都是基于上一篇,springmvc----json参数绑定
springmvc的参数校验,并不是传统的if else等等之类的代码,这里说的是框架校验。
springmvc的参数校验用的是hibernate的vaildation校验框架.
要求安全行较高的项目,都会做前台js校验+后台参数校验,这里仅仅代码仅仅作为引子,没有做那么全面。
示例开始。
既然要用到hibernate的vaildation校验框架,自然需要另外的jar包。将对应的jar依赖添加到pom中去。
<!-- hibernate 校验框架 start -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<!-- hibernate 校验框架 end -->
添加一个校验框架专门用的xml springmvc-vaildation.xml
<?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">
<!-- spring 校验器 -->
<bean id="vaildator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<!-- hibernate 校验器 -->
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!-- 指定校验使用的资源文件默认使用classpath下的ValidationMessages.properties -->
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- 资源文件名 -->
<property name="basenames">
<list>
<value>classpath:vaildation/Vaildations</value>
</list>
</property>
<!-- 文件编码 -->
<property name="fileEncodings" value="UTF-8"/>
<!--资源文件缓存时间 单位秒-->
<property name="cacheSeconds" value="200"/>
</bean>
</beans>
文件中的classpath:vaildation/Vaildations对应着一个properties文件(Vaildations.properties)。
#user.account.notnull=用户名不能为空
#user.password.length=密码最大长度为12位
user.account.notnull=\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a
user.password.length=\u5bc6\u7801\u6700\u5927\u957f\u5ea6\u4e3a12\u4f4d
由于中文有可能有问题,反正我这里一直乱码,网上搜索别人也有这种问题,有说什么将fileEncodings改成defaultEncoding,我这里不行,
还有的说在代码中做一层转换(这种方法可行,但是多了一层代码逻辑),建议直接将中文转成unicode编码。
controller代码
package com.soft.controller;
import com.soft.po.ValidationVo;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
/**
* Created by xuweiwei on 2017/8/20.
*/
@Controller
public class TestVaildationController {
/**
* @Validated 用于激活ValidationVo中的校验,
* @param validationVo 传参数vo, 校验也在其中
* @param bindingResult 校验的结果都放在这里面。
* 注意:如果有多个vo,bindingResult需要和校验的vo成对出现,也就是像这种
* public ModelAndView vaildater01(@Validated ValidationVo validationVo, BindingResult bindingResult,
* @Validated XXXXVo validationVo, BindingResult xxxxResult)
* @return
*/
@RequestMapping("/testVaildater01")
public ModelAndView vaildater01(@Validated ValidationVo validationVo, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("status", "success");
// 是否有错误信息
if (bindingResult.hasErrors()) {
// 获取全部的错误结果
List<ObjectError> allerror = bindingResult.getAllErrors();
for (ObjectError objectError : allerror) {
// 打印错误消息
System.out.println(objectError.getDefaultMessage());
}
// 将错误消息显示到页面。
modelAndView.addObject("errors", allerror);
modelAndView.addObject("status", "error");
}
modelAndView.setViewName("test/testVaildate");
return modelAndView;
}
}
接收参数,校验参数的vo ValidationVo.java
package com.soft.po;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* Created by xuweiwei on 2017/8/20.
*/
public class ValidationVo {
@NotNull(message = "{user.account.notnull}")
private String account;
@Size(min=1, max=12,message = "{user.password.length}")
private String password;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
显示消息的jsp页面 testVaildate.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ page isELIgnored="false"%>
<html>
<head>
<title>Title</title>
</head>
<body>
是否有错误信息,无显示success,有显示error:${status}<br/>
<c:forEach items="${errors}" var="err">
${err.defaultMessage}<br/>
</c:forEach>
</body>
</html>
准备工作已经完毕,接下来进行测试。浏览器输入
http://localhost:8080/testVaildater01?password=123456789456123
回车,进入action
上面可以看到打印出来的校验结果信息。结果前台jsp也进行了显示。
框架校验结束,但是上面的有局限性,如果有的需求不需要做这些的校验,但是又不想另行做一个vo,这是就需要用到校验分组了。
2 分组校验。
分组校验仅仅需要定义对应的接口。
package com.soft.vaildate;
/**
* Created by xuweiwei on 2017/8/20.
*/
public interface VaildateGroup {
// 里面不需要定义任何的方法,仅作为分组依据。
}
然后将这个分组接口加入到校验中,vo还是那个vo,只不过在校验password的时候加入了分组,此时仅仅在有该分组的时候才进行校验,如果再次输入上面的测试地址,密码长度的提示不在显示。
@Size(min=1, max=12,message = "{user.password.length}",groups = {VaildateGroup.class})
private String password;
测试结果。
另写一个action用于校验分组,
/**
* @Validated 用于激活ValidationVo中的校验,
* @param validationVo 传参数vo, 校验也在其中
* @param bindingResult 校验的结果都放在这里面。
* 注意:如果有多个vo,bindingResult需要和校验的vo成对出现,也就是像这种
* public ModelAndView vaildater01(@Validated ValidationVo validationVo, BindingResult bindingResult,
* @Validated XXXXVo validationVo, BindingResult xxxxResult)
* @return
*/
@RequestMapping("/testVaildater02")
public ModelAndView vaildater02(@Validated(value={VaildateGroup.class}) ValidationVo validationVo, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("status", "success");
// 是否有错误信息
if (bindingResult.hasErrors()) {
// 获取全部的错误结果
List<ObjectError> allerror = bindingResult.getAllErrors();
for (ObjectError objectError : allerror) {
// 打印错误消息
System.out.println(objectError.getDefaultMessage());
}
// 将错误消息显示到页面。
modelAndView.addObject("errors", allerror);
modelAndView.addObject("status", "error");
}
modelAndView.setViewName("test/testVaildate");
return modelAndView;
}
仔细看这个action跟01也就差了一句@Validated(value={VaildateGroup.class}),这个方法添加了分组校验,vo中加了VaildateGroup.class分组的都会校验,没加的不会校验。
如图所示,vo中仅仅password有分组,所以这里仅仅校验password 但是account的@NotNull并没有起作用。
如果多个controller公用一个vo ,有的需要校验,有的不需要校验,灵活运用分组即可。
这里仅仅做了两个简单的校验,没有太深入,请自行深入,这里只做引子。
点滴记载,点滴进步,愿自己更上一层楼。加油!!!