在Spring框架中,我们经常需要对控制器方法进行日志记录,以便更好地监控应用的运行情况。在本文中,我们将介绍如何使用AOP(Aspect-Oriented Programming)来实现对控制器方法的拦截, 以及如何让你的应用变得更加透明。
使用AOP来拦截controller方法
首先,让我们看一下一个简单的例子。我们将创建一个切面类`WebLogAspect`,用于拦截所有的控制器方法。
@Aspect
@Component
public class WebLogAspect {
//
@Pointcut("@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController)")
public void cutController() {}
//
@Before("cutController()")
public void doBefore(JoinPoint point) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String url = request.getRequestURL().toString();
List<Object> list = Lists.newArrayList();
for (Object object : point.getArgs()) {
if (object instanceof MultipartFile || object instanceof HttpServletRequest || object instanceof HttpServletResponse || object instanceof BindingResult) {
continue;
}
list.add(object);
}
log.info("请求 uri:[{}],params:[{}]", url, StringUtils.join(list, ","));
}
//
@AfterReturning(returning = "response", pointcut = "cutController()")
public void doAfterReturning(Object response) {
if (response != null) {
log.info("请求返回result:[{}]", JSONUtil.toJsonStr(response));
}
}
}
在上述代码中,我们使用了 `@Aspect` 和 `@Component` 注解来标记我们的切面类。我们定义了一个切入点 `cutController()`,用于匹配所有的控制器方法。
应用案例
让我们通过一个实际的例子来演示这个切面的应用。
假设我们有一个控制器类,包含两个方法:
@RestController
public class ExampleController {
@GetMapping("/example")
public String example() {
//
return "Hello, World!";
}
@PostMapping("/example")
public String example(String param) {
//
return "Hello, " + param + "! ";
}
}
当我们访问 `/example` 页面时,切面会捕捉到请求参数,并记录日志信息。
INFO [http-nio-8080-exec-1] WebLogAspect - 请求 uri:[http://localhost:8080/example],params:[]
当我们访问 `/example` 页面并传递 `param` 参数时,切面会捕捉到参数,并记录日志信息。
INFO [http-nio-8080-exec-1] WebLogAspect - 请求 uri:[http://localhost:8080/example],params:[param=hello]
当我们访问 `/example` 页面并传递 `param` 参数后,切面会捕捉到返回值,并记录日志信息。
INFO [http-nio-8080-exec-1] WebLogAspect - 请求返回result:[Hello, hello! ]
通过这个例子,我们可以看出如何使用AOP来实现对控制器方法的拦截, 以及如何让你的应用变得更加透明。