使用spring aop 統(tǒng)一捕獲異常和寫日志的示例demo
之前給大家介紹過Spring AOP的基礎(chǔ)知識(shí),需要的朋友點(diǎn)擊了解下吧,這邊我將給您介紹用spring AOP 實(shí)現(xiàn)的異常捕獲和日志的小demo,我也會(huì)詳細(xì)解釋相關(guān)配置。
首先給大家看一下我的工程目錄:

大家可以先用eclipse中新建一個(gè)maven工程,在工程中pom.xml按下面文件添加依賴:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zy</groupId>
<artifactId>AOPException</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>AOPException Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.6.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.18.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>AOPException</finalName>
</build>
</project>
添加完依賴后,開始配置web.xml文件,如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>exception-test-web</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>//這邊是加載spring的配置文件
/WEB-INF/config/applicationContext.xml
</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>production</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
//這邊是加載spring的配置文件
<param-value>/WEB-INF/config/spring-mvc-config.xml</param-value>
</init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <session-config> <session-timeout>20</session-timeout> </session-config></web-app>
配置完web.xml后,你可開始配置spring配置文件了,也就是applicationContext.xml文件。如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"
default-lazy-init="true">
<description>Spring公共配置</description>
<!-- 使用annotation 自動(dòng)注冊(cè)bean, 并保證@Required、@Autowired的屬性被注入 -->
<context:component-scan base-package="com.zy.test">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />//不掃描controller注解類
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />//不掃描ControllerAdvice注解類
</context:component-scan>
</beans>
然后配置spring-mvc-config.xml文件,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd ">
<!-- 自動(dòng)掃描 -->
<context:component-scan base-package="com.zy.test" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />//掃描COntroller注解類
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />//掃描ControllerAdvice注解類
</context:component-scan>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" />
<property name="writeAcceptCharset" value="false" />
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="prettyPrint" value="true" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--
<bean class="com.zy.test.config.ExceptionConfig"/>
-->
<!-- 這里的配置可以通過 com.zy.test.config.ExceptionConfig這個(gè)注解類來完成 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean class="com.zy.test.aspect.WebExceptionAspect" scope="singleton"/> //配置了單例
</beans>
上面spring容器和spring-mvc容器中掃描的類不一樣,是為了區(qū)分兩個(gè)容器的職責(zé),spring-mvc負(fù)責(zé)controller控制器這塊的類。因?yàn)槲覀兊漠惓2东@是從controller類往外拋,所以我們對(duì)于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
*
*/
@Aspect
public class WebExceptionAspect {
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")//連接點(diǎn)是@RequestMapping注解的方法
private void webPointcut() {}
@AfterThrowing(pointcut = "webPointcut()", throwing = "e")//切點(diǎn)在webpointCut()
public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller類拋出的異常在這邊捕獲
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
//開始打log
System.out.println("異常:" + e.getMessage());
System.out.println("異常所在類:" + className);
System.out.println("異常所在方法:" + methodName);
System.out.println("異常中的參數(shù):");
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();
//在項(xiàng)目中最好記錄當(dāng)前操作的時(shí)間和用戶
System.out.println("操作所在類:" + className);
System.out.println("操作所在方法:" + methodName);
System.out.println("操作中的參數(shù):");
for (int i = 0; i < args.length; i++) {
System.out.println(args[i].toString());
}
}
@AfterReturning(value = "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中的值,一遍在日志時(shí)明確這個(gè)操作的名稱
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}) //注解可以用于參數(shù)或者方法上
@Retention(RetentionPolicy.RUNTIME) //保留至運(yùn)行時(shí)
@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 {
@Autowired
private ExceptionService service;
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8" )
@ResponseBody
@ArchivesLog(operationType = "測(cè)試", operationName = "測(cè)試異?;蛘邷y(cè)試返回")
public JSONObject test(@PathVariable Integer id) throws Exception {
JSONObject result = new JSONObject();
result.put("zhouyu", "asdasdasdasd");
// try {//去掉注釋可以測(cè)捕獲的異常,不去掉注釋可以測(cè)日志處理
// 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實(shí)現(xiàn)類:
package com.zy.test.service;
import org.springframework.stereotype.Service;
@Service
public class ExceptionService implements ExceptionServiceBase{
public void test() throws Exception {
boolean flag = true;
if(flag) {
throw new Exception("service 異常");
}
}
}
其中工程中的ExceptionConfig是一個(gè)配置類,用于掃描包的。但是如果你是用配置文件的化,這個(gè)文件就不用了,這邊就不說了。
github上可以拉到新代碼:代碼在這里
到此這篇關(guān)于spring aop 統(tǒng)一捕獲異常和寫日志的文章就介紹到這了,更多相關(guān)spring aop統(tǒng)一異常日志內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springBoot項(xiàng)目中的全局異常處理和自定義異常處理實(shí)現(xiàn)
異常是由于程序邏輯錯(cuò)誤、運(yùn)行環(huán)境問題、用戶輸入錯(cuò)誤等原因?qū)е碌囊环N非正常的狀態(tài)或事件,本文主要介紹了springBoot項(xiàng)目中的全局異常處理和自定義異常處理實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08
idea切換分支的時(shí)候,忽略一些無用的修改設(shè)置
這篇文章主要介紹了idea切換分支的時(shí)候,忽略一些無用的修改操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
實(shí)現(xiàn)一個(gè)簡(jiǎn)單Dubbo完整過程詳解
這篇文章主要為大家介紹了實(shí)現(xiàn)一個(gè)簡(jiǎn)單Dubbo完整過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Elasticsearch?計(jì)數(shù)分詞中的token使用實(shí)例
這篇文章主要為大家介紹了Elasticsearch?計(jì)數(shù)分詞中的token使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
解決SpringBoot中使用@Transactional注解遇到的問題
這篇文章主要介紹了SpringBoot中使用@Transactional注解遇到的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09

