java注解判断字段是否存在_JAVA 利用切面、注解 动态判断请求信息中字段是否需要为空...

项目中遇到一个需求,保存医生信息时,执业范围在医师编号为23开头时为必填项,其他医师编号时,执业范围为非必填项。当然这样的需求可以使用简单的if判断来解决,但是最近学习了注解的使用,刚好此需求可以用到,基本思路如下:

1、创建有条件判断字段为空的注解 ConditionalNotEmpty

2、在医生实体类--》执业范围字段上添加 ConditionalNotEmpty,并给出相应条件

3、切面类中使用java反射机制拿到注解信息,并根据传入的条件动态判断配置了该注解的字段是否需要校验空值

以下是大致代码:

1、注解

@Target({ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface ConditionalNotEmpty {

//分组标识

String groupIdentify() default "";

//错误提示信息

String message();

//业务操作标识

String[] operation() default {};

//判断依据的字段名称,如医师编号

String conditionFiledName() default "";

//判断条件,如本例中为医师编号起始值为23或者25,那么配置23,25

String contionString() default "";

}

2、医生信息实体中,在执业范围字段配置该注解

@Data

@Table(name = "t_doctor")

public class Doctor implements Serializable{

private static final long serialVersionUID = -7355208328761399457L;

@Id

private String id;

@NotEmpty(message = "职务代码不能为空",groups = {InsertGroup.class})

@Length(max = 3,message = "专业技术职务代码不能超过3位",groups = {InsertGroup.class})

private String zwdm;

@Length(max = 30,message = "证书编码不能超过30位",groups = {InsertGroup.class})

@ConditionalNotEmpty(groupIdentify = "1",message = "当职务代码前缀为 aa及前缀为 bb的编码时,证书编码必填",operation = {ValidateConstants.INSERT},conditionFiledName = "zwdm",contionString = "aa,bb")

private String zsbm;

}

3、切面类中获取注解并进行判断

package mypackage;

import org.apache.commons.lang3.ArrayUtils;

import org.apache.commons.lang3.StringUtils;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.reflect.MethodSignature;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;

import javax.validation.ConstraintViolationException;

import javax.validation.Validator;

import java.io.IOException;

import java.lang.annotation.Annotation;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.*;

/**

* @desc 校验结果处理

*/

@Aspect

@Component

public class CustomValidatedAop {

@Autowired

protected Validator validator;

/**

* @desc 判断是否存在@CustomValidated注解

*/

@Before("@annotation(org.springframework.web.bind.annotation.PostMapping) || @annotation(org.springframework.web.bind.annotation.DeleteMapping) || @annotation(org.springframework.web.bind.annotation.PutMapping) || @annotation(org.springframework.web.bind.annotation.GetMapping )|| @annotation(org.springframework.web.bind.annotation.RequestMapping )")

public void doBefore(JoinPoint joinPoint) throws IOException {

//切入点方法参数

Object[] params = joinPoint.getArgs();

MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

Method method = methodSignature.getMethod();

//获取方法参数类型

Class>[] paramsType = method.getParameterTypes();

Set errorMessages = new HashSet<>();

//获取方法参数上的注解(因为方法可以有多参数;参数上可以有注解,返回二维数组)

Annotation[][] an = method.getParameterAnnotations();

int index = 0;

//循环参数

for (Annotation[] an1 : an) {

Object param = params[index];

//循环参数上的注解

for (Annotation an2 : an1) {

//有自定义校验注解

if (an2 instanceof CustomValidated) {

//参数是List

if (param instanceof List) {

List list = (List) param;

for (Object l : list) {

errorMessages.addAll(this.beanValidator(l, ((CustomValidated) an2).value()));

}

} else {//参数非list

//获取该参数类型

Class clazz = paramsType[index];

//反射所有字段

Field[] fields = clazz.getDeclaredFields();

for(Field field : fields){

ValidateObj validateObj = field.getAnnotation(ValidateObj.class);

//如果字段上有自定义注解@ValidateObj

if(validateObj != null){

field.setAccessible(true);

try {

Object obj = field.get(param);

errorMessages.addAll(this.beanValidator(obj, ((CustomValidated) an2).value()));

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

errorMessages.addAll(this.beanValidator(param, ((CustomValidated) an2).value()));

}

//执行分组校验 begin

Set errorMessage = this.groupNotEmpty(param,((CustomValidated) an2).operation());

if(errorMessage != null && errorMessage.size() > 0){

errorMessages.addAll(errorMessage);

}

//执行分组校验 end

//执行有条件动态校验 begin

Set errorMessageCon = this.conditionalNotEmpty(param,((CustomValidated) an2).operation());

if(errorMessageCon != null && errorMessageCon.size() > 0){

errorMessages.addAll(errorMessageCon);

}

//执行有条件动态校验 end

if (errorMessages.size() > 0) {

List rtnStr = new ArrayList<>();

rtnStr.addAll(errorMessages);

throw new BusinessException(this.listToString(rtnStr));

}

}

}

index++;

}

}

/**

* @desc 通过validator进行分组校验返回错误信息

*/

protected List beanValidator(Object object, Class>... groups) {

List errorMessages = new ArrayList();

try {

Set constraintViolations = validator.validate(object, groups);

if (!constraintViolations.isEmpty()) {

return this.extractMessage(constraintViolations);

}

} catch (ConstraintViolationException ex) {

return errorMessages;

}

return errorMessages;

}

/**

* 转换Set为List

*/

protected List extractMessage(Set extends ConstraintViolation> constraintViolations) {

List errorMessages = new ArrayList();

for (ConstraintViolation violation : constraintViolations) {

errorMessages.add(violation.getMessage());

}

return errorMessages;

}

/**

* 工具方法 list转string

*/

protected String listToString(List mList) {

String convertedListStr = "";

if (null != mList && mList.size() > 0) {

String[] mListArray = mList.toArray(new String[mList.size()]);

for (int i = 0; i < mListArray.length; i++) {

if (i < mListArray.length - 1) {

convertedListStr += mListArray[i] + ",";

} else {

convertedListStr += mListArray[i];

}

}

return convertedListStr;

} else {

return "";

}

}

/***

* Description: 分组校验属性不能同时为空

* @param

* @return

*/

protected Set groupNotEmpty(Object param,String[] operation){

//本类及其父类的属性集合

List fieldList = new ArrayList<>() ;

Class tempClass = param.getClass();

//递归获取本身及父类的属性

//当父类不是object并且为null的时候说明到达了最上层的父类(form继承的Entity类).

while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {

//反射本类所有属性,包括私有属性

fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));

//得到父类,然后赋给自己

tempClass = tempClass.getSuperclass();

}

// key--groupId value true 都为空 false 不全为空

Map isNotEmptyMap = new HashMap<>();

// key--groupId value 所有message

Map emptyMessageMap = new HashMap<>();

for(Field field : fieldList){

GroupNotEmpty groupNotEmpty = field.getAnnotation(GroupNotEmpty.class);

if(groupNotEmpty != null){

//分组标识

String groupId = groupNotEmpty.groupIdentify();

if(StringUtils.isBlank(groupId)) {

groupId = UUIDUtils.generateUuid();

}

//操作标识

String[] operations = groupNotEmpty.operation();

//判断是否匹配controller中的校验操作

boolean isValidat = this.checkArray(operations,operation);

//不匹配跳出本次循环

if(isValidat){

continue;

}

//错误提示

String message = groupNotEmpty.message();

field.setAccessible(true);

try {

//带GroupNotEmpty注解的字段的值

Object obj = field.get(param);

boolean isNull = this.isNull(obj);

if (isNull) {

// 1. 为空则

if (isNotEmptyMap.containsKey(groupId)) {

emptyMessageMap.get(groupId).add(message);

} else {

isNotEmptyMap.put(groupId, true);

Set set = new HashSet();

set.add(message);

emptyMessageMap.put(groupId, set);

}

} else {

// 2. 不为空

isNotEmptyMap.put(groupId, false);

emptyMessageMap.put(groupId, new HashSet());

}

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

Set returnSet = new HashSet();

for(String groupId: isNotEmptyMap.keySet()) {

if (isNotEmptyMap.get(groupId)) {

returnSet.addAll(emptyMessageMap.get(groupId));

}

}

return returnSet;

}

/***

* Description: 校验当某属性属于特定值时,该注解字段校验非空

* @param

* @return

*/

protected Set conditionalNotEmpty(Object param,String[] operation){

//本类及其父类的属性集合

List fieldList = new ArrayList<>() ;

Class tempClass = param.getClass();

//递归获取本身及父类的属性

//当父类不是object并且为null的时候说明到达了最上层的父类(form继承的Entity类).

while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {

//反射本类所有属性,包括私有属性

fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));

//得到父类,然后赋给自己

tempClass = tempClass.getSuperclass();

}

Set returnSet = new HashSet();

try{

for(Field field : fieldList){

ConditionalNotEmpty conditionalNotEmpty = field.getAnnotation(ConditionalNotEmpty.class);

if(conditionalNotEmpty != null){

String conditionFiledName=conditionalNotEmpty.conditionFiledName();

String contionString=conditionalNotEmpty.contionString();

String[] prefixStrs=null;

if(StringUtils.isNotEmpty(contionString)){

prefixStrs=contionString.split(",");

}

//根据conditionFiledName 的值动态判断当前field是否需要不为空

boolean needCheckEmptyFlag=false;

//获取条件字段的值

Field conditionField = param.getClass().getDeclaredField(conditionFiledName);

conditionField.setAccessible(true);

//该参数为想要获取值得对象

Object conditionFieldValue = conditionField.get(param);

for(String prefixStr:prefixStrs){

if(conditionFieldValue.toString().startsWith(prefixStr)){

//需要校验当前字段不为空

needCheckEmptyFlag=true;

}

}

if(needCheckEmptyFlag){

//操作标识

String[] operations = conditionalNotEmpty.operation();

//判断是否匹配controller中的校验操作

boolean isValidat = this.checkArray(operations,operation);

//不匹配跳出本次循环

if(isValidat){

continue;

}

//错误提示

String message = conditionalNotEmpty.message();

field.setAccessible(true);

//带ConditionalNotEmpty注解的字段的值

Object obj = field.get(param);

boolean isNull = this.isNull(obj);

if (isNull) {

returnSet.add(message);

}

}

}

}

}

catch (IllegalAccessException e) {

e.printStackTrace();

}

catch(Exception e){

e.printStackTrace();

}

return returnSet;

}

//判空

protected boolean isNull(Object obj){

boolean isNull = false;

//字段是数组类型

if(obj instanceof java.lang.String[]){

String[] array = (String[]) obj;

if(array == null || array.length == 0){

isNull = true;

}

}

//字段是集合类型

else if(obj instanceof java.util.Collection){

Collection c = (Collection) obj;

if(c == null || c.size() == 0){

isNull = true;

}

}

//字段是其他对象类型

else {

if(obj == null){

isNull = true;

}else {

isNull = org.springframework.util.StringUtils.isEmpty(obj);

}

}

return isNull;

}

//判断一个数组中的元素是否在另一个数组中出现

private boolean checkArray(String [] array1,String [] array2){

boolean flag = true;

if((array1 != null && array1.length > 0) && (array2 != null && array2.length > 0)){

for(String s1 : array1){

if(ArrayUtils.contains(array2,s1)){

flag = false;

break;

}

}

}

return flag;

}

}

//

import java.lang.annotation.*;

/**

*

* @version 2018-09-29

* @desc 与Validated功能相仿只是把错误结果在aop中直接处理

*/

@Target({ ElementType.METHOD, ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface CustomValidated {

Class>[] value() default {};

//业务操作标识 jiaor

String[] operation() default {};

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值