使用spring|使用spring aop 统一捕获异常和写日志的示例demo

之前给大家介绍过Spring AOP的基础知识,需要的朋友点击了解下吧,这边我将给您介绍用spring AOP 实现的异常捕获和日志的小demo,我也会详细解释相关配置。
首先给大家看一下我的工程目录:
使用spring|使用spring aop 统一捕获异常和写日志的示例demo
文章图片

【使用spring|使用spring aop 统一捕获异常和写日志的示例demo】大家可以先用eclipse中新建一个maven工程,在工程中pom.xml按下面文件添加依赖:

4.0.0com.zyAOPExceptionwar0.0.1-SNAPSHOTAOPException Maven Webapphttp://maven.apache.orgaspectjaspectjrt1.5.2org.springframeworkspring-web5.0.6.RELEASEorg.springframeworkspring-aop5.0.4.RELEASEorg.springframeworkspring-context5.0.5.RELEASEorg.springframeworkspring-core5.0.6.RELEASE org.springframeworkspring-webmvc5.0.6.RELEASE org.aspectjaspectjweaver1.8.13 com.fasterxml.jackson.corejackson-annotations2.9.5 com.fasterxml.jackson.corejackson-core2.9.5 com.fasterxml.jackson.corejackson-databind2.9.5 com.alibabafastjson1.2.47org.springframeworkspring-test5.0.6.RELEASEtest org.mockitomockito-core2.18.3test AOPException

添加完依赖后,开始配置web.xml文件,如下:
exception-test-webcontextConfigLocation//这边是加载spring的配置文件/WEB-INF/config/applicationContext.xmlspring.profiles.defaultproductionencodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingUTF-8forceEncodingtrueencodingFilter/*org.springframework.web.context.ContextLoaderListenerspringServletorg.springframework.web.servlet.DispatcherServletcontextConfigLocation//这边是加载spring的配置文件/WEB-INF/config/spring-mvc-config.xml 1springServlet /20

配置完web.xml后,你可开始配置spring配置文件了,也就是applicationContext.xml文件。如下:
Spring公共配置//不扫描controller注解类//不扫描ControllerAdvice注解类

然后配置spring-mvc-config.xml文件,如下:
//扫描COntroller注解类//扫描ControllerAdvice注解类 //配置了单例

上面spring容器和spring-mvc容器中扫描的类不一样,是为了区分两个容器的职责,spring-mvc负责controller控制器这块的类。因为我们的异常捕获是从controller类往外抛,所以我们对于aspect类也放在spring-mvc容器中。
下面就开始介绍我们的切面类:
package com.zy.test.aspect; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import com.zy.test.annotation.ArchivesLog; /** * web 异常切面 * @author user**/@Aspectpublic class WebExceptionAspect {@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")//连接点是@RequestMapping注解的方法private void webPointcut() {}@AfterThrowing(pointcut = "webPointcut()", throwing = "e")//切点在webpointCut()public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller类抛出的异常在这边捕获String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); //开始打logSystem.out.println("异常:" + e.getMessage()); System.out.println("异常所在类:" + className); System.out.println("异常所在方法:" + methodName); System.out.println("异常中的参数:"); System.out.println(methodName); for (int i = 0; i < args.length; i++) {System.out.println(args[i].toString()); }}@Before("execution(* com.zy.test.controller.*.*(..))")public void beforeProcess(JoinPoint joinPoint) {String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); //在项目中最好记录当前操作的时间和用户System.out.println("操作所在类:" + className); System.out.println("操作所在方法:" + methodName); System.out.println("操作中的参数:"); for (int i = 0; i < args.length; i++) {System.out.println(args[i].toString()); }}@AfterReturning(value = "https://www.it610.com/article/execution(* com.zy.test.controller.*.*(..)))", returning = "returnVal")public void returnProcess(JoinPoint joinPoint, Object returnVal) {String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); Class targetClass = null; String operationName = ""; try {targetClass = Class.forName(className); } catch (ClassNotFoundException e) {e.printStackTrace(); }Method[] methods = targetClass.getMethods(); for (Method method : methods) {if (method.getName().equals(methodName)) {Class[] clazzs = method.getParameterTypes(); if (clazzs != null && clazzs.length == args.length&&method.getAnnotation(ArchivesLog.class)!=null) {//这块是取出我们注解ArchiveLog中的值,一遍在日志时明确这个操作的名称operationName = method.getAnnotation(ArchivesLog.class).operationName(); break; }}}System.out.println("操作名称:" + operationName); System.out.println("方法正常返回的值:" + returnVal); }}

这边我们需要自定义注解:
package com.zy.test.annotation; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; @Target({ElementType.PARAMETER, ElementType.METHOD})//注解可以用于参数或者方法上@Retention(RetentionPolicy.RUNTIME)//保留至运行时@Documented//被javadoc所记录public @interface ArchivesLog {/*** 操作类型@return*/public String operationType() default ""; /*** 操作名称@return*/public String operationName() default ""; }

然后定义我们的controller类:
package com.zy.test.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONObject; import com.zy.test.annotation.ArchivesLog; import com.zy.test.service.ExceptionService; @Controller@RequestMapping("/exception")public class ExceptionController {@Autowiredprivate ExceptionService service; @RequestMapping(value = "https://www.it610.com/test/{id}", method = RequestMethod.GET, produces = "application/json; charset=UTF-8" )@ResponseBody@ArchivesLog(operationType = "测试", operationName = "测试异常或者测试返回")public JSONObject test(@PathVariable Integer id) throws Exception {JSONObject result = new JSONObject(); result.put("zhouyu", "asdasdasdasd"); //try {//去掉注释可以测捕获的异常,不去掉注释可以测日志处理//service.test(); //} catch (Exception ex) {//throw new Exception("controller 层 异常"); //}return result; }}

service接口:
package com.zy.test.service; public interface ExceptionServiceBase {void test() throws Exception; }

service实现类:
package com.zy.test.service; import org.springframework.stereotype.Service; @Servicepublic class ExceptionService implements ExceptionServiceBase{public void test() throws Exception {boolean flag = true; if(flag) {throw new Exception("service 异常"); }}}

其中工程中的ExceptionConfig是一个配置类,用于扫描包的。但是如果你是用配置文件的化,这个文件就不用了,这边就不说了。
github上可以拉到新代码:代码在这里
到此这篇关于spring aop 统一捕获异常和写日志的文章就介绍到这了,更多相关spring aop统一异常日志内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读