需求:
项目中需要记录用户操作信息,例如用户登陆系统后做了那些操作,需要有具体的日志记录。
解决办法:
1、编写操作记录日志业务类,在使用的方法中调用(一般记录方式)。
2、使用面向切面方式记录日志,例如针对某些业务处理方法进行日志记录。
3、通过注解方式,在调用的业务方法上增加日志类注解。
推荐使用第二、第三中方式,使用灵活,如果不需要日志记录,将切面取消即可,第一种不够灵活。一些介绍使用注解方式编写日志记录。
项目结构如下:
在pom.xml导入依赖包
xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0modelVersion> <groupId>com.example.springbootgroupId> <artifactId>springboot-aopartifactId> <version>0.0.1-SNAPSHOTversion> <packaging>jarpackaging> <name>springboot-aopname> <description>Demo project for Spring Bootdescription> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>1.5.12.RELEASEversion> <relativePath/> parent> <properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding> <java.version>1.7java.version> properties> <dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-log4jartifactId> <version>1.3.5.RELEASEversion> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-aopartifactId> dependency> <dependency> <groupId>org.mybatis.spring.bootgroupId> <artifactId>mybatis-spring-boot-starterartifactId> <version>1.3.1version> dependency> <dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> dependency> <dependency> <groupId>com.github.pagehelpergroupId> <artifactId>pagehelperartifactId> <version>4.1.0version> dependency> dependencies> <build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> plugin> plugins> build> project>在application.properties配置文件中增加数据库连接
#server.port=8090 #标示使用的是mysql/oracle/sqlserver datasource.type=mysql #mysql数据连接 spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.username=root spring.datasource.password=root #spring.datasource.max-active=20 #spring.datasource.max-idle=8 #spring.datasource.min-idle=8 #spring.datasource.initial-size=20 #mybatis 配置 # 配置映射文件加载 mybatis.mapper-locations=classpath*:mapper/**/*.xml # 实体类通过别名使用 #mybatis.type-aliases-package=
自定义注解类
package com.example.springboot.aop.annotation; import java.lang.annotation.*; /** *自定义注解 拦截Controller */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemControllerLog { String LogAction() default ""; String LogContent() default ""; int ModuleID() default 0; }
实体类
package com.example.springboot.aop.entity; public class SystemLogModel { private String LogAction; private String LogContent; private String FlagID; private String FlagName; private String LogIP; private String TimeFlag; private int ModuleID;
自定义切面类
package com.example.springboot.aop.aspect; import com.example.springboot.aop.annotation.SystemControllerLog; import com.example.springboot.aop.dao.SystemLogMapper; import com.example.springboot.aop.entity.SystemLogModel; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; /** * 切点类 */ @Aspect @Component public class SystemLogAspect { // 本地异常日志记录对象 private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class); @Autowired private SystemLogMapper systemLogMapper; // Controller层切点,针对在业务模块标注SystemControllerLog注解记录日志 @Pointcut("@annotation( com.example.springboot.aop.annotation.SystemControllerLog )") public void controllerAspect() { } /** * 前置通知 用于拦截Controller层记录用户的操作 * * @param joinPoint 切点 */ @Before("controllerAspect()") public void doBefore(JoinPoint joinPoint) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder .getRequestAttributes()).getRequest(); try { // 请求的IP String logIP = request.getHeader("X-Real-IP"); // if (StringUtils.isEmpty(logIP)) { // logIP = request.getRemoteAddr(); // } String userID = request.getParameter("UserID"); String userName = request.getParameter("UserName"); // if (StringUtils.isEmpty(userID) || StringUtils.isEmpty(userName)) { // logger.debug("操作日志-->日志添加:用户名或用户ID为空,返回不添加日志!"); // return; // } SystemLogModel slm = getControllerMethodDescription(joinPoint); slm.setLogIP(logIP); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss"); String date = dateFormat.format(new Date()); slm.setTimeFlag(date); slm.setFlagID(userID); slm.setFlagName(userName); // *========控制台输出=========*// logger.debug("=====注解参数获取开始====="); logger.debug("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); logger.debug("操作模块:" + slm.getModuleID()); logger.debug("操作方法:" + slm.getLogAction()); logger.debug("操作内容:" + slm.getLogContent()); logger.debug("请求IP:" + slm.getLogIP()); logger.debug("FlagID:" + slm.getFlagID()); logger.debug("FlagName:" + slm.getFlagName()); // *========数据库日志=========*// int res = systemLogMapper.saveOrUpdate(slm); if (res > 0) { logger.info(">>>>>>>>保存日志成功"); } } catch (Exception e) { // 记录本地异常日志 logger.error("前置通知异常,保存日志异常信息:{}", e.getMessage()); } } /** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param joinPoint 切点 * @return 方法描述 * @throws Exception */ public static SystemLogModel getControllerMethodDescription( JoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; SystemControllerLog log; SystemLogModel logM = new SystemLogModel(); for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { log = method.getAnnotation(SystemControllerLog.class); logM.setModuleID(log.ModuleID()); logM.setLogAction(log.LogAction()); logM.setLogContent(log.LogContent()); break; } } } return logM; } }
mapper接口
package com.example.springboot.aop.dao; import com.example.springboot.aop.entity.SystemLogModel; import org.apache.ibatis.annotations.Mapper; @Mapper public interface SystemLogMapper { //保存日志 public int saveOrUpdate(SystemLogModel systemLogModel); }mapper配置文件
xml version="1.0" encoding="UTF-8" ?> mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.example.springboot.aop.dao.SystemLogMapper"> <insert id="saveOrUpdate" parameterType="com.example.springboot.aop.entity.SystemLogModel"> insert into test_system_Operation_log(FlagID,FlagName,LogAction,LogContent,LogIP,ModuleID,TimeFlag) values(#{FlagID},#{FlagName},#{LogAction},#{LogContent},#{LogIP},#{ModuleID},#{TimeFlag}) insert> mapper>
创建controller类
package com.example.springboot.aop.controller; import com.example.springboot.aop.annotation.SystemControllerLog; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * @desc aop测试日志记录 * @Author wangsh * @date 2018/5/7 20:57 */ @RestController @RequestMapping("/aop") public class AopController { @SystemControllerLog(LogAction = "查询", ModuleID = 12, LogContent = "测试aop示例") @ResponseBody @RequestMapping("/hello") public String hello() { return "hello"; } }
创建启动服务类
package com.example.springboot.aop; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; //配置扫描指定的包及包下的所以子集 @ComponentScan("com.example.springboot.aop") @SpringBootApplication public class SpringbootAopApplication { public static void main(String[] args) { SpringApplication.run(SpringbootAopApplication.class, args); } }启动服务测试
浏览器访问: http://localhost:8080//aop/hello
查看数据库记录:
以上就是aop切面及注解的使用。