spring aop实现操作日志记录
spring aop实现操作日志记录
此次的目的是实现 对 controller中的方法执行情况进行记录,记录的有方法执行时间,操作人,请求的路径,方法的入参,模块,功能等。并实现利用注解的方式实现对被操作方法的简单注释(模块,功能)
框架 springmvc+ mybatis
1.Log注解
package com.dzqc.dz.common.aop;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/** 方法模块 */
String title() default "";
/** 功能 */
String action() default "";
}
2.LogAspect切面 (重点)
package com.dzqc.dz.common.aop;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.dzqc.dz.common.dao.LogMapper;
import com.dzqc.dz.common.entity.LogMessage;
/**
* @author Administrator
* @Description 日志记录
*/
public class LogAspect {
@Autowired
private LogMapper logMapper;//日志 mapper
private String requestPath = null ; // 请求地址
private long startTimeMillis = 0; // 开始时间
private long endTimeMillis = 0; // 结束时间
private String user = null; // 操作人
private HttpServletRequest request = null;//请求
/**
* @param joinPoint
* @Description 气质通知 方法调用前触发 记录开始时间,从session中获取操作人
*/
public void before(JoinPoint joinPoint){
startTimeMillis = System.currentTimeMillis();
}
/**
* @param joinPoint
* @Description 获取入参方法参数
* @return
*/
public Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
Map<String, Object> param = new HashMap<>();
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature)joinPoint.getSignature()).getParameterNames();
for (int i = 0; i < paramNames.length; i++) {
if(paramValues[i] instanceof Integer || paramValues[i] instanceof String) {
param.put(paramNames[i], paramValues[i]);
}
}
return param;
}
/**
* @param joinPoint
* @Description 后置通知 方法调用后触发 记录结束时间 ,操作人 ,入参等
*/
public void after(JoinPoint joinPoint) {
request = getHttpServletRequest();
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class<?> targetClass = null;
try {
targetClass = Class.forName(targetName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = targetClass.getMethods();
String title;
String action;
Class<?>[] clazzs;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
clazzs = method.getParameterTypes();
if (clazzs!=null&&clazzs.length == arguments.length
&&method.getAnnotation(Log.class)!=null) {
request = getHttpServletRequest();
requestPath=request.getServletPath();
user = (String) request.getSession().getAttribute("user");
title = method.getAnnotation(Log.class).title();
action = method.getAnnotation(Log.class).action();
endTimeMillis = System.currentTimeMillis();
LogMessage log=new LogMessage(user, requestPath,
(endTimeMillis-startTimeMillis)+"ms",
getNameAndValue(joinPoint).toString(), title, action);
logMapper.writeLog(log);
break;
}
}
}
}
/**
* @Description: 获取request
*/
public HttpServletRequest getHttpServletRequest(){
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes)ra;
HttpServletRequest request = sra.getRequest();
return request;
}
/**
* @param joinPoint
* @return 环绕通知
* @throws Throwable
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
return null;
}
/**
* @param joinPoint
* @Description 异常通知
*/
public void throwing(JoinPoint joinPoint) {
System.out.println("异常通知");
}
}
3.封装日志信息的实体类
package com.dzqc.dz.common.entity;
public class LogMessage {
private String operationUser;//操作人
private String path;//请求路径
private String time;//方法执行时间
private String parameter;//方法入参
private String title;//操作方法
private String action;//方法描述
public String getOperationUser() {
return operationUser;
}
public LogMessage() {
super();
// TODO Auto-generated constructor stub
}
public LogMessage(String operationUser, String path, String time,
String parameter, String title, String action) {
super();
this.operationUser = operationUser;
this.path = path;
this.time = time;
this.parameter = parameter;
this.title = title;
this.action = action;
}
public void setOperationUser(String operationUser) {
this.operationUser = operationUser;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getParameter() {
return parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
4.Mapper
package com.dzqc.dz.common.dao;
import com.dzqc.dz.common.entity.LogMessage;
public interface LogMapper {
public void writeLog(LogMessage message);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.dzqc.dz.common.dao.LogMapper" >
<insert id="writeLog" parameterType="com.dzqc.dz.common.entity.LogMessage">
INSERT into log(operationUser,path,time,parameter,title,action) VALUES(#{operationUser},#{path},#{time},#{parameter},#{title},#{action});
</insert>
</mapper>
5.spring aop配置文件
<aop:aspectj-autoproxy proxy-target-class="true" />
<!--将日志类注入到bean中。-->
<bean id="logAspect" class="com.dzqc.dz.common.aop.LogAspect"></bean>
<aop:config>
<aop:aspect id="LogAspect" ref="logAspect">
<aop:pointcut id="log" expression="execution(* com.dzqc.dz.*.controller.*.*(..))"/>
<aop:before pointcut-ref="log" method="before"/>
<aop:after-throwing pointcut-ref="log" method="throwing" throwing="e"/>
<aop:after pointcut-ref="log" method="after"/>
</aop:aspect>
</aop:config>
6.测试controller
package com.dzqc.dz.common.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dzqc.dz.common.aop.Log;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/logtest")
@ResponseBody
@Log(title="logtest",action="测试log日志")
public Map<String,Object> logtest(HttpSession session,Integer id,String username) {
session.setAttribute("user","jiajiajia");
Map<String,Object> map=new HashMap<>();
map.put("code", 200);
map.put("data", "success");
return map;
}
@RequestMapping("/test")
@ResponseBody
public Map<String,Object> test(HttpSession session,Integer id,String username) {
session.setAttribute("user","jiajiajia");
Map<String,Object> map=new HashMap<>();
map.put("code", 200);
map.put("data", "success");
return map;
}
}
我们在logtest方法中加入Log注解,在调用这个方法的时候 会把一些信息记录进数据库,而没有加Log注解的方法则没有记录,但是根据aop的配置可知,TestController中所有的方法都被植入进了 LogAspect 切面中的逻辑,只是在LogAspect中进行了判断,只有带Log注解的方法执行才会 被记录进数据库。
测试
注意:如果运行出现如下错误,请换较高版本的spring依赖
<spring.version>4.3.5.RELEASE</spring.version>
4.3.5版本的不会报错
猜你喜欢
框架
882
1.Log注解importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;//
spring/springmvc
642
"spring在ioc容器中获取aop的受理对象",这句话是什么意思呢?有时候我们会在spring项目中对一下类进行代理,比如我们会用spring的aop和自定义注解对一些接口访问添加日志,再比如对
blog
spring的生命周期
spring/springmvc
976
bean的什么周期SpringBean的生命周期在整个Spring中占有很重要的位置,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个
spring/springmvc
1929
目接着就开始配置spring,springmvc,mybatis等1.首先目录结构如下因为上次没有在model-web模块中添加对model-common的依赖,所以这次我们在model-web的pom
spring/springmvc
1520
搭建spring+springmvc+mybatis+maven项目(1)首先在配置好maven仓库的情况下:1.创建父项目file-new-mavenprojectnextgroup为父项目坐标
official
405
BeanPostProcessor是SpringIOC容器给我们提供的一个扩展接口。,他的作用主要是如果我们需要在Spring容器完成Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处
blog
mysql日志分析
数据库
287
MariaDB/MySQL中,主要有5种日志文件:1.错误日志(errorlog):记录mysql服务的启停时正确和错误的信息,还记录启动、停止、运行过程中的错误信息。2.查询日志(generallog):
blog
mysql日志分析【二进制日志】
数据库
334
开启和设置二进制日志日志切换二进制日志相关参数二进制日志恢复数据库上一篇文章介绍了普通查询日志和慢查询日志等参考:mysql日志分析,本篇主要介绍二进制日志。一、什么是二进制日志 二进制日志主要记
最近发表
归档
2018年11月
12
2018年12月
33
2019年01月
28
2019年02月
28
2019年03月
32
2019年04月
27
2019年05月
33
2019年06月
6
2019年07月
12
2019年08月
12
2019年09月
21
2019年10月
8
2019年11月
15
2019年12月
25
2020年01月
9
2020年02月
5
2020年03月
16
2020年04月
4
2020年06月
1
2020年07月
7
2020年08月
13
2020年09月
9
2020年10月
5
2020年12月
3
2021年01月
1
2021年02月
5
2021年03月
7
2021年04月
4
2021年05月
4
2021年06月
1
2021年07月
7
2021年08月
2
2021年09月
8
2021年10月
9
2021年11月
16
2021年12月
14
2022年01月
7
2022年05月
1
2022年08月
1
标签
算法基础
linux
前端
c++
数据结构
框架
数据库
计算机基础
储备知识
java基础
ASM
其他
深入理解java虚拟机
nginx
git
消息中间件
搜索
maven
redis
docker
dubbo
vue
导入导出
软件使用
idea插件
协议
无聊的知识
jenkins
springboot
mqtt协议
keepalived
minio
目录
祝愿神州十三飞行乘组平安归来