java aop日志记录_AOP实现日志记录功能
场景:整个系统的DML操作需要记录日志
记录内容:1 操作人 2 操作时间 3 操作类型(登录 新增 修改 删除) 4 操作描述 5 详细请求数据(varchar2()) 6 操作IP ==>日志表
实现:
原来方式:在每个方法的里面编写记录日志代码;
缺点:代码重复 ,与原有逻辑耦合度高。
AOP: 将日志记录功能提取到切面中。动态切入到需要日志记录的方法上即可;
优点: 解耦合,代码复用。
1) 先写一个日志切面LogAspect.java;
//日志切面
@Component//对象由spring管理
@Aspect//切面注解
public classLogAspect {//定义切入点,切入到添加了LogData注解的方法上
@Pointcut("@annotation(aop.LogData)")public voidpointCut(){}/**
* 记录日志的切面方法
* 在该方法中定义统一的日志记录逻辑
* @param joinPoint*/@Before("pointCut()")public voidlog(JoinPoint joinPoint){
System.out.println("进入日志Aspect");
}
}
2)写一个日志信息LogData.java;
//自定义日志注解
@Target({ElementType.METHOD})//指定作用的目标对象(可以添加的位置)
@Retention(RetentionPolicy.RUNTIME)//指定在运行期间起作用
public@interface LogData {//定义注解中的属性
String description() default "";//日志类型
intlogType();
}
3)在控制层方法上写上注解,加上描述信息,描述日志;
@LogData(logType = 1,description = "学生信息修改")
@RequestMapping("/update")publicString update(Integer id,ModelMap modelMap){//查询用户信息,展示到页面
Student student=studentService.findById(id);
modelMap.put("student",student);return "update.jsp";
}
要想起作用,还要在springmvc.xml配置文件中配置AOP注解;
二、自定义注解
枚举:jdk1.5之后存在的一种数据类型。用来定义有限个对象。 enum
语法:
Public enum 类名{
对象定义;
类的成员定义
}
调用: 类名.对象名 获取枚举对象。
1)创建一个LogType.java文件来写枚举;
/**
* 日志枚举类型
* 枚举是一个特殊的类
* class 可以创建n个对象
* 枚举类型的对象是固定的*/
public enumLogType {//创建枚举对象,对象的个数是有限的,对象与对象之间用逗号隔开
LOGIN(1),DELETE(2),UPDATE(3),INSERT(4);//可以定义任意的方法和属性,与普通类类似
private final inttype;//构造方法
LogType(inttype) {this.type =type;
}public intgetType() {returntype;
}
}
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")publicString delete(Integer id){
studentService.delete(id);return "redirect:list";
}
@LogData(logType= LogType.UPDATE,description = "学生信息修改")
@RequestMapping("/update2")publicString update2(Integer id,ModelMap modelMap){
Student student=studentService.selectById(id);
modelMap.put("student",student);return "update.jsp";
}
@LogData(logType= LogType.INSERT,description = "学生信息新增")
@RequestMapping("/insert")publicString insert(Student student){
studentService.insert(student);return "redirect:list";
}
4)写LogAspect.java文件;
@Component//对象由spring管理
@Aspect//切面注解
public classLogAspect {private static final Logger LOGGER = LogManager.getLogger(LogAspect.class);//定义切入点,切入到添加了LogData注解的方法上
@Pointcut("@annotation(aop.LogData)")public voidpointCut(){
}/**
* 记录日志的切面方法
* 在该方法中定义统一的日志记录逻辑
* @param joinPoint*/@Before("pointCut()")public voidlog(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 parameterMap=request.getParameterMap();//将对象转换成json字符串==>存储到请求数据字段中//jackSon json字符串操作
ObjectMapper objectMapper=newObjectMapper();try{
String s=objectMapper.writeValueAsString(parameterMap);
LOGGER.info("请求数据:"+s);
}catch(JsonProcessingException e) {
e.printStackTrace();
}//todo 将日志信息保存到数据库 LogController service mapper jsp
}
}
三、枚举
枚举可用于switch语句中
public classT {public static voidmain(String[] args) {
test(LogType.DELETE);//获取到枚举对象
LogType logType =LogType.DELETE;//获取到对象之后,与普通对象操作方式一样
int type =logType.getType();
}/**
* 枚举类型在switch中的使用
* @param logType*/
public static voidtest(LogType logType) {switch(logType){caseLOGIN:
System.out.println("登录操作");break;caseDELETE:
System.out.println("删除操作");break;caseINSERT:
System.out.println("插入操作");break;caseUPDATE:
System.out.println("修改操作");break;
}
}
}
四、枚举还是实现单例模式的最佳方式