提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、aop是什么?
- 二、使用步骤
- 1.引入pom文件依赖
- 2.请求日志记录
- 总结
前言
本文主要描述面向切面编程AOP的用例
一、AOP是什么?
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
二、使用步骤
1.引入pom文件依赖
代码如下(示例):
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.4</version> </dependency>
2.请求日志记录
代码如下(示例):
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface OptLog {/*** 操作日志类型** @return*/OperationTypeEnum scenesType();/*** 请求处理状态** @return*/int status() default 0;/*** 写SpEL表达式 获取request请求内容** @return*/String request() default "";/*** request请求内容的类型** @return*/Class<?> requestType() default String.class;/*** 默认 系统管理员* 其他的取当前登录人** @return*/String operationUser() default "系统管理员";/*** 默认 系统管理员* 其他的取当前登录人** @return*/long operationUserId() default 0L;
}
@Slf4j
@Aspect
@Component
public class OptLogAspect {/*** 用于SpEL表达式解析.*/private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();/*** 用于获取方法参数定义名字.*/private final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();@Autowiredprivate InLogRepository inLogRepository;@Pointcut("@annotation(com.yssk.interfaces.biz.annotation.OptLog)")public void optLogAspect() {}@Around("optLogAspect()")public Object doAround(ProceedingJoinPoint joinPoint) {Object obj = null;try {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();//获取方法参数值Object[] args = joinPoint.getArgs();OptLog optLog = getTargetAnnotation(joinPoint);String request = optLog.request();Class<?> requestType = optLog.requestType();// 获取request请求内容Object requestKeyVal = getValBySpEl(request, methodSignature, args, requestType);if(Objects.nonNull(requestKeyVal)){Long id = handleOptRecordBefore(requestKeyVal);log.info("rizhi:{}", id);obj = joinPoint.proceed();handleOptRecordAfter(id, obj);}} catch (Throwable e) {log.warn("记录请求日志出现异常...", e);}return obj;}private Long handleOptRecordBefore(Object request){log.info("请求日志保存");String jsonStr = JSONObject.toJSONString(request);String requestUrl = "";if(ObjectUtils.isNotEmpty(request)){if(request instanceof RequestDTO){requestUrl = ((RequestDTO<?>) request).getRequestUrl();}}// 保存请求日志InLog inLog = new InLog();inLog.setRequest(jsonStr);inLog.setRequestUrl(requestUrl);inLog.setStatus(0);inLogRepository.save(inLog);return inLog.getId();}private void handleOptRecordAfter(Long id, Object response){log.info("请求日志修改");String jsonStr = JSONObject.toJSONString(response);int status = 0;if(ObjectUtils.isNotEmpty(response)){if(response instanceof ResponseDTO){if(((ResponseDTO<?>) response).getError_code() == 0){status = 1;}}}// 修改请求日志LambdaUpdateWrapper<InLog> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.set(InLog::getStatus, status);updateWrapper.eq(InLog::getId, id);updateWrapper.set(InLog::getResponse, jsonStr);inLogRepository.update(updateWrapper);}/*** 获取注解* @param point* @return*/public static OptLog getTargetAnnotation(JoinPoint point) {try {OptLog annotation = null;if (point.getSignature() instanceof MethodSignature) {Method method = ((MethodSignature) point.getSignature()).getMethod();if (method != null) {annotation = method.getAnnotation(OptLog.class);}}return annotation;} catch (Exception e) {log.warn("获取 {}.{} 的 @OptLog 注解失败", point.getSignature().getDeclaringTypeName(), point.getSignature().getName(), e);return null;}}/*** 解析spEL表达式*/private Object getValBySpEl(String spEl, MethodSignature methodSignature, Object[] args, Class<?> classType) {try {//获取方法形参名数组String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());if (paramNames != null && paramNames.length > 0) {Expression expression = spelExpressionParser.parseExpression(spEl);// spring的表达式上下文对象EvaluationContext context = new StandardEvaluationContext();// 给上下文赋值for (int i = 0; i < args.length; i++) {context.setVariable(paramNames[i], args[i]);context.setVariable("p" + i, args[i]);}return expression.getValue(context, classType);}} catch (Exception e) {log.warn("解析请求日志的el表达式出错", e);}return null;}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了aop的使用法。