SpringMVCAOP通过注解方式拦截Controller等实现日志管理
开始上代码:
注解定义
packagecom.jiankunking.common;
importjava.lang.annotation.;
/
@authorjiankunking
@Date:2016/8/15
@Time:11:09
@annotationOperationLogger
/
@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取
@Target(ElementType.METHOD)//目标是方法
@Documented//文档生成时,该注解将被包含在javadoc中,可去掉
public@interfaceOperationLogger
{
/
模块名字
/
StringmodelName()default"";
/
操作类型
/
Stringoption();
}
@interface是用来自定义注释类型的。
注释的声明用@符号后面跟上这个注释类型的名字,再后面跟上括号,括号中列出这个注释中元素/方法的key-value对。值必须是常量。
AOP拦截部分
packagecom.jiankunking.common;
importorg.apache.log4j.Logger;
importorg.aspectj.lang.JoinPoint;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.aspectj.lang.Signature;
importorg.aspectj.lang.annotation.;
importorg.aspectj.lang.reflect.MethodSignature;
importorg.springframework.stereotype.Component;
importjava.lang.reflect.Method;
/
@authorjiankunking
@Date:2016/8/15
@Time:11:11
@annotationSysLogAspect
/
@Aspect
@Component
publicclassSysLogAspect
{
privatestaticfinalLoggerlogger=Logger.getLogger(SysLogAspect.class);
/
定义Pointcut,Pointcut的名称,此方法不能有返回值,该方法只是一个标示
/
@Pointcut("@annotation(com.jiankunking.common.OperationLogger)")
publicvoidcontrollerAspect()
{
System.out.println("我是一个切入点");
}
/
前置通知(Beforeadvice):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。
@paramjoinPoint
/
@Before("controllerAspect()")
publicvoiddoBefore(JoinPointjoinPoint)
{
System.out.println("=====SysLogAspect前置通知开始=====");
//handleLog(joinPoint,null);
}
/
后通知(Afteradvice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
@paramjoinPoint
/
@AfterReturning(pointcut="controllerAspect()")
publicvoiddoAfter(JoinPointjoinPoint)
{
System.out.println("=====SysLogAspect后置通知开始=====");
//handleLog(joinPoint,null);
}
/
抛出异常后通知(Afterthrowingadvice):在方法抛出异常退出时执行的通知。
@paramjoinPoint
@parame
/
@AfterThrowing(value="controllerAspect()",throwing="e")
publicvoiddoAfter(JoinPointjoinPoint,Exceptione)
{
System.out.println("=====SysLogAspect异常通知开始=====");
//handleLog(joinPoint,e);
}
/
环绕通知(Aroundadvice):包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。
@paramjoinPoint
/
@Around("controllerAspect()")
publicObjectdoAround(ProceedingJoinPointjoinPoint)throwsThrowable
{
System.out.println("=====SysLogAspect环绕通知开始=====");
//handleLog(joinPoint,null);
Objectobj=joinPoint.proceed();
System.out.println("=====SysLogAspect环绕通知结束=====");
returnobj;
}
/
日志处理
@paramjoinPoint
@parame
/
privatevoidhandleLog(JoinPointjoinPoint,Exceptione)
{
try
{
//获得注解
OperationLoggerlogger=giveController(joinPoint);
if(logger==null)
{
return;
}
Stringsignature=joinPoint.getSignature().toString();//获取目标方法签名
StringmethodName=signature.substring(signature.lastIndexOf(".")+1,
signature.indexOf("("));
StringlongTemp=joinPoint.getStaticPart().toLongString();
StringclassType=joinPoint.getTarget().getClass().getName();
Class>clazz=Class.forName(classType);
Method[]methods=clazz.getDeclaredMethods();
System.out.println("methodName:"+methodName);
for(Methodmethod:methods)
{
if(method.isAnnotationPresent(OperationLogger.class)
&&method.getName().equals(methodName))
{
//OpLoggerlogger=method.getAnnotation(OpLogger.class);
StringclazzName=clazz.getName();
System.out.println("clazzName:"+clazzName+",methodName:"
+methodName);
}
}
}catch(Exceptionexp)
{
logger.error("异常信息:{}",exp);
exp.printStackTrace();
}
}
/
获得注解
@paramjoinPoint
@return
@throwsException
/
privatestaticOperationLoggergiveController(JoinPointjoinPoint)throwsException
{
Signaturesignature=joinPoint.getSignature();
MethodSignaturemethodSignature=(MethodSignature)signature;
Methodmethod=methodSignature.getMethod();
if(method!=null)
{
returnmethod.getAnnotation(OperationLogger.class);
}
returnnull;
}
}
Aspect通常用于将必要的但和业务无关的逻辑和业务逻辑分离。
Spring使用的AOP注解分为三个层次:
前提条件是在xml中放开了
@Aspect放在类头上,把这个类作为一个切面。
@Pointcut放在方法头上,定义一个可被别的方法引用的切入点表达式。
5种通知。
@Before,前置通知,放在方法头上。
@After,后置【finally】通知,放在方法头上。
@AfterReturning,后置【try】通知,放在方法头上,使用returning来引用方法返回值。
@AfterThrowing,后置【catch】通知,放在方法头上,使用throwing来引用抛出的异常。
@Around,环绕通知,放在方法头上,这个方法要决定真实的方法是否执行,而且必须有返回值。
在Maven中加入以下以依赖
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.mkyong.common
spring-mvc-log4j
war
1.0-SNAPSHOT
SpringMVC+Log4j
1.7
4.3.2.RELEASE
2.6.2
1.2
3.1.0
1.7.4
3.1
org.springframework
spring-webmvc
${spring.version}
org.springframework
spring-aop
${spring.version}
org.springframework
spring-aspects
${spring.version}
org.apache.logging.log4j
log4j-api
${log4j.version}
org.apache.logging.log4j
log4j-core
${log4j.version}
jstl
jstl
${jstl.version}
javax.servlet
javax.servlet-api
${servletapi.version}
provided
log4j
log4j
1.2.17
org.aspectj
aspectjrt
${org.aspectj-version}
javax.inject
javax.inject
1
cglib
cglib
${cglib.version}
org.apache.maven.plugins
maven-compiler-plugin
3.3
${jdk.version}
${jdk.version}
在spring-.xml中加入spring支持,打开aop功能
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd
">
/WEB-INF/pages/
.jsp
注解也写好了,spring也配置好了,在controller里面怎么用呢?
Controller应用
packagecom.jiankunking.controller;
importcom.jiankunking.common.OperationLogger;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value="/Welcome",produces="text/html;charset=UTF-8")
publicclassWelcomeController
{
@OperationLogger(modelName="WelcomeController",option="getWelcome")
@RequestMapping(value="/getWelcome",method=RequestMethod.POST)
publicvoidgetWelcome()
{
//异常拦截测试
//inti=9/0;
System.out.println("controller方法执行!");
}
}
如何测试呢?
从前端发起ajax请求controller,即可:
$.ajax({
type:"POST",
url:"/Welcome/getWelcome",
contentType:"application/json",
data:null,
success:function()
{
//alert("22");
},
error:function()
{
//alert("失败!");
}
});
效果如下:
|
|