如何在Java Spring Boot中审计方法



我正在编写一个Spring Boot应用程序。我想审计方法与我的注释@AuditMetod:例如,我有方法foo()注释:

@AuditMetod(name = "SomeValue")
foo() {...}

我想这样处理和审计这样的方法(最简单的例子):

auditMethod(Method method) {
if (method.hasAnnotation(AuditMethod.class)) {
System.out.println (method.getName() + " was called at " + new Date())
}
}

乌利希期刊指南

感谢@Karthikeyan @Swapnil Khante和@misha2048,我明白了,我需要使用AOP。但我有两个问题:
  1. Aspect类中唯一没有被调用的方法,我没有看到铭文&;---------- Aspect method IS called -----------&;在日志
  2. 我如何在aspect方法中检查它拦截了什么方法。获取Method类的实例。

现在我有以下代码:控制器:

@PostMapping
@LoggingRest(executor = "USER", method = "CREATE", model = "SUBSCRIPTION")
public ResponseEntity<?> create(@Valid @RequestBody SubscriptionRequestDto dto) {
...
}

方面:

`@Aspect
@Slf4j
@Component
public class AuditAspect {
@Pointcut(value = "@annotation(com.aspect.annotations.LoggingRest)")
public void auditMethod(ProceedingJoinPoint proceedingJoinPoint) {
log.info("----------ASPECT METHOD IS CALLED------------");
}`

和注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoggingRest {
String executor() default "SYSTEM";
String method() default "";
String model() default "";
}

审计是cross-cutting关注的问题,可以使用AOP处理。

另一个解决方案是使用低级解决方案,通过编写自定义注释并使用Spring interceptor来编写业务逻辑。

要使用Spring interceptor,您需要实现HandlerInterceptorinterface

注释

示例
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Audit {
boolean active() default true;
}

拦截器的例子

@Component
public class AuditInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Audit annotation = handlerMethod.getMethodAnnotation(Audit.class);
if (annotation != null && annotation.active()) {
// your business logic
}
}
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}

查看这个拦截器示例

我认为这里的解决方案之一,正如@Karthikeyan提到的,是使用Spring AOP。

如果你不知道一个简短的介绍- spring-aop模块实现面向方面的编程范式。我们提取了一些常见的功能,我们通常希望将其应用于函数/方法的某个子集,到一个名为Aspect的实体(参见带@Aspect注释的类)。这个类将包含我们的横切功能——比如审计,比如我们想要审计方法的执行时间。我们只是放置了要执行的代码,条件,它告诉spring这个方面应该影响哪些确切的bean方法,见下文。

例如,如果我可以用以下非常简单的例子来审计方法的执行时间(在我的例子中,我说任何public方法,在com.example.stackoverflow.BusinessLogicClass类中返回void必须由这个方面检查):

@SpringBootApplication
@EnableAspectJAutoProxy
public class StackoverflowApplication implements ApplicationRunner {
@Autowired
private BusinessLogicClass businessLogicClass;
public static void main(String[] args) {
SpringApplication.run(StackoverflowApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
businessLogicClass.test();
}
}
@Aspect
@Component
class MyAspectLogicClass {
@Around("execution(public void com.example.stackoverflow.BusinessLogicClass.*(..))")
public Object hangAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long before = System.currentTimeMillis();
Object returnedValue = proceedingJoinPoint.proceed();
long after = System.currentTimeMillis();
System.out.printf("Retruned in '%s' ms %n", (after - before));
return returnedValue;
}
}
@Component
class BusinessLogicClass {
public void test() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

在我的例子中,我将获得方法执行前的时间,然后通过proceedingJoinPoint.proceed ()我将执行委托给真正的方法,然后,一旦我得到响应,我将获得当前系统时间并计算执行时间,相当简单。

我希望我至少给你指明了方向,如果你正在寻找文档,这是我建议你应该寻找的资源:

  • https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html官方春季文档(有点陈旧,但有一些有价值的东西值得学习)
  • https://docs.spring.io/spring-framework/docs/4.3.15.RELEASE/spring-framework-reference/html/aop.html更新鲜doc

希望有帮助:)

问题出在右标注上。在Aspect类中,我尝试了@Around,一切都按照我的需要工作。

@Aspect
@Slf4j
@Component
public class AuditAspect {
@Around(value = "@annotation(com.aspect.annotations.LoggingRest)")
public void auditMethod(ProceedingJoinPoint proceedingJoinPoint) {
var method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
log.info("----------ASPECT METHOD IS CALLED------------");
}
}

获取一个Method实例,我使用以下代码

Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();

相关内容

  • 没有找到相关文章

最新更新