前言:

本文不是讲@Validate、@Valid是如何使用的、区别是什么,想看这些内容的请换篇文章。

背景:

当前端传过来的参数是进行对称性加密、base64加密等处理后过的参数时,在controller接口使用@Validae、@Valid 主键是没用的。
接口收到加密参数后,第一步应该是解密,然后再转换为实际的参数。那么判断参数字段是否符合条件又要写代码去判断了,不够优雅。
那么我是怎么做的呢?看下文...

假设我们现在有一个登录接口,大概是下面这样↓↓↓↓↓↓↓↓↓↓↓

原本的登录逻辑

@PostMapping(value = "/login")
public R login(@RequestParam(value = "param") String param){ // 1:将参数解密出来拿到解密后的字符串(对称性解密)
String realParam = rsa.decryptStr(encryptParamsVO.getParams(), KeyType.PrivateKey, StandardCharsets.UTF_8); // 2:将解密后的字符串转换为dto
LoginDto dto = JSON.parseObject(realParam , UserDto.class); // 3:靠代码进行字段规则判断
if(StringUtils.isBlank(dto.getUsername)){
throw new ServiceException("password不能为空");
}
if(StringUtils.isBlank(dto.getPassword)){
throw new ServiceException("password不能为空");
} // 4:校验通过后登陆
userService.login(dto); return R.success();
}

可以看到第三步有这明显的缺陷,如果 LoginDto 参数一多,那么就要写很多 if 语句代码来进行判断,这样势必是不优雅的写法。

参数类

@Data
public class LoginDto { @NotBlank(message = "用户名不能为空")
@Size(min = 6, max = 16, message = "用户名格式不正确")
private String username; @NotBlank(message = "密码不能为空")
@Size(min = 8, max = 16, message = "密码格式不正确")
private String password;
}

这个类其实才是接口中实际用到的参数类。而它本身的字段其实是用了@NotNull、@Size注解修饰过的,只不过没有起到作用。

那么参数在解密后转换为 LoginDto 后如何让这些注解起到原本的作用呢?

自己写个工具类

@Slf4j
public class JSRValidatorUtil { private final static Validator VALIDATOR = Validation.byProvider(HibernateValidator.class)
.configure()
.buildValidatorFactory().getValidator(); public static <T> void validate(T param) {
Set<ConstraintViolation<T>> validate = VALIDATOR.validate(param);
validate.forEach(v -> {
log.error("JSR校验异常,property:{},message:{}", v.getPropertyPath(), v.getMessage());
throw new ServiceException(v.getMessage());
});
}
}

看看测试效果:

    @Test
public void validateTest() {
LoginDto loginDto = new LoginDto();
loginDto.setUsername("123456");
loginDto.setPassword("123456"); JSRValidatorUtil.validate(loginDto);
}

利用Spring自带的Validator、SpringValidatorAdapter

    @Resource
private SpringValidatorAdapter adapter;
@Resource
private Validator validator; @Test
public void validate() {
LoginDto loginDto = new LoginDto();
loginDto.setUsername("123456");
loginDto.setPassword("123456"); Set<ConstraintViolation<LoginDto>> validate1 = adapter.validate(loginDto);
Set<ConstraintViolation<LoginDto>> validate2 = validator.validate(loginDto); validate1.forEach(v -> logger.error("JSR校验异常,property:{},message:{}", v.getPropertyPath(), v.getMessage()));
validate2.forEach(v -> logger.error("JSR校验异常,property:{},message:{}", v.getPropertyPath(), v.getMessage()));
}

自定义符合JSR330规范的注解

很多场景下需要自定义注解实现的,比如字段属性为 性别、密码、身份证 等等。

自定义一个密码格式校验注解:

@Constraint(validatedBy = PasswordValidation.class)
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Password { String message() default "密码必须包含大小写英文字符、数字、特殊字符"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }

规则实现类:

public class PasswordValidation implements ConstraintValidator<Password, String> {

    @Override
public boolean isValid(String value, ConstraintValidatorContext context) {
boolean haveDigit = false;
boolean uppercase = false;
boolean lowercase = false;
boolean special = false; char v;
for (int i = 0; i < value.length(); i++) {
v = value.charAt(i);
if (Character.isDigit(v))
haveDigit = true;
else if (Character.isUpperCase(v))
uppercase = true;
else if (Character.isLowerCase(v))
lowercase = true;
}
if (Pattern.compile("[ _`~!@#$%^&*()+=|{}':;,\\[\\].<>/?!¥…()—【】‘;:”“’。,、?]|\n|\r|\t").matcher(value).find())
special = true; return haveDigit && uppercase && lowercase && special;
}
}

使用@Password 注解修饰

    @Password
private String password;

看效果:

如何优雅的做参数校验-JSR330的更多相关文章

  1. 使用hibernate validate做参数校验

    1.为什么使用hibernate validate ​ 在开发http接口的时候,参数校验是必须有的一个环节,当参数校验较少的时候,一般是直接按照校验条件做校验,校验不通过,返回错误信息.比如以下校验 ...

  2. 寻找写代码感觉(十六)之 集成Validation做参数校验

    写在前面 今天是大年初五了... 不知不觉,又要上班了,美好的假期只剩一天了,有点不舍呢! 也不知道为什么,总感觉像在做梦一样,像没睡醒一样,并不是因为眼睛小,更多应该是自寻烦恼,想得多罢了. 参数校 ...

  3. SpringBoot Validation优雅的全局参数校验

    前言 我们都知道在平时写controller时候,都需要对请求参数进行后端校验,一般我们可能会这样写 public String add(UserVO userVO) { if(userVO.getA ...

  4. 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!

    本文为作者原创,如需转载请在文首著名地址,公众号转载请申请开白. springboot-guide : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维 ...

  5. 如何在 Spring/Spring Boot 中做参数校验

    数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...

  6. spring mvc +@Valid +@RequestBody 来做参数校验返回400,并且不显示具体message 如何解决

    参考文档: https://www.oschina.net/question/115867_2282711   谢谢原作者

  7. 全栈项目|小书架|服务器开发-Koa2 参数校验处理

    为什么需要做参数校验 在开发中,无论是App开发还是服务器接口开发, 我们无法去预测用户传入的数据,因此参数(数据)校验是开发中不可或缺的一环. 例如像App的注册登录表单提交页面,就要做好多层的判断 ...

  8. SpringBoot中通过实现WebMvcConfigurer完成参数校验

    在Spring5.0和SpringBoot2.0中废弃了WebMvcConfigurerAdapter类. 现有两种解决方案 1 直接实现WebMvcConfigurer (官方推荐)2 直接继承We ...

  9. 为List<T>中的T进行参数校验

    1.现在前端发送了一个POST请求,他的Data是一个数组,而不是对象(jsonObj的值两侧是中括号). var jsonObj = [{'id':11, 'name':'叵'}, {'id':12 ...

随机推荐

  1. 构建基于表单配置的 Jenkins 测试项目(接口、UI、APP、Jmeter)

    1. 第一个 hello world 项目 2. 构建自动触发的项目(接口测试) 1)新建测试项目(执行测试脚本) 2)新建 Maven 打包项目 3)手动执行构建 4)修改 Web 工程代码并 pu ...

  2. 软件调研——GoodNotes 5与Notability

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 作业要求 我在这个课程的目标是 积累软件开发经验,提高工程能力 这个作业在哪个具体方面帮助我实现目标 深入调 ...

  3. 1036 Boys vs Girls

    This time you are asked to tell the difference between the lowest grade of all the male students and ...

  4. 07- Linux常用命令

    cat命令 作用:将文件内容作为标准输出打印到终端. 格式:cat   文件名1  文件名2 例如: cat more命令: 作用:分页显示文本文件的内容 格式:more 文件名 实例:more he ...

  5. UVA11375火柴(递推+大数)

    题意:       给你n根火柴,问你能组成多少种数字,比如3根可以组成1或者7,组成的数字中不能有前导0, 思路:       我们开一个数组,d[i]记录用i跟火柴可以组成多少种数字,则更新状态是 ...

  6. [CTF]ROT5/13/18/47位移密码

    [CTF]ROT5/13/18/47位移密码 ---------------转换网站 https://www.qqxiuzi.cn/bianma/ROT5-13-18-47.php ROT5:只对数字 ...

  7. 『动善时』JMeter基础 — 8、JMeter主要元件介绍

    目录 1.测试计划(Test Plan) 2.线程组 3.取样器(sampler) 4.逻辑控制器(Logic Controller) 5.配置元件(Config Element) 6.定时器(Tim ...

  8. 【js】Leetcode每日一题-完成所有工作的最短时间

    [js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...

  9. Java中volatile关键字你真的理解了吗?

    面:你怎样理解volatile关键字时? 我:不加思索的说出,volatile修饰的成员变量,可保证线程可见性.不保证原子性和禁止指令重排. 面:你能谈谈什么是线程可见性吗? 我:各个线程对主内存中共 ...

  10. Handle详解

    首先通过一个函数启动一个服务器,只提供一个方法并返回Hello World!,当你在浏览器输入http://127.0.0.1:8080,就会看到Hello World. 对于http.ListenA ...