校验通常是前端校验,比如js校验,但对于安全要求较高的建议在服务端进行校验
controller层:校验检验页面请求的参数类型的合法性(页面提交的东西)
service层:(使用较多)检验关键业务参数
dao层:一般不校验:
springmvc使用了hibernate的validation校验框架
引入依赖:
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
<scope>provided</scope>
</dependency>
<!-- Hibernate Validator添加依赖,使springmvc支持Hibernate的 Validator校验-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.0.Final</version>
</dependency>
<!-- Hibernate Validator添加依赖,使springmvc支持Hibernate的 Validator校验-->
spring-mvc添加相关配置,使其支持validation校验:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="cn.itcast.ssm.controller"/>
<mvc:annotation-driven></mvc:annotation-driven>
<!--对于注解的handler可以单个配置,可以每次手动的在配置文件中添加bean注册,但建议使用组件扫描方式注册bean-->
<!--HttpRequestHandlerAdapter适配器,要求编写handler实现HttpRequestHandler-->
<!-- <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>-->
<!-- 视图解析器-->
<!-- 解析jsp,默认使用jstl,classpath下的有jstl的包,视图解析器的有代码://classname javax.servlet.jsp.jstl.core.Config-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<!--日期类型转换-->
<!-- <bean class="cn.meko.controller.converter.CustomDateConverter"/>-->
</list>
</property>
</bean>
<!-- 指定自己定义的validator -->
<mvc:annotation-driven validator="validator"/>
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册-->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<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>
<!-- 在web环境中一定要定位到classpath 否则默认到当前web应用下找 -->
<value>classpath:validat</value>
</list>
</property>
<property name="useCodeAsDefaultMessage" value="false"/>
<property name="defaultEncoding" value="utf-8" />
<property name="cacheSeconds" value="60"/>
</bean>
<!--配置校验器结束-->
</beans>
实体类Items上添加注释:校验规则
public class Items {
private Integer id;
@Size(min=1,max=30,message = "{items.name.length.error}")
private String name;
private Float price;
private String pic;
@NotNull(message = "时间不允许为空")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date createtime;
}
itemsController测试代码:
//@Validated 必须在之前,BindingResult必须在之后
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model,HttpServletRequest request, Integer id, @Validated ItemsCustom itemsCustom,BindingResult bindingResult
)throws Exception {
List<ObjectError> allErrors = null;
if (bindingResult.hasErrors()) {
allErrors = bindingResult.getAllErrors();
for (ObjectError objectError : allErrors) {
System.out.println(objectError.getDefaultMessage());
}
}
model.addAttribute("allErrors", allErrors);
return "/items/editItems";
}
商品编辑页面editItem.jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>修改商品</title>
</head>
<body>
<c:if test="${allErrors!=null}">
<c:forEach items="${allErrors}" var="error">
${error.defaultMessage}
</c:forEach>
</c:if>
<form action="${pageContext.request.contextPath}/editItemsSubmit.action" method="post" id="itemForm">
<input type="hidden" name="id" value="${itemsCustom.id}"/>
修改商品信息:
<table width="100%" border="1">
<tr>
<td>商品名称</td>
<td><input type="text" name="name" value="${itemsCustom.name}"></td>
</tr>
<tr>
<td>商品价格</td>
<td><input type="text" name="price" value="${itemsCustom.price}"></td>
<%-- <td>生产日期</td>
<td>商品描述</td>
<td>操作</td>--%>
</tr>
<tr>
<td>商品简介</td>
<td><textarea rows="3" cols="30" name="detail">${itemsCustom.detail}</textarea></td>
</tr>
<tr>
<td>商品时间</td>
<td><input type="text" name="createtime" value="<fmt:formatDate value='${itemsCustom.createtime}' type='date' pattern='yyyy-MM-dd HH:mm:ss'/>"></td></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
</body>
</html>
分组校验:(当不同的controller方法对同一个pojo进行校验,但每个controller有不同校验规则)分组校验(是一个java接口)
新建一个接口:ValidGroup1
public interface ValidGroup1 {
//此分组之校验商品名称
}
更改实体类Items中的validation如下:
public class Items {
private Integer id;
@Size(min=1,max=30,message = "长度错误",groups = {ValidGroup1.class})
private String name;
private Float price;
private String pic;
@NotNull(message = "时间不允许为空")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date createtime;
private String detail;
}
更改ItemsController的代码如下:
//@Validated 必须在之前,BindingResult必须在之后,@Validated(value = {ValidGroup1.class}指定使用组一校验
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model, HttpServletRequest request, Integer id, @Validated(value = {ValidGroup1.class}) ItemsCustom itemsCustom, BindingResult bindingResult
)throws Exception {
List<ObjectError> allErrors = null;
if (bindingResult.hasErrors()) {
allErrors = bindingResult.getAllErrors();
for (ObjectError objectError : allErrors) {
System.out.println(objectError.getDefaultMessage());
}
}
model.addAttribute("allErrors", allErrors);
return "/items/editItems";
}
测试会发现:如果时间,姓名的长度都为空,validation只检验姓名,因为我们分组检验的就只是validation
数据回显:
提交错误,将刚才提交的数据回显到刚才的提交页面
springmvc默认对pojo数据进行回显
pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,而key就等于pojo的类名的首字母小写itemscustom
数据 回显验证:通过ModelAttribute实现,
//@Validated 必须在之前,BindingResult必须在之后,@Validated(value = {ValidGroup1.class}指定使用组一校验
// @ModelAttribute("items")指定pojo回显到页面在request中的key,还可以将方法的返回值传到页面
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model, HttpServletRequest request, Integer id,
@ModelAttribute("items") @Validated(value = {ValidGroup1.class}) ItemsCustom itemsCustom, BindingResult bindingResult
)throws Exception {
List<ObjectError> allErrors = null;
if (bindingResult.hasErrors()) {
allErrors = bindingResult.getAllErrors();
for (ObjectError objectError : allErrors) {
System.out.println(objectError.getDefaultMessage());
}
}
model.addAttribute("allErrors", allErrors);
return "/items/editItems";
}
ModelAttribute("items")指定pojo回显到页面在request中的key,还可以将方法的返回值传到页面
//itemtypes表示最终将方法返回值放在requestType中的key,页面上可以得到itemtypes的数据
@ModelAttribute("itemtypes")
public Map<String,String>getItemTypes(){
Map<String,String>itemTypes=new HashMap<String,String>();
itemTypes.put("101","数码");
itemTypes.put("102","派克");
return itemsTypes;
}
jsp的测试代码:
<select name="itemtype">
<c:forEach items="${itemtypes}" var="itemtype">
<option value="${itemtype.key}">${itemtype.value}</option>
</c:forEach>
</select>
</form>
简单数据类型的回显用model就可以了,也可以用注解实现回显:
最后在放一下综合的:Controller层:ItemsController.java
@Controller
@RequestMapping("/items")
public class ItemsController {
@Autowired
private ItemsService itemsService;
//itemtypes表示最终将方法返回值放在requestType中的key,页面上可以得到itemtypes的数据
@ModelAttribute("itemtypes")
public Map<String,String> getItemType(){
Map<String,String> itemTypes=new HashMap<String,String>();
itemTypes.put("101","数码");
itemTypes.put("102","派克");
return itemTypes;
}
@RequestMapping("/queryItems")
public ModelAndView queryItems(HttpServletRequest request, ItemsQueryVo itemsQueryVo) throws Exception {
List<ItemsCustom> itemsList = itemsService.finditemsList(itemsQueryVo);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("/items/itemsList");
return modelAndView;
}
//@Validated 必须在之前,BindingResult必须在之后,@Validated(value = {ValidGroup1.class}指定使用组一校验
// @ModelAttribute("items")指定pojo回显到页面在request中的key,还可以将方法的返回值传到页面
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Model model, HttpServletRequest request, Integer id,
@ModelAttribute("itemsCustom") @Validated(value = {ValidGroup1.class}) ItemsCustom itemsCustom, BindingResult bindingResult
)throws Exception {
List<ObjectError> allErrors = null;
if (bindingResult.hasErrors()) {
allErrors = bindingResult.getAllErrors();
for (ObjectError objectError : allErrors) {
System.out.println(objectError.getDefaultMessage());
}
}
model.addAttribute("allErrors", allErrors);
model.addAttribute("items",itemsCustom);
return "/items/editItems";
}
}
视图层editItem.jsp:测试数据回显页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>修改商品</title>
</head>
<body>
<c:if test="${allErrors!=null}">
<c:forEach items="${allErrors}" var="error">
${error.defaultMessage}
</c:forEach>
</c:if>
<form action="${pageContext.request.contextPath}/editItemsSubmit.action" method="post" id="itemForm">
<input type="hidden" name="id" value="${itemsCustom.id}"/>
修改商品信息:
<table width="100%" border="1">
<tr>
<td>商品名称</td>
<td><input type="text" name="name" value="${itemsCustom.name}"></td>
</tr>
<tr>
<td>商品价格</td>
<td><input type="text" name="price" value="${itemsCustom.price}"></td>
<%-- <td>生产日期</td>
<td>商品描述</td>
<td>操作</td>--%>
</tr>
<tr>
<td>商品简介</td>
<td><textarea rows="3" cols="30" name="detail">${itemsCustom.detail}</textarea></td>
</tr>
<tr>
<td>商品时间</td>
<td><input type="text" name="createtime" value="<fmt:formatDate value='${itemsCustom.createtime}' type='date' pattern='yyyy-MM-dd HH:mm:ss'/>"></td></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/></td>
</tr>
</table>
</body>
</html>
获取modelAttribute标注方法的返回值的测试页面:ItemsList.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<html>
<head>
<%-- <base href="<%=basePath%>">--%>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>查询商品列表</title>
</head>
<body>
<form action="#" method="post" id="itemsForm">
查询条件:
<table width="100%" border="1">
<tr>
<td>商品名称    <input name="itemsCustom.name">
商品类型 <select name="itemtypes">
<c:forEach items="${itemtypes}" var="i">
<option value="${i.key}">${i.value}</option>
</c:forEach>
</select>
</td>
<td><button onclick="queryItems()">查询</button> </td>
<td><button onclick="deleteItems()">删除</button> </td>
</tr>
</table>
商品列表:
<table width="100%" border="1">
<tr>
<td>选择</td>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList}" var="item">
<tr>
<td><input type="checkbox" name="ids" value="${item.id}"></td>
<td>${item.name}</td>
<td>${item.price}</td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>${item.detail}</td>
<td><a href="${pageContext.request.contextPath}/selectAllItem.action">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
<script type="text/javascript">
function queryItems() {
document.getElementById("itemsForm").action ="${pageContext.request.contextPath}/queryItems.action";
document.getElementById("itemsForm").submit();
}
function deleteItems() {
document.getElementById("itemsForm").action="${pageContext.request.contextPath}/deleteItems.action";
document.getElementById("itemsForm").submit;
}
</script>
</body>
</html>
测试结果如下: