一、原理:

  1、做一个field注解,注解有两个参数:是否必填、toString之后的最大长度

  2、对某个request类(或基类),使用注解标记某个字段的校验详情

  3、通用的static方法,利用反射获取属性的值,并做校验。不通过则抛出特定的异常

二、上代码:

异常类:

package com.test;

/**
* 基础异常
* @author zyydd
* @date 2019/1/24 10:33
* @version 1.0.0
**/
public class BaseException extends RuntimeException { /** 异常码 */
private String code;
/** 异常描述 */
private String desc; public BaseException(){ } public String getCode() {
return code;
} private void setCode(String code) {
this.code = code;
} public String getDesc() {
return desc;
} private void setDesc(String desc) {
this.desc = desc;
} public BaseException(String code, String desc) {
this(code, desc, new Throwable(desc));
} public BaseException(String code, String desc, Throwable canse) {
super(new StringBuilder().append("code=").append(code).append(", desc=").append(desc).toString(), canse);
this.setCode(code);
this.setDesc(desc);
} @Override
public String toString() {
return new StringBuilder().append(getClass().getName())
.append("{code=").append(this.getCode())
.append(", desc=").append(this.getDesc())
.append("}").toString();
}
}

测试的request类:

package com.test;

/**
* @author zyydd
* @date 2019/6/13 18:29
*/
public class TestChildRequest {
/**
* name
*/
@ParameterAttr(isNecessary = true, lengthLimit = 10)
private String name; /**
* pin
*/
@ParameterAttr(lengthLimit = 15)
private String address; @ParameterAttr(isNecessary = true)
private String school; private String other; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public String getSchool() {
return school;
} public void setSchool(String school) {
this.school = school;
} public String getOther() {
return other;
} public void setOther(String other) {
this.other = other;
}
}

field校验注解类:

package com.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @author zyydd
* @date 2019/6/13 16:52
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParameterAttr {
/**
* 是否必须,默认不必须
*
* @return
*/
boolean isNecessary() default false; /**
* 属性toSring之后,最大长度
*
* @return
*/
int lengthLimit() default 0; }

通用校验工具类及main测试方法:

package com.test;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; /**
* @author zyydd
* @date 2019/6/13 17:02
*/
public class ParameterCheckUtils {
private static Logger logger = LoggerFactory.getLogger(ParameterCheckUtils.class); public static void commonCheck(Object obj) throws IllegalAccessException {
if (obj == null) {
logger.error("obj can not be null!");
throw new BaseException("9999", "obj can not be null!");
} List<Field> fieldList = new ArrayList<Field>();
Class clazz = obj.getClass();
while (!Object.class.equals(clazz)) {
fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
for (Field field : fieldList) {
field.setAccessible(true);
ParameterAttr attr = field.getAnnotation(ParameterAttr.class);
if (attr == null) {
continue;
}
Object paramObj = field.get(obj);
if (attr.isNecessary()) {
if (paramObj == null || StringUtils.isBlank(paramObj.toString())) {
logger.error("class={} field={} can not be null!", obj.getClass().getName(), field.getName());
throw new BaseException("9998", "field=" + field.getName() + " can not be null!");
}
}
if (attr.lengthLimit() > 0 && paramObj != null && StringUtils.isNotBlank(paramObj.toString())) {
if (paramObj.toString().length() > attr.lengthLimit()) {
logger.error("class={} field={} length is too long! limit={} but length={}", obj.getClass().getName(), field.getName(), attr.lengthLimit(), paramObj.toString().length());
throw new BaseException("9997", "field=" + field.getName() + " length is too long!");
}
}
}
logger.info("commonCheck success!");
} public static void main(String[] args) throws IllegalAccessException {
//正常数据
TestChildRequest request1 = new TestChildRequest();
request1.setName("王钢蛋");
request1.setAddress("aabbccddeeaabbc");
request1.setSchool("北京市智障二中");
ParameterCheckUtils.commonCheck(request1); //为空数据
try {
ParameterCheckUtils.commonCheck(null);
} catch (Exception e) {
logger.error("error1 ", e); }
//必填没传的数据
try {
TestChildRequest request2 = new TestChildRequest();
request2.setName("王钢蛋");
request2.setAddress("aabbccddeeaabbc");
ParameterCheckUtils.commonCheck(request2);
} catch (Exception e) {
logger.error("error2 ", e);
} //字段超长的数据
try {
TestChildRequest request3 = new TestChildRequest();
request3.setName("王钢蛋");
request3.setAddress("aabbccddeeaabbcc");
request3.setSchool("北京市智障二中");
ParameterCheckUtils.commonCheck(request3);
} catch (Exception e) {
logger.error("error3 ", e);
}
} }

执行结果:

java利用注解及反射做通用的入参校验的更多相关文章

  1. 【Java】利用注解和反射实现一个"低配版"的依赖注入

    在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...

  2. Java基于注解和反射导入导出Excel

    代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...

  3. 使用Java元注解和反射实现简单MVC框架

    Springmvc的核心是DispatcherServlet来进行各种请求的拦截,进而进行后续的各种转发处理.流程图如下: 说明:客户端发出一个http请求给web服务器,web服务器对http请求进 ...

  4. Java之注解与反射

    Java之注解与反射 注解(Annotation)简介 注解(Annotation)是从JDK5.0引入的新技术 Annotation作用:注解(Annotation)可以被其他程序如编译器等读取 A ...

  5. java自定义注解与反射

    java注解与反射一.Java中提供了四种元注解,专门负责注解其他的注解,分别如下 1.@Retention元注解,表示需要在什么级别保存该注释信息(生命周期).可选的RetentionPoicy参数 ...

  6. java 利用注解实现BaseDao 增删查改

    第一步,编写两个注解类,用于表明实体类对应的表名及字段. TableInfo.java 此注解用于标注表名及主键名 import static java.lang.annotation.Element ...

  7. postman中用当前时间戳做请求的入参

    用postman做接口测试的,有些接口需要带上当前时间的时间戳作为请求的入参,postman支持这种功能吗? 答案是肯定的. 文中有使用时间戳的两种方法和postman常用的预定义变量. 例子中接口的 ...

  8. Java注解(Annotation)用法:利用注解和反射机制指定列名导出数据库数据

    闲来没事,想了一个应用的例子:用java如何把数据库的数据根据我们指定的某几列,如第2列,第4列,第6列导出来到Excel里? 写代码也是为了应用的,写好的代码更重要的是在于思考.我自己思考了这个示例 ...

  9. Java基础--注解、反射

    一.注解(Annotation) 1.什么是注解? 从JDK5开始,Java增加了Annotation(注解),Annotation是代码里的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行 ...

随机推荐

  1. Application类-应用程序生命周期

    1.创建Application对象 新建WPF程序后,排除掉WPF自动创建的App.xaml,我们自定义一个类,在该类的Main()方法中,创建Application对象,然后调用创建一个窗口对象,最 ...

  2. 通过SharpZipLib实现文件夹压缩以及解压

    代码说明 基于SharpZipLib实现Zip压缩解压,扩展实现文件夹级别压缩解压: 项目源码:MasterChief.DotNet.Infrastructure.Zip Install-Packag ...

  3. python基础知识(最基本)

    保留字(关键字)   False None True and as break class continue def elif else except finally for from global ...

  4. Python的变量命名规则

    1.只能用大小写字母与“_”(下划线) 2.数字不能用在开头,如:12tea 3.不能使用空格 4.C语言的变量命名规则如上相同

  5. yaml格式配置文件

    YAML 是一种可读性非常高,与程序语言数据结构非常接近.同时具备丰富的表达能力和可扩展性,并且易于使用的数据标记语言. python中处理 Yaml 格式的数据需要先下载pyyaml: pip in ...

  6. MySQL数据物理备份之lvm快照

    使用lvm快照实现物理备份 优点: 几乎是热备(创建快照前把表上锁,创建完后立即释放) 支持所有存储引擎 备份速度快 无需使用昂贵的商业软件(它是操作系统级别的) 缺点: 可能需要跨部门协调(使用操作 ...

  7. vmware虚拟机安装T6客户端

    1.虚拟机安装T6 经过测试,vmware 里系统装T6  网络适配器必须使用桥接,nat模式是无法连接数据库的

  8. springboot easypoi 报错The bean 'beanNameViewResolver', defined in class path resource [cn/afterturn/e

    事故现场: The bean 'beanNameViewResolver', defined in class path resource [cn/afterturn/easypoi/configur ...

  9. Ubuntu16.04下Python2:pip安装opendr库

    在Ubuntu16.04/Python2环境安装opendr遇到了问题,并且报错不清楚. 使用dis_to_free的方法很好地解决问题. sudo apt install libosmesa6-de ...

  10. CentOS6.10部署的Tomcat8.5启动后,浏览器访问不到的解决方法

    解决过程如下: 一.关闭 selinux 和 iptables 防火墙 二.查看 tomcat 是否在运行 ps aux |grep tomcat 三.查看端口情况 lsof -i:8080 查看后都 ...