How to get method execution flow in spring mvc interceptor(如何在Spring MVC拦截器中获取方法执行流程)
问题描述
我想在Spring MVC项目中获得完整的执行流程以及它们的执行时间。
public class MetricsInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod) handler;
Method method = hm.getMethod();
if (method.getDeclaringClass().isAnnotationPresent(Controller.class)) {
if (method.isAnnotationPresent(Metrics.class)) {
// System.out.println(method.getAnnotation(Metrics.class).value());
System.out.println(method.getName());
}
}
}
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
我使用@Metrics注释获取控制器类和方法,以记录几个方法的度量。我想要的是获得每个方法所花费的时间的整个方法执行流程(控制器-->服务-->DAO)。有没有办法在postHandle()或AfterCompletion()中获取该信息。请提出建议。
推荐答案
使用Spring AOPAround
建议可以实现这一点。
编写将截获的pointcut
- 包及其子包中公共方法的所有执行
- 属于 的包及其子包
- 控制器层
- 服务层(可选仅限于特定服务)
- DAO层
然后写下周围的建议,如下
@Component
@Aspect
public class TraceAdvice {
@Around("execution(* com.test..*(..)) &&" + " (within(com.test.controller..*) || "
+ "(within(com.test.service..*) && this(com.test.service.TestService)) || " + "within(com.test.dao..*))")
public Object traceCall(ProceedingJoinPoint pjp) throws Throwable {
/* This will hold our execution details in reverse order
* i.e. last method invoked would appear first.
* Key = Full qualified name of method
* Value = Execution time in ms
*/
Map<String, Long> trace = null;
Signature sig = pjp.getSignature();
// Get hold of current request
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// check if we are in controller (I used RestController modify it if Controller is required instead)
boolean isController = sig.getDeclaringType().isAnnotationPresent(RestController.class);
if (isController) {
// set the request attributte if we are in controller
trace = new LinkedHashMap<>();
req.setAttribute("trace", trace);
} else {
// if its not controller then read from request atributte
trace = (Map<String, Long>) req.getAttribute("trace");
}
Object result = null;
StopWatch watch = new StopWatch();
try {
// start the timer and invoke the advised method
watch.start();
result = pjp.proceed();
} finally {
// stop the timer
watch.stop();
String methodName = sig.getDeclaringTypeName() + "." + sig.getName();
// make entry for the method name with time taken
trace.put(methodName, watch.getTotalTimeMillis());
if (isController) {
// since controller method is exit point print the execution trace
trace.entrySet().forEach(entry -> {
System.out.println("Method " + entry.getKey() + " took " + String.valueOf(entry.getValue()));
});
}
}
return result;
}
}
在进行必要的配置后,示例输出应如下所示
com.est.dao.TestDAO.getTest方法花费350
方法com.est.service.TestService.getTest采用1954年
方法com.est.Controller.TestController.getTest采用3751
或者,可以编写三个切入点和各自的Around
建议,每个拦截特定的包,以消除检查控制器的if-else
部分
我已使用
测试了设置Spring 4.3.2 Release
AspectJ 1.7.4
JDK 1.8
Tomcat 8.0
如果有任何问题,请在备注中告知。
这篇关于如何在Spring MVC拦截器中获取方法执行流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在Spring MVC拦截器中获取方法执行流程
基础教程推荐
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- 降序排序:Java Map 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01