1. Java中的参数验证(非Spring版)

1.1. 前言

  • 为什么我总遇到这种非正常问题,我们知道很多时候我们的参数校验都是放在controller层的传入参数进行校验,我们常用的校验方式就是引入下列的jar包,在参数中添加@Validated,并对Bean对象的参数做不同的注解处理就行,对Spring这种常用做法大家应该比较熟了
  • 但我现在遇到的需求,因为boss追求通用性,我们的controller入口只有一个,是通过传入参数中的不同tradeCode来区分调用哪个服务,这时我校验参数就得放到具体的每个服务方法上了,这样经过我的测试,加该注解已经不起作用了
    <!--jsr 303-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
    @PostMapping("/save/valid")
public RspDTO save(@RequestBody @Validated UserDTO userDTO) {
userService.save(userDTO);
return RspDTO.success();
}
@Data
public class UserDTO implements Serializable { private static final long serialVersionUID = 1L; /*** 用户ID*/
@NotNull(message = "用户id不能为空")
private Long userId; /** 用户名*/
@NotBlank(message = "用户名不能为空")
@Length(max = 20, message = "用户名不能超过20个字符")
@Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户昵称限制:最多20字符,包含文字、字母和数字")
private String username; /** 手机号*/
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
private String mobile; /**性别*/
private String sex; /** 邮箱*/
@NotBlank(message = "联系邮箱不能为空")
@Email(message = "邮箱格式不对")
private String email; /** 密码*/
private String password; /*** 创建时间 */
@Future(message = "时间必须是将来时间")
private Date createTime; }

1.2. 方案

  • 不能用它的注解,但我们可以用它的方法,下面我写了一个用Java代码验证参数的例子,抛砖引玉,并不能直接用在自己的系统哦,想要使用请结合自己系统封装方法,我打算做成注解的形式,利用spring aop切我的服务层,实现的效果就和controller层类似了

1.2.1. 主方法

import org.springframework.validation.annotation.Validated;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Date;
import java.util.Set;
import java.util.stream.Stream; /**
* @author laoliangliang
* @date 2019/10/22 15:19
*/
public class ValidLearn {
public static void main(String[] args) {
ValidLearn learn = new ValidLearn();
learn.testValid(new Order().setIdcard("33062119981012361X").setName(" ").setCreateDate(new Date()));
} public void testValid(@Validated Order order) {
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
//分组Insert.class则id为空不检验
Set<ConstraintViolation<Order>> validate = validator.validate(order, Insert.class);
Stream.of(validate).forEach(action -> {
for (ConstraintViolation<Order> orderConstraintViolation : action) {
String message = orderConstraintViolation.getMessage();
System.out.println(message);
}
});
}
}

1.2.2. 实体类

/**
* @author laoliangliang
* @date 2019/10/21 16:44
*/
@Data
@Accessors(chain = true)
public class Order { @NotNull(message = "id不能为空",groups = Update.class)
private Long id; @NotEmpty(message = "name is not null",groups = Insert.class)
private String name; @Future(message = "必须之后的时间")
private Date createDate; @IdCardValid(message = "idcard 不合法")
private String idcard;
}
  • 以上两个代码就可以做到检验实体类对象注解,并打印校验不通过的消息了,可以改造成存在校验错误消息则抛出异常
  • 代码还涉及了一些细节,比如group分组和自定义注解

1.2.3. group分组

import javax.validation.groups.Default;

/**
* @author laoliangliang
* @date 2019/10/22 16:32
*/
public interface Update extends Default {
}
import javax.validation.groups.Default;

/**
* @author laoliangliang
* @date 2019/10/22 16:32
*/
public interface Insert extends Default {
}
  • 我例子代码中用到了Insert.class,表示做插入动作时,存在这个分组的注解才会起作用,因此我id不传,id不为空的注解也不会起作用

1.2.4. 自定义注解

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* @author laoliangliang
* @date 2019/10/22 15:55
*/
public class IdCardValidator implements ConstraintValidator<IdCardValid, Object> { private Pattern pattern = Pattern.compile("^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])" +
"\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$");
@Override
public void initialize(IdCardValid idCardValid) {
} @Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
Matcher matcher = pattern.matcher(o.toString());
return matcher.matches();
}
}
/**
* @author laoliangliang
* @date 2019/10/22 15:53
*/
@Documented
@Target({ElementType.PARAMETER,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCardValid { String message() default "身份证不合法"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};
}
  • 这里我以验证身份证号为例,写了个自定义注解,实现ConstraintValidator接口,在isValid方法中实现自定义逻辑即可使用注解

1.3. 总结

  • 此篇举了Validation用Java代码实现验证的例子,应对service层参数验证,实际应用到自己代码可以自己写个自定义注解,实现aop切面,在切面中进行验证

Java中的参数验证(非Spring版)的更多相关文章

  1. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  2. Java 中可变参数

    可变参数 Java 中可变参数 现在需要编写一个求和的功能,但是不知道有几个参数,在调用的时候才知道有几个参数,请问这如何实现呢? Java 给我们提供了一个 JDK 1.5 的新特性---可变参数 ...

  3. Java中的阻塞和非阻塞IO包各自的优劣思考(经典)

    Java中的阻塞和非阻塞IO包各自的优劣思考 NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式. 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的,对一个 ...

  4. Java中的数据验证

    原文链接:https://www.cuba-platform.com/blog/2018-10-09/945 翻译:CUBA China CUBA-Platform 官网 : https://www. ...

  5. java bean validation 参数验证

    一.前言 二.几种解决方案 三.使用bean validation 自带的注解验证 四.自定义bean validation 注解验证 一.前言 在后台开发过程中,对参数的校验成为开发环境不可缺少的一 ...

  6. java中方法参数的一些总结(1)

    1.问题说明        在C++中,函数调用时有传值调用和传址调用两种方式,但在Java中只有传值调用一种方式.Java中的方法参数为那几种基本数据类型的情况跟C++中一样,传入的只是变量的拷贝. ...

  7. Summary: Java中函数参数的传递

    函数调用参数传递类型(java)的用法介绍. java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清. (一)基本数据类型:传值,方法不会改变实参的值. public class Te ...

  8. java中生成和验证jwt

    在这篇文章中主要记录一下在Java中如何使用 java 代码生成jwt token,主要是使用jjwt来生成和验证jwt,关于什么是JWT,以及JWT可以干什么不做详解. jwt的格式: base64 ...

  9. Java中静态变量与非静态变量的区别

    感谢大佬:https://www.cnblogs.com/liuhuijie/p/9175167.html ①java类的成员变量有俩种: 一种是被static关键字修饰的变量,叫类变量或者静态变量 ...

随机推荐

  1. 设备树(device tree)学习笔记【转】

    转自:https://www.cnblogs.com/pengdonglin137/p/4495056.html 阅读目录(Content) 1.反编译设备树 2.分析工具fdtdump 3.Linu ...

  2. CodeForces - 1253C(思维+贪心)

    题意 https://vjudge.net/problem/CodeForces-1253C n个糖果,一天最多吃m个糖果,每个糖果有个值a[i],第d天会变成d*a[i],问吃k(k=1~n)个糖果 ...

  3. 1.Python爬虫入门_urllib

    #2019-11-22 import urllib.request #Pthon自带的网络连接库 import gzip #解压缩库 #程序入口 if __name__=='__main__': #u ...

  4. itestpdf

    itestpdf jar pdf

  5. 压力测试中tps上不去的原因

    PS (transaction per second)代表每秒执行的事务数量,可基于测试周期内完成的事务数量计算得出.例如,用户每分钟执行6个事务,TPS为6 / 60s = 0.10 TPS. 同时 ...

  6. 日志检索实战 grep sed

    日志检索实战 grep sed 参考 sed命令 使用 grep -5 'parttern' inputfile //打印匹配行的前后5行 grep -C 5 'parttern' inputfile ...

  7. 工具资源系列之给 windows 虚拟机装个 centos

    前面我们已经介绍了如何在 Windows 宿主机安装 VMware 虚拟机,这节我们将利用安装好的 VMware 软件安装 centos 系统. 前情回顾 由于大多数人使用的 Windows 电脑而工 ...

  8. leetcode279. 完全平方数

    给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n.你需要让组成和的完全平方数的个数最少. 示例 1: 输入: n = 12输出: 3 解释: 12 = ...

  9. 用arthas查看JVM已加载的类及方法信息

    1.sc:“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 [d].[E].[f] 和 [x:]. [d] 输出当前类的详细信 ...

  10. 洛谷P3157 [CQOI2011]动态逆序对

    题目大意: 给定\(1\)到\(n\)的一个排列,按照给定顺序依次删除\(m\)个元素,计算每个元素删除之前整个序列的逆序对数量 基本套路:删边变加边 那么我们不就是求满足\(pos_i<pos ...