AOP实现日志记录功能
Posted xie-qi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AOP实现日志记录功能相关的知识,希望对你有一定的参考价值。
场景:整个系统的DML操作需要记录日志
记录内容:1 操作人 2 操作时间 3 操作类型(登录 新增 修改 删除) 4 操作描述 5 详细请求数据(varchar2()) 6 操作IP ==>日志表
实现:
原来方式:在每个方法的里面编写记录日志代码;
缺点:代码重复 ,与原有逻辑耦合度高。
AOP: 将日志记录功能提取到切面中。动态切入到需要日志记录的方法上即可;
优点: 解耦合,代码复用。
1) 先写一个日志切面LogAspect.java;
// 日志切面 @Component//对象由spring管理 @Aspect// 切面注解 public class LogAspect { //定义切入点,切入到添加了LogData注解的方法上 @Pointcut("@annotation(aop.LogData)") public void pointCut(){} /** * 记录日志的切面方法 * 在该方法中定义统一的日志记录逻辑 * @param joinPoint */ @Before("pointCut()") public void log(JoinPoint joinPoint){ System.out.println("进入日志Aspect"); } }
2)写一个日志信息LogData.java;
// 自定义日志注解 @Target({ElementType.METHOD})//指定作用的目标对象(可以添加的位置) @Retention(RetentionPolicy.RUNTIME)//指定在运行期间起作用 public @interface LogData { //定义注解中的属性 String description() default ""; //日志类型 int logType(); }
3)在控制层方法上写上注解,加上描述信息,描述日志;
@LogData(logType = 1,description = "学生信息修改") @RequestMapping("/update") public String update(Integer id,ModelMap modelMap){ //查询用户信息,展示到页面 Student student=studentService.findById(id); modelMap.put("student",student); return "update.jsp"; }
要想起作用,还要在springmvc.xml配置文件中配置AOP注解;
<!--配置注解式AOP支持--> <aop:aspectj-autoproxy proxy-target-class="true"/>
二、自定义注解
枚举:jdk1.5之后存在的一种数据类型。用来定义有限个对象。 enum
语法:
Public enum 类名{
对象定义;
类的成员定义
}
调用: 类名.对象名 获取枚举对象。
1)创建一个LogType.java文件来写枚举;
/** * 日志枚举类型 * 枚举是一个特殊的类 * class 可以创建n个对象 * 枚举类型的对象是固定的 */ public enum LogType { //创建枚举对象,对象的个数是有限的,对象与对象之间用逗号隔开 LOGIN(1),DELETE(2),UPDATE(3),INSERT(4); //可以定义任意的方法和属性,与普通类类似 private final int type; //构造方法 LogType(int type) { this.type = type; } public int getType() { return type; } }
2)日志的注解也需要改变为枚举类型的,在LogData.java文件中;
/** * 自定义注解 */ @Target({ElementType.METHOD,ElementType.FIELD})//指定作用的目标对象(可以添加的位置) @Retention(RetentionPolicy.RUNTIME) public @interface LogData { //定义注解中的属性 String description() default ""; //日志类型 1、登录 2、删除 3、修改 4、插入 LogType logType(); }
3)调用日志对象,在控制层中;
@LogData(logType = LogType.DELETE,description = "学生信息删除") @RequestMapping("/delete") public String delete(Integer id){ studentService.delete(id); return "redirect:list"; } @LogData(logType = LogType.UPDATE,description = "学生信息修改") @RequestMapping("/update2") public String update2(Integer id,ModelMap modelMap){ Student student = studentService.selectById(id); modelMap.put("student",student); return "update.jsp"; } @LogData(logType = LogType.INSERT,description = "学生信息新增") @RequestMapping("/insert") public String insert(Student student){ studentService.insert(student); return "redirect:list"; }
4)写LogAspect.java文件;
@Component//对象由spring管理 @Aspect//切面注解 public class LogAspect { private static final Logger LOGGER = LogManager.getLogger(LogAspect.class); //定义切入点,切入到添加了LogData注解的方法上 @Pointcut("@annotation(aop.LogData)") public void pointCut(){ } /** * 记录日志的切面方法 * 在该方法中定义统一的日志记录逻辑 * @param joinPoint */ @Before("pointCut()") public void log(JoinPoint joinPoint){ System.out.println("进入日志Aspect"); //获取到方法签名 MethodSignature signature= (MethodSignature) joinPoint.getSignature(); //获取到连接点方法对象 Method method=signature.getMethod(); //获取方法上面特定的注解 LogData annotation=method.getAnnotation(LogData.class); LogType logType=annotation.logType(); String description=annotation.description(); LOGGER.info("获取到注解内容:logType="+logType.getType() +",description:"+description); //aop中获取request ServletRequestAttributes requestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request=requestAttributes.getRequest(); HttpSession session=request.getSession(); //获取操作人 Student student= (Student) session.getAttribute("student"); //获取请求数据 Map<String,String[]> parameterMap=request.getParameterMap(); //将对象转换成json字符串==>存储到请求数据字段中 //jackSon json字符串操作 ObjectMapper objectMapper=new ObjectMapper(); try { String s=objectMapper.writeValueAsString(parameterMap); LOGGER.info("请求数据:"+s); } catch (JsonProcessingException e) { e.printStackTrace(); } //todo 将日志信息保存到数据库 LogController service mapper jsp } }
三、枚举
枚举可用于switch语句中
public class T { public static void main(String[] args) { test(LogType.DELETE); //获取到枚举对象 LogType logType = LogType.DELETE; //获取到对象之后,与普通对象操作方式一样 int type = logType.getType(); } /** * 枚举类型在switch中的使用 * @param logType */ public static void test(LogType logType) { switch (logType){ case LOGIN: System.out.println("登录操作");break; case DELETE: System.out.println("删除操作");break; case INSERT: System.out.println("插入操作");break; case UPDATE: System.out.println("修改操作");break; } } }
四、枚举还是实现单例模式的最佳方式
以上是关于AOP实现日志记录功能的主要内容,如果未能解决你的问题,请参考以下文章