Spring MVC框架的数据验证

用户的输入一般是随意的,为了保证数据的合法性,数据验证是所有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<Goods> getGoods();
}

@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;
	}

}

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)

<?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:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
	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.xsd
        http://www.springframework.org/schema/util 
		http://www.springframework.org/schema/util/spring-util.xsd
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 使用扫描机制扫描控制器类,控制器类都在包及其子包下 -->
	<context:component-scan base-package="com.validator"/>
	
	<!-- 注册格式化转换器,因为用到了日期转换 -->
	<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	</bean>
	
	<mvc:annotation-driven conversion-service="conversionService"/>
	
	<!-- 配置消息属性文件 -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basename" value="/WEB-INF/resource/errorMessages"/>
		<property name="defaultEncoding" value="UTF-8" />
	</bean>

	<!-- 视图解析器 -->
	<bean id="jspViewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 前缀 -->
		<property name="prefix" value="/WEB-INF/jsp/"></property>
		<!-- 后缀 -->
		<property name="suffix" value=".jsp"></property>
	</bean>
</beans>		

6,创建数据显示页面
WEB-INF/jsp/goodsList.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>数据显示页面</title>
</head>
<body>

	<table>
		<tr>
			<td>商品名</td>
			<td>商品详情</td>
			<td>商品价格</td>
			<td>商品日期</td>
		</tr>
		<c:forEach items="${goodsList }" var="goods">
			<tr>
				<td>${goods.gname }</td>
				<td>${goods.gdescription }</td>
				<td>${goods.gprice }</td>
				<td>${goods.gdate }</td>
			</tr>
		
		</c:forEach>
	</table>
</body>

addGoods.jsp

<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加商品</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:form>

</body>

7,创建web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<!-- xxx为项目名称 -->
	<display-name>validator</display-name>
	<!-- 设置应用首页 -->
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<!-- 部署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内的值为springmvc-serlvet.xml的路径 -->
			<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>characterEncodingFilter</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>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>    	

8,测试应用
在这里插入图片描述在这里插入图片描述

github项目:https://github.com/chegy218/ssm-review/tree/master/validator

猜你喜欢

转载自blog.csdn.net/chegy218/article/details/88770303