用户的输入一般是随意的,为了保证数据的合法性,数据验证是所有Web应用必须处理的问题。在Spring MVC框架中有两种方法可以验证输入数据,一种是利用Spring自带的验证框架,另一种是利用JSR 303实现。在这里只介绍Spring的验证体系的使用。
数据验证分为客户端验证和服务端验证,客户端验证主要是过滤正常用户的误操作,通过JavaScript代码完成;服务器端是整个应用阻止非法数据的最后防线,通过在应用中编程实现。
客户端验证
在大多数情况下,使用JavaScript进行客户端验证的步骤如下:
(1)编写验证函数。
(2)在提交表单的事件中调用验证函数。
(3)根据验证函数来判断是否进行表单提交。
客户端验证可以过滤用户的误操作,是第一道防线,一般使用JavaScript代码实现。但仅用客户端验证是不够的,攻击者还可以绕过客户端验证直接进行非法输入,这样可能会引起系统异常,为了确保数据的合法性,防止用户通过非正常手段提交错误信息,必须加上服务器验证。
服务器端验证
SpringMVC的Converter和Formatter在进行类型转换时是将输入数据转换为邻域对象的属性值(一种Java类型),一旦成功,服务器端验证器就好介入。也就是说,在SpringMVC框架中先进行数据类型转换,再进行服务器端验证。
使用Spring验证器的步骤:
web-project项目目录:
1,编写Model类
public class Goods {
private String gname;
private String gdescription;
private double gprice;
//日期格式化(需要在配置文件中配置FormattingConversionServiceFactoryBean
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date gdate;
//省略setter和getter方法
2,编写验证器类
@Component
public class GoodValidator implements Validator{
@Override
public boolean supports(Class> klass) {
//要验证的model,返回值为false则不验证
return Goods.class.isAssignableFrom(klass);
}
@Override
public void validate(Object object, Errors errors) {
Goods goods = (Goods) object;//object要验证的对象
//goods.gname.required 是错误消息属性文件中的编码(国际化后对应的是国际化的信息
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");
}
}
}
3,编写错误消息属性文件
在WEB-INF目录下创建文件夹resource,并在该文件夹中编写属性文件errorMessages.properties。
goods.gname.required=请输入商品名称。
goods.gdescription.required=请输入商品详情。
gprice.invalid=价格为0~100。
gdate.invalid=创建日期不能在系统日期之后。
Unicode编码的属性文件如下:
goods.gname.required=\u8bf7\u8f93\u5165\u5546\u54c1\u540d\u79f0\u3002
goods.gdescription.required=\u8bf7\u8f93\u5165\u5546\u54c1\u8be6\u60c5\u3002
gprice.invalid=\u4ef7\u683c\u4e3a0~100\u3002
gdate.invalid=\u521b\u5efa\u65e5\u671f\u4e0d\u80fd\u5728\u7cfb\u7edf\u65e5\u671f\u4e4b\u540e\u3002
4,编写Service层
public interface GoodsService {
boolean save(Goods g);
ArrayList getGoods();
}
@Service
public class GoodsServiceImpl implements GoodsService{
//使用静态集合变量goods模拟数据库
private static ArrayList goods = new ArrayList();
@Override
public boolean save(Goods g) {
goods.add(g);
return true;
}
@Override
public ArrayList getGoods() {
return goods;
}
}
5,编写控制器类
@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会抛出异常
//因为表单标签无法找到modelAttribute属性指定的from backing object
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("goodsList",goodsService.getGoods());
return "goodsList";
}
}
5,编写配置文件(WEB-INF/spring-config/springmvc-servlet.xml)
6,创建数据显示页面
WEB-INF/jsp/goodsList.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
数据显示页面
商品名
商品详情
商品价格
商品日期
${goods.gname }
${goods.gdescription }
${goods.gprice }
${goods.gdate }
addGoods.jsp
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
添加商品
7,创建web.xml文件
validator
index.jsp
default.html
default.htm
default.jsp
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring-config/springmvc-servlet.xml
1
springmvc
/
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
characterEncodingFilter
/*
github项目:https://github.com/chegy218/ssm-review/tree/master/validator