Spring MVC AOP通过自定义注解方式拦截Controller等实现日志管理

网友投稿 944 2022-09-07

Spring MVC AOP通过自定义注解方式拦截Controller等实现日志管理

Spring MVC AOP通过自定义注解方式拦截Controller等实现日志管理

之前一直写-,没玩过spring,一直没用过aop(面向切面编程)这类功能,当然不是说-里面没有这类框架,企业库就可以​​微软企业库官网​​

开始上代码:

注解定义

package com.jiankunking.common;import java.lang.annotation.*;/** * @author jiankunking * @Date: 2016/8/15 * @Time: 11:09 * @annotation@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取@Target(ElementType.METHOD)//目标是方法@Documented//文档生成时,该注解将被包含在javadoc中,可去掉public @interface OperationLogger /** * 模块名字 */ String modelName() default ""; /** * 操作类型 */

AOP拦截部分

package com.jiankunking.common;import org.apache.log4j.Logger;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.annotation.*;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component;import java.lang.reflect.Method;/** * @author jiankunking * @Date: 2016/8/15 * @Time: 11:11 * @annotation@Aspect@Componentpublic class SysLogAspect private static final Logger logger = Logger.getLogger(SysLogAspect.class); /** * 定义Pointcut,Pointcut的名称,此方法不能有返回值,该方法只是一个标示 */ @Pointcut("@annotation(com.jiankunking.common.OperationLogger)") public void controllerAspect() { System.out.println("我是一个切入点"); } /** * 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。 * @param @Before("controllerAspect()") public void doBefore(JoinPoint joinPoint) { System.out.println("=====SysLogAspect前置通知开始====="); //handleLog(joinPoint, null); } /** * 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 * @param @AfterReturning(pointcut = "controllerAspect()") public void doAfter(JoinPoint joinPoint) { System.out.println("=====SysLogAspect后置通知开始====="); //handleLog(joinPoint, null); } /** * 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。 * @param joinPoint * @param @AfterThrowing(value = "controllerAspect()", throwing = "e") public void doAfter(JoinPoint joinPoint, Exception e) { System.out.println("=====SysLogAspect异常通知开始====="); //handleLog(joinPoint, e); } /** * 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。 * @param @Around("controllerAspect()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("=====SysLogAspect 环绕通知开始====="); //handleLog(joinPoint, null); Object obj= joinPoint.proceed(); System.out.println("=====SysLogAspect 环绕通知结束====="); return obj; } /** * 日志处理 * * @param joinPoint * @param private void handleLog(JoinPoint joinPoint, Exception e) { try { //获得注解 OperationLogger logger = giveController(joinPoint); if (logger == null) { return; } String signature = joinPoint.getSignature().toString(); // 获取目标方法签名 String methodName = signature.substring(signature.lastIndexOf(".") + 1, signature.indexOf("(")); String longTemp = joinPoint.getStaticPart().toLongString(); String classType = joinPoint.getTarget().getClass().getName(); Class clazz = Class.forName(classType); Method[] methods = clazz.getDeclaredMethods(); System.out.println("methodName: " + methodName); for (Method method : methods) { if (method.isAnnotationPresent(OperationLogger.class) && method.getName().equals(methodName)) { //OpLogger logger = method.getAnnotation(OpLogger.class); String clazzName = clazz.getName(); System.out.println("clazzName: " + clazzName + ", methodName: " + methodName); } } } catch (Exception exp) { logger.error("异常信息:{}", exp); exp.printStackTrace(); } } /** * 获得注解 * @param joinPoint * @return * @throws private static OperationLogger giveController(JoinPoint joinPoint) throws Exception { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method != null) { return method.getAnnotation(OperationLogger.class); } return null; }}

Aspect通常用于将必要的但和业务无关的逻辑和业务逻辑分离。

Spring使用的AOP注解分为三个层次: 前提条件是在xml中放开了

@Aspect放在类头上,把这个类作为一个切面。@Pointcut放在方法头上,定义一个可被别的方法引用的切入点表达式。5种通知。

@Before,前置通知,放在方法头上。@After,后置【finally】通知,放在方法头上。@AfterReturning,后置【try】通知,放在方法头上,使用returning来引用方法返回值。@AfterThrowing,后置【catch】通知,放在方法头上,使用throwing来引用抛出的异常。@Around,环绕通知,放在方法头上,这个方法要决定真实的方法是否执行,而且必须有返回值。

在Maven中加入以下以依赖

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功能

/WEB-INF/pages/ .jsp

注解也写好了,spring也配置好了,在controller里面怎么用呢?

Controller应用

package com.jiankunking.controller;import com.jiankunking.common.OperationLogger;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controller@RequestMapping(value = "/Welcome", produces = "text/html;charset=UTF-8")public class WelcomeController{ @OperationLogger(modelName = "WelcomeController", option = "getWelcome") @RequestMapping(value = "/getWelcome", method = RequestMethod.POST) public void getWelcome() { //异常拦截测试 //int i = 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("失败!");

效果如下:

由于这里是通过Spring的@Aspect注解实现的AOP,所以同一个类中的某个方法A(该方法没有注解标识)调用另一个有注解标识的方法B时,方法B上的注解是不会起作用的。

xml方式实现aop拦截及aop基础知识参考: ​​​xml实现aop拦截​​

Spring Boot 自定义注解方式拦截Controller等实现日志管理: ​​​Spring Boot 自定义注解​​

作者:jiankunking​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:四个经典的SQL编程问题
下一篇:Error:Maven Resources Compiler: Failed to copy 'XXX' to 'YYY': YYY (拒绝访问。)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~