spring AOP自定义注解方式实现日志管理

转:spring AOP自定义注解方式实现日志管理

今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理。废话不多说,直接开始!!!

关于配置我还是的再说一遍。

 

在applicationContext-mvc.xml中要添加的

     <mvc:annotation-driven />
     <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->
     <context:component-scan base-package="com.gcx" />

  

     <!-- 启动对@AspectJ注解的支持 -->
     <!-- proxy-target-class等于true是强制使用cglib代理,proxy-target-class默认是false,如果你的类实现了接口 就走JDK代理,如果没有,走cglib代理  -->
     <!-- 注:对于单利模式建议使用cglib代理,虽然JDK动态代理比cglib代理速度快,但性能不如cglib -->

     <!--如果不写proxy-target-class="true"这句话也没问题-->
     <aop:aspectj-autoproxy proxy-target-class="true"/>

     <!--切面-->
     <bean id="systemLogAspect" class="com.gcx.annotation.SystemLogAspect"></bean>

接下来开始编写代码。

     创建日志类实体

View Code

     编写dao接口

View Code

    编写service层

View Code

   编写service实现类serviceImpl

View Code

到这里基本程序编写完毕

下面开始自定义注解

复制代码
 1 package com.gcx.annotation;
 2 
 3 import java.lang.annotation.*;  4  5 @Target({ElementType.PARAMETER, ElementType.METHOD})  6 @Retention(RetentionPolicy.RUNTIME)  7 @Documented  8 public @interface Log {  9 10 /** 要执行的操作类型比如:add操作 **/ 11 public String operationType() default ""; 12 13 /** 要执行的具体操作比如:添加用户 **/ 14 public String operationName() default ""; 15 }
复制代码

 

下面编写切面

复制代码
  1 package com.gcx.annotation;
  2 
  3 import java.lang.reflect.Method;  4 import java.util.Date;  5 import java.util.UUID;  6  7 import javax.annotation.Resource;  8 import javax.servlet.http.HttpServletRequest;  9 import javax.servlet.http.HttpSession;  10  11 import org.aspectj.lang.JoinPoint;  12 import org.aspectj.lang.ProceedingJoinPoint;  13 import org.aspectj.lang.annotation.After;  14 import org.aspectj.lang.annotation.AfterReturning;  15 import org.aspectj.lang.annotation.AfterThrowing;  16 import org.aspectj.lang.annotation.Around;  17 import org.aspectj.lang.annotation.Aspect;  18 import org.aspectj.lang.annotation.Before;  19 import org.aspectj.lang.annotation.Pointcut;  20 import org.slf4j.Logger;  21 import org.slf4j.LoggerFactory;  22 import org.springframework.stereotype.Component;  23  24 import com.gcx.entity.SystemLog;  25 import com.gcx.entity.User;  26 import com.gcx.service.SystemLogService;  27 import com.gcx.util.JsonUtil;  28  29 /**  30  * @author 杨建  31  * @E-mail: email  32  * @version 创建时间:2015-10-19 下午4:29:05  33  * @desc 切点类  34 */  35  36 @Aspect  37 @Component  38 public class SystemLogAspect {  39  40 //注入Service用于把日志保存数据库  41 @Resource //这里我用resource注解,一般用的是@Autowired,他们的区别如有时间我会在后面的博客中来写  42 private SystemLogService systemLogService;  43  44 private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);  45  46 //Controller层切点  47 @Pointcut("execution (* com.gcx.controller..*.*(..))")  48 public void controllerAspect() {  49  }  50  51 /**  52  * 前置通知 用于拦截Controller层记录用户的操作  53  *  54  * @param joinPoint 切点  55 */  56 @Before("controllerAspect()")  57 public void doBefore(JoinPoint joinPoint) {  58 System.out.println("==========执行controller前置通知===============");  59 if(logger.isInfoEnabled()){  60 logger.info("before " + joinPoint);  61  }  62  }  63  64 //配置controller环绕通知,使用在方法aspect()上注册的切入点  65 @Around("controllerAspect()")  66 public void around(JoinPoint joinPoint){  67 System.out.println("==========开始执行controller环绕通知===============");  68 long start = System.currentTimeMillis();  69 try {  70  ((ProceedingJoinPoint) joinPoint).proceed();  71 long end = System.currentTimeMillis();  72 if(logger.isInfoEnabled()){  73 logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");  74  }  75 System.out.println("==========结束执行controller环绕通知===============");  76 } catch (Throwable e) {  77 long end = System.currentTimeMillis();  78 if(logger.isInfoEnabled()){ 79 logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage()); 80 } 81 } 82 } 83 84 /** 85 * 后置通知 用于拦截Controller层记录用户的操作 86 * 87 * @param joinPoint 切点 88 */ 89 @After("controllerAspect()") 90 public void after(JoinPoint joinPoint) { 91 92 /* HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 93 HttpSession session = request.getSession(); */ 94 //读取session中的用户 95 // User user = (User) session.getAttribute("user"); 96 //请求的IP 97 //String ip = request.getRemoteAddr(); 98 User user = new User(); 99 user.setId(1); 100 user.setName("张三"); 101 String ip = "127.0.0.1"; 102 try { 103 104 String targetName = joinPoint.getTarget().getClass().getName(); 105 String methodName = joinPoint.getSignature().getName(); 106 Object[] arguments = joinPoint.getArgs(); 107 Class targetClass = Class.forName(targetName); 108 Method[] methods = targetClass.getMethods(); 109 String operationType = ""; 110 String operationName = ""; 111 for (Method method : methods) { 112 if (method.getName().equals(methodName)) { 113 Class[] clazzs = method.getParameterTypes(); 114 if (clazzs.length == arguments.length) { 115 operationType = method.getAnnotation(Log.class).operationType(); 116 operationName = method.getAnnotation(Log.class).operationName(); 117 break; 118 } 119 } 120 } 121 //*========控制台输出=========*// 122 System.out.println("=====controller后置通知开始====="); 123 System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType); 124 System.out.println("方法描述:" + operationName); 125 System.out.println("请求人:" + user.getName()); 126 System.out.println("请求IP:" + ip); 127 //*========数据库日志=========*// 128 SystemLog log = new SystemLog(); 129 log.setId(UUID.randomUUID().toString()); 130 log.setDescription(operationName); 131 log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType); 132 log.setLogType((long)0); 133 log.setRequestIp(ip); 134 log.setExceptioncode( null); 135 log.setExceptionDetail( null); 136 log.setParams( null); 137 log.setCreateBy(user.getName()); 138 log.setCreateDate(new Date()); 139 //保存数据库 140 systemLogService.insert(log); 141 System.out.println("=====controller后置通知结束====="); 142 } catch (Exception e) { 143 //记录本地异常日志 144 logger.error("==后置通知异常=="); 145 logger.error("异常信息:{}", e.getMessage()); 146 } 147 } 148 149 //配置后置返回通知,使用在方法aspect()上注册的切入点 150 @AfterReturning("controllerAspect()") 151 public void afterReturn(JoinPoint joinPoint){ 152 System.out.println("=====执行controller后置返回通知====="); 153 if(logger.isInfoEnabled()){ 154 logger.info("afterReturn " + joinPoint); 155 } 156 } 157 158 /** 159 * 异常通知 用于拦截记录异常日志 160 * 161 * @param joinPoint 162 * @param e 163 */ 164 @AfterThrowing(pointcut = "controllerAspect()", throwing="e") 165 public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { 166 /*HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 167 HttpSession session = request.getSession(); 168 //读取session中的用户 169 User user = (User) session.getAttribute(WebConstants.CURRENT_USER); 170 //获取请求ip 171 String ip = request.getRemoteAddr(); */ 172 //获取用户请求方法的参数并序列化为JSON格式字符串 173 174 User user = new User(); 175 user.setId(1); 176 user.setName("张三"); 177 String ip = "127.0.0.1"; 178 179 String params = ""; 180 if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { 181 for ( int i = 0; i < joinPoint.getArgs().length; i++) { 182 params += JsonUtil.getJsonStr(joinPoint.getArgs()[i]) + ";"; 183 } 184 } 185 try { 186 187 String targetName = joinPoint.getTarget().getClass().getName(); 188 String methodName = joinPoint.getSignature().getName(); 189 Object[] arguments = joinPoint.getArgs(); 190 Class targetClass = Class.forName(targetName); 191 Method[] methods = targetClass.getMethods(); 192 String operationType = ""; 193 String operationName = ""; 194 for (Method method : methods) { 195 if (method.getName().equals(methodName)) { 196 Class[] clazzs = method.getParameterTypes(); 197 if (clazzs.length == arguments.length) { 198 operationType = method.getAnnotation(Log.class).operationType(); 199 operationName = method.getAnnotation(Log.class).operationName(); 200 break; 201 } 202 } 203 } 204 /*========控制台输出=========*/ 205 System.out.println("=====异常通知开始====="); 206 System.out.println("异常代码:" + e.getClass().getName()); 207 System.out.println("异常信息:" + e.getMessage()); 208 System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType); 209 System.out.println("方法描述:" + operationName); 210 System.out.println("请求人:" + user.getName()); 211 System.out.println("请求IP:" + ip); 212 System.out.println("请求参数:" + params); 213 /*==========数据库日志=========*/ 214 SystemLog log = new SystemLog(); 215 log.setId(UUID.randomUUID().toString()); 216 log.setDescription(operationName); 217 log.setExceptioncode(e.getClass().getName()); 218 log.setLogType((long)1); 219 log.setExceptionDetail(e.getMessage()); 220 log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); 221 log.setParams(params); 222 log.setCreateBy(user.getName()); 223 log.setCreateDate(new Date()); 224 log.setRequestIp(ip); 225 //保存数据库 226 systemLogService.insert(log); 227 System.out.println("=====异常通知结束====="); 228 } catch (Exception ex) { 229 //记录本地异常日志 230 logger.error("==异常通知异常=="); 231 logger.error("异常信息:{}", ex.getMessage()); 232 } 233 /*==========记录本地异常日志==========*/ 234 logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params); 235 236 } 237 238 }
复制代码

 我这里写的比较全,前置通知,环绕通知,后置通知,异常通知,后置饭后通知,都写上了,在我们实际编写中不写全也没事,我习惯上把记录日志的逻辑写在后置通知里面,我看网上也有些在前置通知里面的,但我感觉写在后置通知里比较好。

下面开始在controller中加入自定义的注解!!

复制代码
 1 package com.gcx.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;  4 import org.springframework.stereotype.Controller;  5 import org.springframework.web.bind.annotation.RequestMapping;  6  7 import com.gcx.annotation.Log;  8 import com.gcx.service.UserService;  9 10 @Controller 11 @RequestMapping("userController") 12 public class UserController { 13 14  @Autowired 15 private UserService userService; 16 17 @RequestMapping("testAOP") 18 @Log(operationType="add操作:",operationName="添加用户") 19 public void testAOP(String userName,String password){ 20  userService.addUser(userName, password); 21  } 22 }
复制代码

下面编写测试类

复制代码
1 @Test
2     public void testAOP1(){ 3 //启动Spring容器 4 ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-mvc.xml","classpath:applicationContext-dataSource.xml"}); 5 //获取service或controller组件 6 UserController userController = (UserController) ctx.getBean("userController"); 7 userController.testAOP("zhangsan", "123456"); 8  } 9 
复制代码

数据库数据:

我原本想写两个切点,一个是service层,一个是controller层,service层是用来记录异常信息的日志,而controller层的是用来记录功能的日志,运行结果如下。    

这样做的话不知道在实际的项目中运行效率好不好,在这里请看到博客的大牛给点建议!!

生活源于拼搏!

转载于:https://www.cnblogs.com/1995hxt/p/6095164.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469881.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPG96244QS1屏驱动难题

void Gpg_Master(unsigned int Data) {unsigned int temp 0b1000000000000000;Master_SCK1;ENABLE_244QS1();//初始化前使能片选_delay(10);DISABLE_244QS1();Master_SCK0; //Generate SCK Clockdo{Master_SDI Data &temp;Master_SCK1; _delay(10); Master_SCK0; //Gener…

linux装机量,在没有盗版的世界 Linux桌面的装机量可能占比达到40%

近日&#xff0c;由奥斯陆大学经济学系博士生Arne Rogde Gramstad公布的“Software Piracy and Linux Adoption”研究报告&#xff0c;发现了Linux系统装机量和软件盗版之间的潜在关联。在这份报告中引用了商业软件联盟(BSA)自2012年以来从104 个国家收集的盗版软件信息&#x…

Spring.io本地服务器解决超时问题

建本地服务器的方法&#xff0c;详情参考官方说明&#xff1a;https://github.com/spring-io/initializr 打开一看是英文&#xff0c;而且你鼓捣半天不一定成功&#xff0c;没事&#xff0c;我已经搭建好了可执行jar包给你下载使用&#xff01;你只需要java -jar&#xff0c;如…

lgg6 android 9,LG G6的18:9屏幕用起来到底是什么样

前不久LG公布了全新18:9屏幕&#xff0c;据他们称这块屏幕是特意为智能手机而设计&#xff0c;如今传言也指向LG G6将会成为首款使用这块屏幕的旗舰&#xff0c;那么为何LG会放弃智能手机坚持的16:9转而使用18&#xff1a;9&#xff0c;体验又会是什么样呢&#xff1f;最近LG公…

屏上有一层紫色(正在找原因)

注&#xff1a; 1、这两天一直在找这个原因、5150控制成功、屏驱动成功、可是为什么屏上面有一层紫色的覆盖住了呢、非常的让我感到不解2、如果什么也不输入、解码出来的信号在TFT上显示是紫色、我现在是不怎么清楚是屏的原因还是解码的原因

Cadence PCB SI

Cadence PCB信号完整性 (SI) 和电源完整性技术(PI)提供了可调整、高性价比并且支持前仿真和后仿真的系统互联设计和分析环境。 Cadence PCB信号完整性 (SI) 和电源完整性技术(PI)提供了可调整、高性价比并且支持前仿真和后仿真的系统互联设计和分析环境。Cadence PCB SI和PI产品…

java1.8安装

简单说下&#xff0c;jdk1.8*的下载&#xff0c;见http://www.cnblogs.com/zlslch/p/5658383.html 双击jdk-8u60-windows-x64.exe运行程序 欢迎使用Java SE开发工具包8 Update 60的安装向导界面&#xff0c;点击“下一步” 选择安装可选功能界面&#xff0c;默认安装&#xff0…

图像正确(相当于这个小项目就要结尾了)

到这里这个小项目就要进入尾声了 1、在其中遇到了很多问题、也听了部门前辈的指点、有的人说的正确、有的人说的不沾边、这时候真的是需要自己去衡量哪个人说的才是自己所需要的、2、关于TVP5150的配置和GPGTFT的配置、刚开始的时候都不知道到底是哪一个配置会出了什么问题、后…

华为升级harmonyos的机型名单,华为智慧屏HarmonyOS 1.0.1.50更新机型和方法

华为智慧屏 V65/V65i/V65尊爵版/V75 新版本发布HarmonyOS 1.0.1.50一、 适配机型&#xff1a;华为智慧屏 V65 4G64G(HEGE-560)华为智慧屏 V65i 4G32G(HEGE-560B)华为智慧屏 V65尊爵版 4G128G(HEGE-560S)华为智慧屏 V75 4G64G(HEGE-570)二、 更新方式&#xff1a;智慧屏系…

LCD-DBI接口与DPI接口与DSI接口

&#xff08;1&#xff09;DBI接口 A&#xff0c;也就是通常所讲的MCU借口&#xff0c;俗称80 system接口。The lcd interface between host processor and LCM device list as below,The LCM driver will repeated update panel display。MCU借口通过并行接口传输控制命令和数…

ios截屏 u3d导出Xcode工程截屏

在ios原生程序里面 全屏截屏 UIWindow *window [[UIApplication sharedApplication] keyWindow];  //下边是经典的4步 UIGraphicsBeginImageContext(window.frame.size);  //打开画布&#xff0c;并设定大小 [window.layer renderInContext:UIGraphicsGetCurrentContext()…

linux我回来了

如题 我想说、linux我又要回来了、不是为了什么就是为了原先刚开始喜欢你的感情一样离开了这么久、学了几行JAVA、搞了一下安卓、不过我还是回到了linux庆幸的是、当初我把我的系统备份了下来、没有删除、所以一切都感觉很熟悉

logistic模型原理与推导过程分析(1)

从线性分类器谈起 给定一些数据集合&#xff0c;他们分别属于两个不同的类别。例如对于广告数据来说&#xff0c;是典型的二分类问题&#xff0c;一般将被点击的数据称为正样本&#xff0c;没被点击的数据称为负样本。现在我们要找到一个线性分类器&#xff0c;将这些数据分为两…

linux Hello World 模块编程

折腾了差不多一个晚上: 1、关于在前面加上TAB,这个是有必要的、 2、Makefile的编写也是有些差异的 3、关于内核的版本可以通过uname -r来查看一下 我

logistic模型原理与推导过程分析(2)

二项逻辑回归模型 既然logistic回归把结果压缩到连续的区间(0,1)&#xff0c;而不是离散的0或者1&#xff0c;然后我们可以取定一个阈值&#xff0c;通常以0.5为阈值&#xff0c;如果计算出来的概率大于0.5&#xff0c;则将结果归为一类&#xff08;1&#xff09;&#xff0c;…

linux下的字符设备驱动

Linux字符设备驱动程序的一个简单示例一.开发环境&#xff1a; 主 机&#xff1a;VMWare--Fedora 9 开发板&#xff1a;友善之臂mini2440--256MB Nandflash 编译器&#xff1a;arm-linux-gcc-4.3.2 二.驱动源码&#xff1a; 该源码很浅显易懂&#xff0c;非常适合初学者。 me…

logistic模型原理与推导过程分析(3)

附录&#xff1a;迭代公式向量化 θ相关的迭代公式为&#xff1a; ​ 如果按照此公式操作的话&#xff0c;每计算一个θ需要循环m次。为此&#xff0c;我们需要将迭代公式进行向量化。 首先我们将样本矩阵表示如下&#xff1a; 将要求的θ也表示成矩阵的形式&#xff1a; 将x…

计算机表示法是知识 表示法么,计算机三级考试关于IP地址知识点

计算机三级考试关于IP地址知识点IP地址是IP协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异&#xff0c;同时也是计算机三级考试的重要内容&#xff0c;小编整理了相关知识点&#xff0c;…

监督学习与无监督学习

监督学习 用一个例子介绍什么是监督学习把正式的定义放在后面介绍。 假如说你想预测房价。前阵子&#xff0c;一个学生从波特兰俄勒冈州的研究所收集了一些房价的数据。你把这些数据画出来&#xff0c;看起来是这个样子&#xff1a; 横轴表示房子的面积&#xff0c;单位是平…

【CodeVS】1023 GPA计算

1023 GPA计算 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 小松终于步入了大学的殿堂&#xff0c;带着兴奋和憧憬&#xff0c;他参加了信息科学技术学院的新生大会。会上&#xff0c;院长梅教授给大家介绍了在大学中的成绩计算方式&…