一、原理:

  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. Asp.NetCoreWebApi - RESTful Api

    目录 参考文章 REST 常用http动词 WebApi 在 Asp.NetCore 中的实现 创建WebApi项目. 集成Entity Framework Core操作Mysql 安装相关的包(为X ...

  2. 我是如何一步步编码完成万仓网ERP系统的(六)产品库设计 2.百度Ueditor编辑器

    https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...

  3. 我是如何一步步编码完成万仓网ERP系统的(八)产品库设计 4.品牌类别

    https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...

  4. ElasticSearch查看删除关闭索引

    curl -XDELETE 'http://10.1.2.2:9200/iis_log_2019-07'     #删除名为/iis_log_2019-07的索引 curl -XPOST 'http: ...

  5. php服务端搜索,功能改进

    php中 ,一直以来,服务端搜索,我都是写一堆条件判断,搜索条件少时还好,条件一多,就显的代码有点丑陋了: 看着非常不舒服.今天在园子里看到一篇文章(http://www.cnblogs.com/xq ...

  6. 一、NodeJS入门——准备工作(1)——NodeJS的安装

    目录 1.介绍 2.nodejs下载 3.nodejs安装 4.nodejs的简单实用 5.nodejs的经典入门:hello world 6.总结 1    介绍 这是一系列的内容主要是关于我在学习 ...

  7. i春秋——“百度杯”CTF比赛 十月场——Not Found(http请求方法,client-ip伪造ip)

    这道题也是让我很迷... 打开就是not found,让我一度以为是服务器挂了,细看发现有个404.php 访问也没发现什么东西,只有来自出题人的嘲讽 haha~ 不过在首页的header中发现个奇怪 ...

  8. JVM参数最佳实践:元空间的初始大小和最大大小

    本文阅读时间大约4分钟. JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Meta ...

  9. MySQL Error--InnoDB Table mysqlinnodb_index_stats has length mismatch in the column

    使用MySQL 5.7.24版本的安装文件替换MySQL 5.7.19版本的安装文件,数据库复制频繁中断,查看error日志发现下面错误: [Warning] InnoDB: Table mysql/ ...

  10. 简明conda使用指南

    目录 区分conda, anaconda, miniconda conda版本 虚拟环境 分享环境 查看某个环境的位置 列出软件包 安装软件包 删除软件包 查找软件包 conda配置 conda实践: ...