SpringMVC参数校验,包括JavaBean和基本类型的校验

标签: spring mvc spring校验
8155人阅读 评论(6) 收藏 举报
分类:

该示例项目使用SpringBoot,添加web和aop依赖。
SpringMVC最常用的校验是对一个javaBean的校验,默认使用hibernate-validator校验框架。而网上对校验单个参数,譬如String,int之类的资料极少,这一篇就是讲这个的。

校验JavaBean

package com.example.bean;

import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;

/**
 * Created by admin on 17/5/3.
 */
public class User {
    private Long id;

    @NotEmpty(message = "姓名不能为空")
    private String name;

    @NotEmpty(message = "密码不能为空")
    @Length(min = 6, message = "密码长度不能小于6位")
    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

定义了@NotEmpty等标签后,结合在Controller里使用@Valid即可完成参数的校验。

package com.example.controller;

import com.example.bean.User;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * Created by wuwf on 17/4/27.
 *
 */
@RestController
public class FirstController {

    @RequestMapping("/first")
    public Object first(@Valid User user, BindingResult bindingResult) {
        return "first controller";
    }

    @RequestMapping("/second")
    public @Length Object second(@Length(min = 6, message = "密码长度不能小于6位") String password) {
        return "second controller";
    }

    @RequestMapping("/third")
    public @Length Object third(@Range(min = 6, max = 10, message = "数据需要大于6小于10") int num, @Length(min = 6, message = "密码长度不能小于6位") String password) {
        return "third controller";
    }

    @RequestMapping("/four")
    public @Length Object four(int page) {
        return "four controller";
    }
}

譬如first方法里,只需要加上@Valid标签即可完成校验。如果校验不通过,那么错误信息就会封装到BindingResult对象了,可以通过bindingResult的相关方法获取详细的错误信息并返回给用户。
访问:http://localhost:8080/first?name=1&password=1 debug可看到
这里写图片描述
如果不加BindingResult则会抛出异常。
此时即可完成表单类,或者用户注册之类的类似请求的参数校验了,可以选择获取bindingResult信息后直接return给用户。如果这样的需要校验的地方比较多,每个都单独处理比较麻烦,可以通过aop统一处理返回,后面会讲到。
校验的标签可参考:http://blog.csdn.net/catoop/article/details/51278675
相关文章:http://412887952-qq-com.iteye.com/blog/2312356

校验基本类型

在很多场景下,我们不需要校验一个javaBean,更多的是校验单个的int,String等。也就是controller里的second和third方法。像方法中写的那样,但是直接写上去,是不起作用的,校验框架并没有去校验,我们需要做的就是让它生效。
参考如下:https://diamondfsd.com/article/78fa12cd-b530-4a90-b438-13d5a0c4e26c
http://blog.csdn.net/catoop/article/details/51284638
直接上代码吧

package com.example.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.ObjectError;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

/**
 * Created by wuwf on 17/4/27.
 * 参数校验切面
 */
@Aspect
@Component
public class ValidAspect {
    private ObjectError error;

    @Pointcut("execution(public * com.example.controller.*.*(..))")
    public void valid() {
    }

    //环绕通知,环绕增强,相当于MethodInterceptor
    @Around("valid()")
    public Object arround(ProceedingJoinPoint pjp) {
        System.out.println("方法环绕start.....");
        try {
            //取参数,如果没参数,那肯定不校验了
            Object[] objects = pjp.getArgs();
            if (objects.length == 0) {
                return pjp.proceed();
            }
            /**************************校验封装好的javabean**********************/
            //寻找带BindingResult参数的方法,然后判断是否有error,如果有则是校验不通过
            for (Object object : objects) {
                if (object instanceof BeanPropertyBindingResult) {
                    //有校验
                    BeanPropertyBindingResult result = (BeanPropertyBindingResult) object;
                    if (result.hasErrors()) {
                        List<ObjectError> list = result.getAllErrors();
                        for (ObjectError error : list) {
                            System.out.println(error.getCode() + "---" + error.getArguments() + "--" + error.getDefaultMessage());
                            //返回第一条校验失败信息。也可以拼接起来返回所有的
                            return error.getDefaultMessage();
                        }
                    }
                }
            }

            /**************************校验普通参数*************************/
            //  获得切入目标对象
            Object target = pjp.getThis();
            // 获得切入的方法
            Method method = ((MethodSignature) pjp.getSignature()).getMethod();
            // 执行校验,获得校验结果
            Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, objects);
            //如果有校验不通过的
            if (!validResult.isEmpty()) {
                String[] parameterNames = parameterNameDiscoverer.getParameterNames(method); // 获得方法的参数名称

                for(ConstraintViolation<Object> constraintViolation : validResult) {
                    PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath();  // 获得校验的参数路径信息
                    int paramIndex = pathImpl.getLeafNode().getParameterIndex(); // 获得校验的参数位置
                    String paramName = parameterNames[paramIndex];  // 获得校验的参数名称

                    System.out.println(paramName);
                    //校验信息
                    System.out.println(constraintViolation.getMessage());
                }
                //返回第一条
                return validResult.iterator().next().getMessage();
            }

            return pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }

    private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
    private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private final ExecutableValidator validator = factory.getValidator().forExecutables();


    private <T> Set<ConstraintViolation<T>> validMethodParams(T obj, Method method, Object[] params) {
        return validator.validateParameters(obj, method, params);
    }
}

注释写的比较清楚了,这是一个aop切面类,拦截请求,并获取方法里的所有参数。第65行到85行是对普通参数进行校验的。
加上这几行代码后在controller里写的那些才会生效,并且把校验信息保存到了ConstraintViolation的Set集合里,判断Set是否有值,即可知道是否有校验不通过的信息,然后就可以取到校验信息并返回给用户,然后结束方法。
而49到62行,主要是判断是否存在BindingResult参数,如果有,说明有校验javaBean的意图,如果BindingResult有值,说明存在校验不通过的信息,那么就可以做处理了。通过这样的aop切面,就可以不用在每个controller方法里去处理校验信息了。

查看评论

SpringMVC中参数校验使用教程

一、环境准备 在项目中添加以下依赖 gradle org.hibernate:hibernate-validator:5.3.5.Final maven dependency> ...
  • KingBoyWorld
  • KingBoyWorld
  • 2017年12月29日 20:45
  • 810

【SpringMVC学习06】SpringMVC中的数据校验

这一篇博文主要总结一下springmvc中对数据的校验。在实际中,通常使用较多是前端的校验,比如页面中js校验,对于安全要求较高的建议在服务端也要进行校验。服务端校验可以是在控制层conroller,...
  • eson_15
  • eson_15
  • 2016年06月22日 20:30
  • 28795

SpringMVC优雅的实现数据校验

我们在使用SpringMVC提供接口时,所提供的参数难免会进行参数的合法性校验,比如非空校验,最原始的办法就是手动校验,比如下面的代码: if(StringUtils.isBlank(auth...
  • lynnlovemin
  • lynnlovemin
  • 2018年01月06日 15:18
  • 302

Spring MVC 参数字段校验

Spring MVC 参数字段校验Spring MVC 参数字段校验 校验规范 内置规则汇总 自定义校验规则 实际使用介绍 引入JAR包 基本使用介绍 结合RequestBody的使用介绍校验规范 ...
  • leiliang163
  • leiliang163
  • 2016年07月12日 17:51
  • 493

springmvc----参数校验

点滴记载,点滴进步,愿自己更上一层楼。加油!!!
  • xu1916659422
  • xu1916659422
  • 2017年08月20日 18:11
  • 358

SpringMVC验证框架Validation特殊用法

基本用法不说了,网上例子很多,这里主要介绍下比较特殊情况下使用的方法。 1. 分组 有的时候,我们对一个实体类需要有多中验证方式,在不同的情况下使用不同验证方式,比如说对于一个实体类来的id来说,保存...
  • wangpeng047
  • wangpeng047
  • 2014年12月11日 13:00
  • 57920

springmvc中的登录验证

Spring有自己的数据验证框架,DataBinder可以完成数据校验工作,下面以用户登录为例,说明登录操作怎样按照一定的规则验证用户提交的用户和密码. 1、  首先需要导入jar包文件 2、 ...
  • sounderme
  • sounderme
  • 2017年08月26日 12:57
  • 140

SpringMVC 参数校验

参数校验虽说大多在前台通过js完成,但是也应该懂得如何在后端实现参数的简单校验。由于本人目前处于初级阶段,所以文章的深度有限。随着时间推移我会逐渐更新。 参数校验的步骤我就不在赘述,推荐: 参数校...
  • taxuexumei
  • taxuexumei
  • 2017年08月21日 20:48
  • 240

springmvc使用校验框架validation校验

1      springmvc校验(服务端 ) b/s系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验性上考虑,但是在一些安全性要求高的系统中服务端校验是不可缺少的,本节主...
  • u012373815
  • u012373815
  • 2015年08月01日 22:24
  • 6836

spring注解式参数校验

spring hibenate注解式参数验证
  • jinzhencs
  • jinzhencs
  • 2016年06月15日 15:42
  • 24043
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 44万+
    积分: 5461
    排名: 6172
    博客专栏
    友情链接
    最新评论