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. 我认为现代IDE编辑器应该具有的几个特性和Visual studio 2010增强

    工作中要使用 VS 2010, 有好多年没有使用Visual studio 了, 试了一小会, 发现VS 2010 缺少不少现代IDE应有的特性, 我认为重要的是下面几个特性, VS2010 已经是1 ...

  2. [MySQL] mysql地理位置服务geometry字段类型

    这个字段类型是mysql5.7新增的功能,主要就是解决坐标存储和距离计算的常见问题 创建表:CREATE TABLE `service` ( `id` bigint(20) NOT NULL AUTO ...

  3. Linux同一机器设置多个IP2019-7-6

    1.临时增加 1)先查看目前的网卡信息 [root@study ~]# ifconfigeno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAS ...

  4. Shell命令-用户用户组管理之id、su

    文件及内容处理 - id.su 1. id:查看用户的uid,gid及归属的用户组 id命令的功能说明 id 命令用于显示用户的 ID,以及所属群组的 ID.id 会显示用户以及所属群组的实际与有效I ...

  5. Shell命令-用户用户组管理之visudo、sudo

    文件及内容处理 - visudo.sudo 1. visudo:编辑/etc/sudoers文件的专属命令 visudo命令的功能说明 visudo命令专门用来编辑/etc/sudoers这个文件的. ...

  6. Java学习笔记(2)--- 对象和类入门,java包,this 和 super区别

    1.对象和类(Object and class): 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作. 面对对象编程是java非常重要的一部分,作者本身之前学过c ...

  7. 报错Error resolving template template might not exist or might not be accessible解决方案

    "C:\Program Files\Java\jdk1.8.0_144\bin\java" "-javaagent:D:\IntelliJ IDEA Community ...

  8. 3.jenkins--- 配置

    一 .系统配置 Mange  jenkins  ------->   configure  system 并发数量可以调整成10个, Usage(使用): 指允许运行绑定到本机的job  ,这个 ...

  9. shell的几个实战脚本例子(欠)

    如何让shell实现 可选择性执行 的功能 巡检内存使用率 批量创建用户 场景:公司想要做测试,需要10000个用户 数据库里查询学生成绩 #如何登录mysql数据库 #如何写sql对数据进行操作 # ...

  10. nowcoder941B 弹钢琴

    题目链接 思路 首先按照音色排个序,顺便离散化一下音高. 用\(h[i]\)表示第\(i\)个键的音高,用\(w[i]\)表示第\(i\)个键的春希度. 朴素\(dp\) \(f[i][j]\)表示前 ...