点滴记载,点滴进步,愿自己更上一层楼。加油!!!


所有代码都是基于上一篇,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

springbatch校验参数_springmvc参数校验

上面可以看到打印出来的校验结果信息。结果前台jsp也进行了显示。

springbatch校验参数_springmvc参数校验_02

框架校验结束,但是上面的有局限性,如果有的需求不需要做这些的校验,但是又不想另行做一个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;

测试结果。


springbatch校验参数_spring mvc_03

另写一个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分组的都会校验,没加的不会校验。

springbatch校验参数_spring_04

如图所示,vo中仅仅password有分组,所以这里仅仅校验password   但是account的@NotNull并没有起作用。

如果多个controller公用一个vo ,有的需要校验,有的不需要校验,灵活运用分组即可。

这里仅仅做了两个简单的校验,没有太深入,请自行深入,这里只做引子。

点滴记载,点滴进步,愿自己更上一层楼。加油!!!