<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
2.1 自定义一个方法注解
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ValidatedMethodAnnotations {
}
2.2 自定义一个参数、字段注解,定义一个默认值,后面使用
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
public @interface ValidatedCharAnnotations {
String value() default "";
}
注:上述的两个注解可以定义一个就行了,将ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER放在一个项即可。
import com.ahdhst.commons.webmvc.exception.CommonException;
import com.ahdhst.lzz.lzt25.annotations.ValidatedCharAnnotations;
import com.ahdhst.lzz.lzt25.annotations.ValidatedMethodAnnotations;
import com.ahdhst.lzz.lzt25.enums.core.ResultEnum;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@Component
@Aspect
@Slf4j
public class ValidatedAspect {
//指定一个或者多个controller,如果多个controller用“||”隔开即可
//within(com.ahdhst.lzz.lzt25.controller.cms.CmsInfoFileController)
/*
指定注解切面处理,希望在下列的方法中添加参数,在argNames指定。字段名与参数名一致。第一个* 表示返回值的类型任意;第二个* 或者.. 表示包名或者类名,.*(..) 表示任何方法名,括号表示参数,两个点表示任何参数类型
*/
@Around(value = "(execution(* com.ahdhst.lzz.lzt25.controller.*.*.*(..))) && @annotation(megLog)", argNames = "joinPoint,megLog")
public Object around(ProceedingJoinPoint joinPoint, ValidatedMethodAnnotations megLog) throws Throwable {
// System.out.println("aspect is run!!");
//自定义注解下的方法参数信息获取
Object[] args = joinPoint.getArgs();
// 方法签名
Signature signature1 = joinPoint.getSignature();
// 获取的是代理类的method对象
Method method1 = ( (MethodSignature)signature1 ).getMethod();
// 这个方法才是目标对象上有注解的方法
Method realMethod = joinPoint.getTarget().getClass().getDeclaredMethod(signature1.getName(), method1.getParameterTypes());
// 取出对应的注解
String name = "";
int num = -1;
Annotation[][] parameterAnnotations = realMethod.getParameterAnnotations();
//锚
A: for (Annotation[] annotations : parameterAnnotations) {
for (Annotation annotation : annotations) {
//获取注解名
name = annotation.annotationType().getSimpleName();
num = num + 1;
if (name.equals("ValidatedCharAnnotations")){
break A;
}
}
}
//方法参数中注解为本人自定义的注解,获取该注解下的参数值,参数为一个对象,该对象中的字段,需要校验的,则加上自定义注解
if(name.equals("ValidatedCharAnnotations")){
//获取对象信息
Object object = args[num];
//获取对象属性
Field[] fieldArr = object.getClass().getDeclaredFields();
//校验错误集
List<String> errorList = new ArrayList<>();
//遍历属性,获取属性值
for(Field objectField : fieldArr){
//获取属性的类型
String ftype = objectField.getGenericType().toString();
//字符串输入校验特殊字符
if(ftype.equals("class java.lang.String")){
//校验是否存在自定义注解的机制
ValidatedCharAnnotations vca = objectField.getAnnotation(ValidatedCharAnnotations.class);
if(null != vca){
//获取属性名称
String fname = objectField.getName();
//首字母大写处理
fname = fname.substring(0,1).toUpperCase()+fname.substring(1,fname.length());
//利用反射原理,调用getter方法获取属性值
Method m = object.getClass().getMethod("get"+fname);
String value = (String) m.invoke(object);
//特殊字符开头的正则表达式
String regEx = "^[+ * \\[ \\] \\ < > ?]+.*";
if(Pattern.compile(regEx).matcher(value).matches()){
//vca.value():获取自定义注解的描述
errorList.add(vca.value()+":"+value+"存在特殊字符");
}
log.info("参数值:{},属性值:{}",vca.value(),value);
}
}
}
if(CollectionUtils.isNotEmpty(errorList)){
throw new CommonException(ResultEnum.ERROR_MESSAGE_SPECIAL_CHARACTER_EXIT,errorList.toString());
}
//已经通过的继续处理业务
return joinPoint.proceed(args);
} else {
//没有这个注解的不验证,继续处理业务
return joinPoint.proceed(args);
}
}
}
@ApiOperation(value = "人员信息列表接口", notes = "查询条件:用户名、姓名、所属机构")
@GetMapping("/userList/{pageNum}/{pageSize}")
@ValidatedMethodAnnotations //方法注解
public DHResult<PageSerializable<UserInfoResult>> userList(@PathVariable Integer pageNum, @PathVariable Integer pageSize,@ValidatedCharAnnotations SearchUserParam param) { //参数注解
return null;
}
@ApiModel("员工列表查询入参")
@Data
public class SearchUserParam {
@ApiModelProperty(value = "用户名")
@ValidatedCharAnnotations("用户名") //字段注解
private String phone;
@ApiModelProperty(value = "姓名")
private String realName;
@ApiModelProperty(value = "所属机构id")
private Integer orgId;
@ApiModelProperty(value = "所属机构名称")
private String orgName;
@NotBlank
@ApiModelProperty(value = "所属站点id", required = true)
private String appId;
}
基于spring boot框架,PostgreSQL数据库,针对特殊开头的条件搜索存在处理报错。由于项目场景比较多,想到了自定义注解、切面处理这类的问题。如有大佬们有好的思路,请指导一下小弟,小弟在此谢过了。