自定义注解 + AOP
自定义注解 + AOP
在实际运用中,当有一些公共的业务方法需要在多个不同方法执行前或执行后运行。
可以通过自定义注解与AOP结合使用。
在多个方法中仅添加注解即可。
通过AOP可以选择方法执行前后,或者是环绕等方式来执行公共方法。
注解实现
注解默认放在项目的 annotation 下(没有可创建,约定成俗)
package com.ruoyi.test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 测试注解
* @Retention(RetentionPolicy.RUNTIME) 运行时级别
* @Target(ElementType.METHOD) 方法注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTestAnnotation {
}
切面实现
切面默认放在项目的 aspect下,类名结尾为Aspect(没有可创建,约定成俗)
本次实现使用环绕通知举例
package com.ruoyi.test.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* 切面实现
* @Aspect 切面注解
* @Component 将本切面类交给Spring进行管理
*/
@Aspect
@Component
public class MyTestAspect {
/**
* @Pointcut 定义切入点
* value 将切入点指定为MyTestAnnotation注解
*/
@Pointcut(value = "@annotation(com.ruoyi.test.annotation.MyTestAnnotation)")
private void pointCut() {
}
/**
* 切面方法
* @param joinPoint 连接点
* @return 被拦截方法的执行结果
*/
@Around(value = "pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("切面方法执行之前");
// 执行切面连接点方法
Object object = joinPoint.proceed();
System.out.println("切面方法执行之后");
return object;
}
}
业务方法(注解使用)
@Override
@MyTestAnnotation
public void testAnnotationMethod(TestDemo testDemo) {
System.out.println("执行业务方法");
}
切面类获取方法参数
@Around(value = "pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("切面方法执行之前");
//--------------------------------------------------------------
// 获取方法签名
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
// 获取方法参数名称
String[] paramNames = methodSignature.getParameterNames();
// 获取方法实际传入的参数值
Object[] arguments = joinPoint.getArgs();
// 输出参数
if (arguments != null && paramNames != null) {
for (int i = 0; i < paramNames.length; i++) {
System.out.println("参数名:" + paramNames[i] + ",参数值:" + arguments[i]);
}
}
//--------------------------------------------------------------
// 执行切面连接点方法
Object object = joinPoint.proceed();
System.out.println("切面方法执行之后");
return object;
}
切面类获取请求头数据
这里以获取请求头中的token举例
@Around(value = "pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("切面方法执行之前");
//--------------------------------------------------------------
// 获取当前请求的上下文属性,并强制转换为Servlet请求属性
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)
Objects.requireNonNull(RequestContextHolder.getRequestAttributes());
// 从Servlet请求属性中获取当前的HTTP请求
HttpServletRequest request = servletRequestAttributes.getRequest();
// 从HTTP请求头中获取名为"token"的值
String token = request.getHeader("token");
//--------------------------------------------------------------
// 执行切面连接点方法
Object object = joinPoint.proceed();
System.out.println("切面方法执行之后");
return object;
}
切面类返回信息
有时候可能需要在切面类中返回特殊的信息,可以通过HttpServletResponse进行处理
这里以返回错误信息进行举例
注意:out.close(); 执行后,请求就会获得到返回值,但是后端代码没有抛出异常,所以后续代码任会执行。
@Around(value = "pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("切面方法执行之前");
// 执行切面连接点方法
Object object = joinPoint.proceed();
//--------------------------------------------------------------
// 获取当前请求的上下文属性,并强制转换为Servlet请求属性
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)
Objects.requireNonNull(RequestContextHolder.getRequestAttributes());
// 从Servlet请求属性中获取当前的HTTP响应
HttpServletResponse response = servletRequestAttributes.getResponse();
// 通过reponse输出信息
render(response, R.fail("环绕后方法执行发生错误"));
System.out.println("切面方法执行之后");
return object;
}
/**
* 将对象转为JSON字符串,写入响应体中,最后刷新并关闭输出流
* @param response HTTP响应对象
* @param codeMsg 返回类
*/
private void render(HttpServletResponse response, Object codeMsg) throws Exception {
// 设置响应的内容类型为JSON,指定字符集为UTF-8
response.setContentType("application/json;charset=UTF-8");
// 获取响应的输出流
OutputStream out = response.getOutputStream();
// 创建ObjectMapper对象,用于对象到JSON字符串的转换
ObjectMapper objectMapper = new ObjectMapper();
// 将codeMsg对象转换为JSON字符串
String result = objectMapper.writeValueAsString(codeMsg);
// 将JSON字符串写入输出流,指定字符集为UTF-8
out.write(result.getBytes(StandardCharsets.UTF_8));
// 刷新输出流
out.flush();
// 关闭输出流
out.close();
}
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 七十七
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果