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版本的不会报错
猜你喜欢
spring/springmvc
70
"spring在ioc容器中获取aop的受理对象",这句话是什么意思呢?有时候我们会在spring项目中对一下类进行代理,比如我们会用spring的aop和自定义注解对一些接口访问添加日志,再比如对
框架
226
1.Log注解importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;//
blog
spring的生命周期
spring/springmvc
515
bean的什么周期SpringBean的生命周期在整个Spring中占有很重要的位置,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个
spring/springmvc
1463
目接着就开始配置spring,springmvc,mybatis等1.首先目录结构如下因为上次没有在model-web模块中添加对model-common的依赖,所以这次我们在model-web的pom
spring/springmvc
895
搭建spring+springmvc+mybatis+maven项目(1)首先在配置好maven仓库的情况下:1.创建父项目file-new-mavenprojectnextgroup为父项目坐标
框架
1390
1.项目结构2.pom文件依赖?xmlversion="1.0"encoding="UTF-8"?projectxmlns="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.
框架
3160
上次我们说了spring集成websocket,实现用websocket通讯集成配置连接:http://www.jiajiajia.club/weblog/blog/artical/128下面来模拟
框架
1055
如果你的eclipse安装了springboot插件可以通过下面方式1.选择springboot项目右击选择spring-adddevtools2.点击后pom文件中会出现一个依赖
最近发表
归档
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月
4
标签
算法基础
linux
前端
c++
数据结构
框架
数据库
计算机基础
储备知识
java基础
ASM
其他
深入理解java虚拟机
nginx
git
undefined
undefined
sdf
sdf
dsdf
sdfasdfasd
sdf
ppp
sdf
fggdgsd
kkk
kkk
kkk
sdddf
456