Spring验证器之Validator接口
Spring验证器
数据验证分为客户端验证和服务器验证,
- 客户端验证主要是过滤正常用户的误操作,通过JavaScript代码完成;
- 服务器验证是整个应用阻止非法数据的最后防线,通过在应用中编程是实现。
Validator接口
创建自定义的Spring验证器需要实现org.springframework.validation.Validator接口,该接口有两个方法
- boolean supports(Class<?> klass)
- void validate(Object object,Errors errors)
实现的数据输入页面效果图
数据显示页面
数据输入页面采用是Spring的表单form标签
需要额外引入<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
addGoods.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form:form modelAttribute="goods" action="${pageContext.request.contextPath }/goods/save" method="post">
<fieldset>
<legend>添加一件商品</legend>
<p>
<label>商品名</label>
<form:input path="gname"/>
</p>
<p>
<label>商品详情</label>
<form:input path="gdescription"/>
</p>
<p>
<label>商品价格</label>
<form:input path="gprice"/>
</p>
<p>
<label>创建日期</label>
<form:input path="gdate"/>(yyyy-MM-dd)
</p>
<p id="buttons">
<input id="reset" type="reset"/>
<input id="submit" type="submit" value="添加"/>
</p>
</fieldset>
<!-- 取出所有验证错误 -->
<form:errors path="*"></form:errors>
</form:form>
</body>
</html>
modelAttribute:表示的是绑定的是哪一个Model,当指定了对应的Model后就可以在form标签内部其它表单标签上通过为path指定Model属性的名称来绑定Model中的数据了,method属性指定form的提交方式如GET、POST等
创建pojo实体类
public class Goods {
private String gname;
private String gdescription;
private double gprice;
//日期格式化
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date gdate;
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
public String getGdescription() {
return gdescription;
}
public void setGdescription(String gdescription) {
this.gdescription = gdescription;
}
public double getGprice() {
return gprice;
}
public void setGprice(double gprice) {
this.gprice = gprice;
}
public Date getGdate() {
return gdate;
}
public void setGdate(Date gdate) {
this.gdate = gdate;
}
@Override
public String toString() {
return "Goods [gname=" + gname + ", gdescription=" + gdescription + ", gprice=" + gprice + ", gdate=" + gdate
+ "]";
}
}
编写验证器类
主要是实现Validator接口,实现方法,使用了类似于goods.gname.required这样的错误消息属性文件。
@Component
public class GoodsValidator implements Validator{
@Override
public boolean supports(Class<?> kclass) {
//要验证的model,返回值为false则不验证
return Goods.class.isAssignableFrom(kclass);
}
@Override
public void validate(Object object, Errors errors) {
Goods goods = (Goods)object;//要验证的对象
ValidationUtils.rejectIfEmpty(errors, "gname", "goods.gname.required");
ValidationUtils.rejectIfEmpty(errors, "gdescription", "goods.gdescription.required");
if(goods.getGprice()>100 || goods.getGprice()<0) {
errors.rejectValue("gprice", "gprice.invalid");
}
Date goodsDate = goods.getGdate();
//在系统时间之后
if(goodsDate!=null && goodsDate.after(new Date())) {
errors.rejectValue("gdate", "gdate.invalid");
}
}
}
配置错误消息属性文件,因为properties对于中文会自动编码
中文依次是:
请输入商品名称--请输入商品详情--价格为0-100--创建日期不能再系统日期之后
属性文件如下
goods.gname.required=\u8BF7\u8F93\u5165\u5546\u54C1\u540D\u79F0
goods.gdescription.required=\u8BF7\u8F93\u5165\u5546\u54C1\u8BE6\u60C5
gprice.invalid=\u4EF7\u683C\u4E3A0-100
gdate.invalid=\u521B\u5EFA\u65E5\u671F\u4E0D\u80FD\u518D\u7CFB\u7EDF\u65E5\u671F\u4E4B\u540E
Service层和ServiceImpl层代码
public interface GoodsService {
boolean save(Goods g);
ArrayList<Goods> getGoods();
}
//serviceImpl层代码
@Service
public class GoodsServiceImpl implements GoodsService{
//使用静态集合变量goods模拟数据库
private static ArrayList<Goods> goods = new ArrayList<Goods>();
@Override
public boolean save(Goods g) {
goods.add(g);
return true;
}
@Override
public ArrayList<Goods> getGoods() {
return goods;
}
}
Controller层代码
主要实现商品未填写跳转到添加商品页面和商品填写错误的验证判断
@Controller
@RequestMapping("/goods")
public class GoodsController {
//日志
private static final Log logger = LogFactory.getLog(GoodsController.class);
@Autowired
private GoodsService goodsService;
//相当于 GoodsValidator validator = new GoodsValidator()
@Resource
private Validator validator;
@RequestMapping("/input")
public String input(Model model) {
//如果model中没有goods属性,addGoods.jsp就会抛出异常
model.addAttribute("goods", new Goods());
return "addGoods";
}
@RequestMapping("/save")
public String save(@ModelAttribute Goods goods,BindingResult result,Model model) {
this.validator.validate(goods,result);//添加验证
if(result.hasErrors()) {
return "addGoods";
}
goodsService.save(goods);
logger.info("添加成功");
model.addAttribute("goodList", goodsService.getGoods());
return "goodList";
}
}
springmvc-servlet.xml文件配置
<!-- 扫描包注解 -->
<context:component-scan base-package="com.controller"></context:component-scan>
<context:component-scan base-package="com.service"></context:component-scan>
<context:component-scan base-package="com.validator"></context:component-scan>
<!-- 注册格式化转化器 因为用到日期转换 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionService">
</bean>
<!-- 注解驱动** -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 配置视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 需要告诉Spring MVC从该文件中获取错误消息 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/resource/errorMessage"></property>
</bean>
数据显示页面
<table>
<tr>
<td>商品名称</td>
<td>商品详情</td>
<td>商品价格</td>
<td>创建日期</td>
</tr>
<c:forEach items="${goodList }" var="goods">
<tr>
<td>${goods.gname }</td>
<td>${goods.gdescription }</td>
<td>${goods.gprice }</td>
<td>${goods.gdate }</td>
</tr>
</c:forEach>
</table>
web.xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="4.0"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
<!-- 部署dispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config/springmvc-servlet.xml</param-value>
</init-param>
<!-- 表示容器启动的时候就加载servlet 启动优先级 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 处理所有的url -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
创建验证器:
定义一个验证器类,实现Spring验证器接口,通过接口中的方法实现来完成验证器功能的实现,从而完成验证器的创建。