Copyright © 2022-2024 aizws.net · 网站版本: v1.2.6·内部版本: v1.23.3·
页面加载耗时 0.00 毫秒·物理内存 61.0MB ·虚拟内存 1299.8MB
欢迎来到 AI 中文社区(简称 AI 中文社),这里是学习交流 AI 人工智能技术的中文社区。 为了更好的体验,本站推荐使用 Chrome 浏览器。
本文讲解"解决Springboot全局异常处理与AOP日志处理中@AfterThrowing失效问题的方法",希望能够解决相关问题。
同时使用上述两种方式,可能出现某一种失效的场景。
失效场景一: 如果采用前后端不分离架构,采用下属代码返回前端响应结果,如果统一异常处理执行顺序在@AfterThrowing之前,就会出现@AfterThrowing中不执行情况。前后端分离架构不会出现此问题。
String xRequestedWith = request.getHeader("x-requested-with"); if ("XMLHttpRequest".equals(xRequestedWith)) { response.setContentType("application/plain;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.write(CommunityUtil.getJSONString(1, "服务器异常!")); } else { response.sendRedirect(request.getContextPath() + "/error"); }
解决方案:让AOP日志处理类实现Ordered 接口,并重写getOrder()方法,使其返回值为1,返回值越小,执行的顺序越靠前,使其执行顺序优先于全部异常处理类。
@Component @Aspect public class LogAspectTest implements Ordered { @Override public int getOrder() { return 1; } @AfterThrowing(value = "pointcut()",throwing = "e") public void afterThrowing(JoinPoint joinPoint,Exception e){ String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); System.out.println("className is : " + className + ". methodName is : " + methodName); System.out.println("afterThrowing excute········" + e.getMessage()); e.printStackTrace(); } }
失效场景二:如果使用了 @Around(“”),在执行 joinPoint.proceed()方法时,捕获了异常,会导致全局异常处理无法收到异常,因此失效。
@Around("pointcut()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); System.out.println("className is : " + className + ". methodName is : " + methodName); System.out.println("around excute before ········"); Object obj = null; try { obj = joinPoint.proceed(); } catch (Throwable e) { System.out.println("我捕获了异常"); } System.out.println("obj 对象: " + obj); System.out.println("around excute after ········"); }
解决方案:不要进行异常捕获,或者捕获后重新抛出异常。
@Around("pointcut()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); System.out.println("className is : " + className + ". methodName is : " + methodName); System.out.println("around excute before ········"); Object obj = null; try { obj = joinPoint.proceed(); } catch (Throwable e) { System.out.println("我捕获了异常"); throw new RuntimeException("执行失败",e); } System.out.println("obj 对象: " + obj); System.out.println("around excute after ········"); }
4、测试全部代码
package com.nowcoder.community.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; /** * @Description aop 日志记录 */ @Component @Aspect public class LogAspectTest implements Ordered { /** * 定义执行顺序的优先级,值越小,优先级越高 * @return */ @Override public int getOrder() { return 1; } /** * 定义切点(织入点) * execution(* com.nowcoder.community.controller.*.*(..)) * - 第一个 * 表示 支持任意类型返回值的方法 * - com.nowcoder.community.controller 表示这个包下的类 * - 第二个 * 表示 controller包下的任意类 * - 第三个 * 表示 类中的任意方法 * - (..) 表示方法可以拥有任意参数 * 可以根据自己的需求替换。 * */ @Pointcut("execution(* com.nowcoder.community.controller.*.*(..))") public void pointcut(){ } /** * 定义 advice 通知 * - 1. @Before 目标方法执行之前 * - 2. @After 目标方法执行之后 * - 3. @AfterReturning 目标方法返回执行结果之后 * - 4. @AfterThrowing 目标方法抛出异常后 * - 5. @Around 可以使用ProceedingJoinPoint joinPoint,获取目标对象,通过动态代理,代理目标类执行,在目标对象执行前后均可 */ @Before("pointcut()") public void before(JoinPoint joinPoint){ String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if (attributes == null){ return; } // 请求ip String ip = attributes.getRequest().getRemoteHost(); // 请求路径 String requestURI = attributes.getRequest().getRequestURI(); // 请求方法 String requestMethod = attributes.getRequest().getMethod(); System.out.println(String.format("用户: [%s] 的请求路径为:[%s], 请求方式为: [%s],请求类名为: [%s], 请求方法名为: [%s]", ip,requestURI, requestMethod,className,methodName)); System.out.println("before excute········"); } @After("pointcut()") public void after(JoinPoint joinPoint){ String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if (attributes == null){ return; } // 请求ip String ip = attributes.getRequest().getRemoteHost(); // 请求路径 String requestURI = attributes.getRequest().getRequestURI(); // 请求方法 String requestMethod = attributes.getRequest().getMethod(); System.out.println(String.format("用户: [%s] 的请求路径为:[%s], 请求方式为: [%s],请求类名为: [%s], 请求方法名为: [%s]", ip,requestURI, requestMethod,className,methodName)); System.out.println("after excute········"); } @AfterReturning("pointcut()") public void afterReturning(JoinPoint joinPoint){ String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if (attributes == null){ return; } // 请求ip String ip = attributes.getRequest().getRemoteHost(); // 请求路径 String requestURI = attributes.getRequest().getRequestURI(); // 请求方法 String requestMethod = attributes.getRequest().getMethod(); System.out.println(String.format("用户: [%s] 的请求路径为:[%s], 请求方式为: [%s],请求类名为: [%s], 请求方法名为: [%s]", ip,requestURI, requestMethod,className,methodName)); System.out.println("afterReturning excute········"); } @AfterThrowing(value = "pointcut()",throwing = "e") public void afterThrowing(JoinPoint joinPoint,Exception e){ String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if (attributes == null){ return; } // 请求ip String ip = attributes.getRequest().getRemoteHost(); // 请求路径 String requestURI = attributes.getRequest().getRequestURI(); // 请求方法 String requestMethod = attributes.getRequest().getMethod(); System.out.println(String.format("用户: [%s] 的请求路径为:[%s], 请求方式为: [%s],请求类名为: [%s], 请求方法名为: [%s],请求失败原因: [%s]", ip, requestURI, requestMethod,className,methodName,e.getMessage()+e.getCause())); System.out.println("afterThrowing excute········" + e.getMessage()); e.printStackTrace(); } @Around("pointcut()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); System.out.println("className is : " + className + ". methodName is : " + methodName); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if (attributes == null){ return; } // 请求ip String ip = attributes.getRequest().getRemoteHost(); // 请求路径 String requestURI = attributes.getRequest().getRequestURI(); // 请求方法 String requestMethod = attributes.getRequest().getMethod(); System.out.println(String.format("用户: [%s] 的请求路径为:[%s], 请求方式为: [%s],请求类名为: [%s], 请求方法名为: [%s]", ip,requestURI, requestMethod,className,methodName)); Object obj = null; try { obj = joinPoint.proceed(); } catch (Throwable e) { System.out.println("我捕获了异常"); throw new RuntimeException("执行失败",e); } System.out.println(String.format("用户: [%s] 的请求路径为:[%s], 请求方式为: [%s],请求类名为: [%s], 请求方法名为: [%s]", ip,requestURI, requestMethod,className,methodName)); System.out.println("around excute after ········"); } }
关于 "解决Springboot全局异常处理与AOP日志处理中@AfterThrowing失效问题的方法" 就介绍到此。希望多多支持编程教程。
Java使用HttpUtils怎么实现发送HTTP请求:本文讲解"Java使用HttpUtils如何实现发送HTTP请求",希望能够解决相关问题。 目录第一部分:简单总结HTTP请求常用配置第二部分:使用JavaLib的H ...