前言:

本文不是讲@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. 一致性哈希做负载均衡,基于dubbo的简化版本,超级简单容易理解!!!

    一致性哈希算法原理以及做分布式存储.一定先看:一致性哈希算法 dubbo提供了四种负载均衡实现:权重随机算法,最少活跃调用数算法,一致性哈希算法,加权轮询算法. 本文基于开源项目:guide-rpc- ...

  2. 动态地绑定到它的 is 特性,可以实现动态组件

    前面的话 让多个组件使用同一个挂载点,并动态切换,这就是动态组件.本文将详细介绍Vue动态组件 概述 通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动 ...

  3. overflow和absolute之间的问题,transfrom可以解决

    CSS代码: .overflow { width: 191px; height: 191px; border: 2px solid #beceeb; overflow: hidden; } .over ...

  4. VPS、云主机 and 服务器集群、云计算 的区别

    VPS:(virtual private server)虚拟专用服务器,将一台服务器分割成多个虚拟专享服务器的优质服务.实现VPS的技术分为容器技术和虚拟化技术.在容器或虚拟机中,每个VPS都可分配独 ...

  5. UVA10391复合词

    题意:      给定一个词典,然后问里面那些是复合词,复合词就是当前这个单词正好是有两个单词拼接而成. 思路:       用map来标记是否出现过,然后先按长短排序,把每个单体拆分成任意两个可能的 ...

  6. 学习Python一年,这次终于弄懂了浅拷贝和深拷贝

    官方文档:copy主题 源代码: Lib/copy.py 话说,网上已经有很多关于Python浅拷贝和深拷贝的文章了,不过好多文章看起来还是决定似懂非懂,所以决定用自己的理解来写出这样一篇文章. 当别 ...

  7. 《前端运维》一、Linux基础--基础命令(1)

    在开始之前,你需要做一些准备工作,去阿里买一台服务器,服务器的具体细节其实并不是十分重要,我也不会在这里一步一步的教大家如何去买一个服务器.百度一下足够了,但是还是要贴一下这篇文章中,我所使用的服务器 ...

  8. IntelliJ IDEA打开Maven项目,Spring boot所有依赖红名,不可用

    导入外部的springboot项目时,出现报红线,无论怎么刷新maven就是不下载依赖包,情况如下 解决办法: 1)直接去自己的maven仓库,找到Spring boot,然后直接删除下面的文件 2) ...

  9. Getting Started and Beyond|云原生应用负载均衡选型指南

    作者 冉昕,腾讯云服务网格TCM产品经理,现负责云原生流量接入网关与应用通信可观测性等产品特性策划与设计工作. 刘旭,腾讯云高级工程师,专注容器云原生领域,有多年大规模 Kubernetes 集群管理 ...

  10. 【Web前端HTML5&CSS3】03-字符实体与语义标签

    笔记来源:尚硅谷Web前端HTML5&CSS3初学者零基础入门全套完整版 目录 字符实体与语义标签 1. 字符实体 2. meta标签 3. 语义标签 4. 块元素与行内元素 块元素(bloc ...