首先我们先了解 AOP切面中execution和annotation的区别,我们这次仅演示annotation的用法
@execution作用:就是指定你要切入的一个地方,比如具体的方法,或者是接口
@annotation作用:项目中的方法,凡是带有被这个annotation修饰的注解,然后这个注解所修饰的方法或是接口都会被拦截!
普通用法,直接写了一个反射方法处理。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BlankAno {
}
@Data
public class AnalysisRows implements Serializable {
private String id;
@BlankAno
private String crefo_no;
private String company_name;
private String company_name_en;
@BlankAno
private String company_name_old;
@BlankAno
private String company_aliasname;
}
/**
* 返回的部分字段置空值
* @param analysisRows
* @throws IllegalAccessException
*/
public void convertBlankField(AnalysisRows analysisRows) throws IllegalAccessException {
Class<?> clazz = AnalysisRows.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(BlankAno.class)) {
field.setAccessible(true);
field.set(analysisRows,"");
}
}
}
下面是Annotation使用AOP切面
/**
* 自定义注解 日志相关
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Syslog {
String value() default "操作日志";
String type() default "业务";
}
当检测到有SysLog则进入切面进行增强逻辑处理
@Syslog("用户登录")
@PostMapping("/login")
@ApiOperation("用户登录")
public ResponseDto login(@RequestBody User params) {
xxxx
}
进入AOP切面增强
/**
* 自定义注解切面
*/
@Aspect
@Component
public class SysLogAspect {
@Autowired
private BaseController baseController;
//注意这里是@annotation 不是@execution
@Pointcut("@annotation(com.linkedcare.technicalsupport.common.annotation.Syslog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long startTime = System.currentTimeMillis();
// 执行方法
Object result = point.proceed();
long costTime = System.currentTimeMillis() - startTime;
// 核心代码
saveSysLog(point,costTime);
return result;
}
private void saveSysLog(ProceedingJoinPoint point, long time) {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
String[] parameterNames = signature.getParameterNames();
Arrays.stream(parameterNames).forEach( x-> System.out.println("参数名"+x));
//Arrays.stream(signature.getParameterTypes()).forEach( x-> System.out.println("参数类型"+x.getFields()));
/* TypeVariable<Method>[] typeParameters = signature.getMethod().getTypeParameters();
Arrays.stream(typeParameters).forEach(x-> System.out.println("111"+x));*/
Class[] parameterTypes = signature.getParameterTypes();
for (Class parameterType : parameterTypes) {
Field[] fields = parameterType.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println("2222"+field.getName());
// 获取不到调用时传递的参数值,查资料也许可以使用cglib动态代理实现
}
}
SysLogEntity sysLog = new SysLogEntity();
// 获取注解的参数
Syslog annotation = method.getAnnotation(Syslog.class);
if (annotation != null) {
// 注解上的描述
sysLog.setOperation(annotation.value());
}
// 请求的方法名
String className = point.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
sysLog.setDelTag(0);
// 请求的参数
Object[] args = point.getArgs();
String params = JSONObject.toJSONString(args);
if (annotation.value().equals("退出当前账号")) {
sysLog.setParams(null);
} else {
sysLog.setParams(params);
}
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// 获取ip
sysLog.setIp(IpUtils.getIpAddr(request));
// 获取操作用户
//如果是登录就走参数查用户名
if (annotation.value().equals("登录")) {
/* JSONArray objects = JSON.parseArray(params);
if (objects != null && objects.size() > 0) {
JSONObject jsonObject = objects.getJSONObject(0);
if (Objects.nonNull(jsonObject)) {
//查询操作者名字
if (StringUtils.isNotBlank(jsonObject.getString("userName"))) {
sysLog.setUserName(jsonObject.getString("userName"));
}
}
}*/
User loginUser = baseController.getLoginUser();
sysLog.setUserName(loginUser.getUserName());
} else {
/* //用户名
String userName = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUserName();
sysLog.setUserName(userName);*/
}
//保存日志
}
}