我是靠谱客的博主 愤怒发夹,这篇文章主要介绍Spring Boot利用AOP获取用户操作实现日志记录,现在分享给大家,希望可以做个参考。

环境:IDEA版本2017.3.1 x64, JDK1.8, SpringBoot2.1.1, Druid1.1.8, mybatis1.3.2,Security5.1.2,thymeleaf3.0.11

思路总结:首先在需要做日志记录的方法中添加一个自定义注解,再去实现一个日志AOP类,AOP类把自定义注解设置为切点,所以当系统执行某一个添加了自定义注解的方法时,AOP会自动获取该方法名称以及用户信息实现日志记录。

编写自定义注解

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** * 自定义注解类 定义controller方法的中文含义 * @Target({METHOD,TYPE}) 表示这个注解可以用用在类/接口上,还可以用在方法上 * @Retention(RetentionPolicy.RUNTIME) 表示这是一个运行时注解,即运行起来之后,才获取注解中的相关信息,而不像基本注解如@Override 那种不用运行,在编译时eclipse就可以进行相关工作的编译时注解。 * @Inherited 表示这个注解可以被子类继承 * @Documented 表示当执行javadoc的时候,本注解会生成相关文档 */ @Target({METHOD, TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Operation { String value() default ""; } 复制代码

日志AOP类会用到获取IP地址的工具类,也用到json工具类,实现工具类如下

实现必要工具类

获取ip地址工具类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/** * 获取用户真实的ip地址 * @param request * @return */ public class IpAdrressUtil { public static String getIpAdrress(HttpServletRequest request) { String ip = null; //X-Forwarded-For:Squid 服务代理 String ipAddresses = request.getHeader("X-Forwarded-For"); String unknown = "unknown"; if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) { //Proxy-Client-IP:apache 服务代理 ipAddresses = request.getHeader("Proxy-Client-IP"); } if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) { //WL-Proxy-Client-IP:weblogic 服务代理 ipAddresses = request.getHeader("WL-Proxy-Client-IP"); } if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) { //HTTP_CLIENT_IP:有些代理服务器 ipAddresses = request.getHeader("HTTP_CLIENT_IP"); } if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) { //X-Real-IP:nginx服务代理 ipAddresses = request.getHeader("X-Real-IP"); } //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP if (ipAddresses != null && ipAddresses.length() != 0) { ip = ipAddresses.split(",")[0]; } //还是不能获取到,最后再通过request.getRemoteAddr();获取 if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) { ip = request.getRemoteAddr(); } return ip; } } 复制代码
实现json工具类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class JacksonUtil { private final static ObjectMapper objectMapper = new ObjectMapper(); private JacksonUtil() { } public static ObjectMapper getInstance() { return objectMapper; } /** * javaBean、列表数组转换为json字符串 */ public static String obj2json(Object obj) throws Exception { return objectMapper.writeValueAsString(obj); } /** * json 转JavaBean */ public static <T> T json2pojo(String jsonString, Class<T> clazz) throws Exception { objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); return objectMapper.readValue(jsonString, clazz); } /** * json字符串转换为map */ public static <T> Map<String, Object> json2map(String jsonString) throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(jsonString, Map.class); } } 复制代码

实现日志AOP类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/** * 系统日志:切面处理类 */ @Aspect @Component public class SysLogAspect { @Autowired private SysLogService sysLogService; //定义切点 @Pointcut //在注解的位置切入代码 @Pointcut("@annotation(cn.springboot.util.Operation)") public void logPoinCut() { } //切面 配置通知 @AfterReturning("logPoinCut()") public void saveSysLog(JoinPoint joinPoint) { //保存日志 SysLog sysLog = new SysLog(); //从切面织入点处通过反射机制获取织入点处的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //获取切入点所在的方法 Method method = signature.getMethod(); //获取操作 Operation operation = method.getAnnotation(Operation.class); if (operation != null) { String value = operation.value(); sysLog.setOperation(value);//保存获取的操作 } //获取请求的类名 String className = joinPoint.getTarget().getClass().getName(); //获取请求的方法名 String methodName = method.getName(); sysLog.setMethod(className + "." + methodName); //请求的参数 Object[] args = joinPoint.getArgs(); //将参数所在的数组转换成json String params = null; try { params = JacksonUtil.obj2json(args); } catch (Exception e) { e.printStackTrace(); } sysLog.setParams(params); //请求的时间 sysLog.setCreateDate(new Date()); //获取用户名 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { sysLog.setUsername(authentication.getName()); } //获取用户ip地址 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getRequest(); sysLog.setIp(IpAdrressUtil.getIpAdrress(request)); //调用service保存SysLog实体类到数据库 sysLogService.saveLog(sysLog); } } 复制代码

最后,我是调用service保存SysLog实体类到数据库,你也可以直接输出到控制台,要保存到数据库,还要实现service类,mapper类和javeBean。 我就简单贴个javaBean,其他类就不具体贴出了。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data @NoArgsConstructor @AllArgsConstructor public class SysLog implements Serializable { private Long id; private String username; //用户名 private String operation; //操作 private String method; //方法名 private String params; //参数 private String ip; //ip地址 private Date createDate; //操作时间 //创建getter和setter方法 } 复制代码

javaBean中使用lombok的注解实现了get、set等方法。

以下是存进数据库的数据,关于IP的问题是因为本地测试,部署在服务器上就会有正常的IP地址了。

更多Spring Boot整合可浏览此博客:malizhi.cn

转载于:https://juejin.im/post/5c1a23e0e51d451e4b1db05d

最后

以上就是愤怒发夹最近收集整理的关于Spring Boot利用AOP获取用户操作实现日志记录的全部内容,更多相关Spring内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部