经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
springboot自定义日志注解的实现
来源:jb51  时间:2022/3/7 16:37:30  对本文有异议

前言

      在之前的日志记录的写法中,我们大多是写一个工具类,在这个类里面定义日志保存的方法,然后再controller中执行请求的时候调用即可,虽然调用仅仅一行代码,但是不够友好;所有可以写一个类似于@Controller等的注解,在需要保存日志的方法上面加上一个注解,这样不用在每个都写一端代码;话不多说上代码

     1、首先一个log的实体类,这个无关紧要    

  1. package com.sysmg.system.domain;
  2. ?
  3. import java.io.Serializable;
  4. import java.util.Date;
  5. ?
  6. import javax.persistence.Column;
  7. import javax.persistence.GeneratedValue;
  8. import javax.persistence.Id;
  9. import javax.persistence.Table;
  10. import javax.persistence.Transient;
  11. ?
  12. import com.sysmg.common.annotation.ExportConfig;
  13. ?
  14. @Table(name = "t_log")
  15. public class SysLog implements Serializable {
  16. ?
  17. ?? ?private static final long serialVersionUID = -8878596941954995444L;
  18. ?
  19. ?? ?@Id
  20. ?? ?@GeneratedValue(generator = "JDBC")
  21. ?? ?@Column(name = "ID")
  22. ?? ?private Long id;
  23. ?
  24. ?? ?@Column(name = "USERNAME")
  25. ?? ?@ExportConfig(value = "操作用户")
  26. ?? ?private String username;
  27. ?
  28. ?? ?@Column(name = "OPERATION")
  29. ?? ?@ExportConfig(value = "描述")
  30. ?? ?private String operation;
  31. ?
  32. ?? ?@Column(name = "TIME")
  33. ?? ?@ExportConfig(value = "耗时(毫秒)")
  34. ?? ?private Long time;
  35. ?
  36. ?? ?@Column(name = "METHOD")
  37. ?? ?@ExportConfig(value = "操作方法")
  38. ?? ?private String method;
  39. ?
  40. ?? ?@Column(name = "PARAMS")
  41. ?? ?@ExportConfig(value = "参数")
  42. ?? ?private String params;
  43. ?
  44. ?? ?@Column(name = "IP")
  45. ?? ?@ExportConfig(value = "IP地址")
  46. ?? ?private String ip;
  47. ?
  48. ?? ?@Column(name = "CREATE_TIME")
  49. ?? ?@ExportConfig(value = "操作时间", convert = "c:com.sysmg.common.util.poi.convert.TimeConvert")
  50. ?? ?private Date createTime;
  51. ?
  52. ?? ?@Column(name = "LOCATION")
  53. ?? ?@ExportConfig(value = "地点")
  54. ?? ?private String location;
  55. ?? ?
  56. ?? ?// 用于搜索条件中的时间字段
  57. ?? ?@Transient
  58. ?? ?private String timeField;
  59. ?
  60. ?? ?/**
  61. ?? ? * @return ID
  62. ?? ? */
  63. ?? ?public Long getId() {
  64. ?? ??? ?return id;
  65. ?? ?}
  66. ?
  67. ?? ?/**
  68. ?? ? * @param id
  69. ?? ? */
  70. ?? ?public void setId(Long id) {
  71. ?? ??? ?this.id = id;
  72. ?? ?}
  73. ?
  74. ?? ?/**
  75. ?? ? * @return USERNAME
  76. ?? ? */
  77. ?? ?public String getUsername() {
  78. ?? ??? ?return username;
  79. ?? ?}
  80. ?
  81. ?? ?/**
  82. ?? ? * @param username
  83. ?? ? */
  84. ?? ?public void setUsername(String username) {
  85. ?? ??? ?this.username = username == null ? null : username.trim();
  86. ?? ?}
  87. ?
  88. ?? ?/**
  89. ?? ? * @return OPERATION
  90. ?? ? */
  91. ?? ?public String getOperation() {
  92. ?? ??? ?return operation;
  93. ?? ?}
  94. ?
  95. ?? ?/**
  96. ?? ? * @param operation
  97. ?? ? */
  98. ?? ?public void setOperation(String operation) {
  99. ?? ??? ?this.operation = operation == null ? null : operation.trim();
  100. ?? ?}
  101. ?
  102. ?? ?/**
  103. ?? ? * @return TIME
  104. ?? ? */
  105. ?? ?public Long getTime() {
  106. ?? ??? ?return time;
  107. ?? ?}
  108. ?
  109. ?? ?/**
  110. ?? ? * @param time
  111. ?? ? */
  112. ?? ?public void setTime(Long time) {
  113. ?? ??? ?this.time = time;
  114. ?? ?}
  115. ?
  116. ?? ?/**
  117. ?? ? * @return METHOD
  118. ?? ? */
  119. ?? ?public String getMethod() {
  120. ?? ??? ?return method;
  121. ?? ?}
  122. ?
  123. ?? ?/**
  124. ?? ? * @param method
  125. ?? ? */
  126. ?? ?public void setMethod(String method) {
  127. ?? ??? ?this.method = method == null ? null : method.trim();
  128. ?? ?}
  129. ?
  130. ?? ?/**
  131. ?? ? * @return PARAMS
  132. ?? ? */
  133. ?? ?public String getParams() {
  134. ?? ??? ?return params;
  135. ?? ?}
  136. ?
  137. ?? ?/**
  138. ?? ? * @param params
  139. ?? ? */
  140. ?? ?public void setParams(String params) {
  141. ?? ??? ?this.params = params == null ? null : params.trim();
  142. ?? ?}
  143. ?
  144. ?? ?/**
  145. ?? ? * @return IP
  146. ?? ? */
  147. ?? ?public String getIp() {
  148. ?? ??? ?return ip;
  149. ?? ?}
  150. ?
  151. ?? ?/**
  152. ?? ? * @param ip
  153. ?? ? */
  154. ?? ?public void setIp(String ip) {
  155. ?? ??? ?this.ip = ip == null ? null : ip.trim();
  156. ?? ?}
  157. ?
  158. ?? ?/**
  159. ?? ? * @return CREATE_TIME
  160. ?? ? */
  161. ?? ?public Date getCreateTime() {
  162. ?? ??? ?return createTime;
  163. ?? ?}
  164. ?
  165. ?? ?/**
  166. ?? ? * @param createTime
  167. ?? ? */
  168. ?? ?public void setCreateTime(Date createTime) {
  169. ?? ??? ?this.createTime = createTime;
  170. ?? ?}
  171. ?
  172. ?? ?public String getLocation() {
  173. ?? ??? ?return location;
  174. ?? ?}
  175. ?
  176. ?? ?public void setLocation(String location) {
  177. ?? ??? ?this.location = location;
  178. ?? ?}
  179. ?
  180. ?? ?public String getTimeField() {
  181. ?? ??? ?return timeField;
  182. ?? ?}
  183. ?
  184. ?? ?public void setTimeField(String timeField) {
  185. ?? ??? ?this.timeField = timeField;
  186. ?? ?}
  187. ?? ?
  188. ?
  189. }

  2、定义一个注解接口

  1. package com.sysmg.common.annotation;
  2. ?
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. ?
  8. @Target(ElementType.METHOD)
  9. @Retention(RetentionPolicy.RUNTIME)
  10. public @interface Log {
  11. ? ? String value() default "";
  12. }

@Target(ElementType.METHOD)代表是方法上的注解,当然也可以是类注解,字段注解等

@Target(ElementType.TYPE) //接口、类、枚举、注解 
@Target(ElementType.FIELD) //字段、枚举的常量 
@Target(ElementType.METHOD) //方法 
@Target(ElementType.PARAMETER) //方法参数 
@Target(ElementType.CONSTRUCTOR) //构造函数 
@Target(ElementType.LOCAL_VARIABLE)//局部变量 
@Target(ElementType.ANNOTATION_TYPE)//注解 
@Target(ElementType.PACKAGE) ///包 

@Retention(RetentionPolicy.RUNTIME)代表注解会被jvm保留,这个参数有三种

RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略 
RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略 
RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
一般默认第三种

当然也可以写

@Documented和@Order(优先级  数字越小优先级越高)

@Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。

@Order标记定义了组件的加载顺序,这个标记包含一个value属性。属性接受整形值。如:1,2 等等。值越小拥有越高的优先级。Ordered.HIGHEST_PRECEDENCE这个属性值是最高优先级的属性,它的值是-2147483648,对应的最低属性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。

String value() default ""

这个代表是要传递的参数,类似

  1. @Autowired(required=true)
  2. ?
  3. ?
  4. public @interface Autowired {
  5. ?
  6. ?? ?/**
  7. ?? ? * Declares whether the annotated dependency is required.
  8. ?? ? * <p>Defaults to {@code true}.
  9. ?? ? */
  10. ?? ?boolean required() default true;
  11. ?
  12. }

springmvc项目还需要开启切面编程

  1. <aop:aspectj-autoproxy proxy-target-class="true"/>

springboot默认是开启的

3、定义注解的实现类,也就是这个注解要做什么事

  1. package com.sysmg.common.aspect;
  2. ?
  3. import java.lang.reflect.Method;
  4. import java.util.Date;
  5. ?
  6. import javax.servlet.http.HttpServletRequest;
  7. ?
  8. import org.apache.shiro.SecurityUtils;
  9. import org.aspectj.lang.ProceedingJoinPoint;
  10. import org.aspectj.lang.annotation.Around;
  11. import org.aspectj.lang.annotation.Aspect;
  12. import org.aspectj.lang.annotation.Pointcut;
  13. import org.aspectj.lang.reflect.MethodSignature;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
  16. import org.springframework.stereotype.Component;
  17. ?
  18. import com.fasterxml.jackson.databind.ObjectMapper;
  19. import com.sysmg.common.annotation.Log;
  20. import com.sysmg.common.util.AddressUtilsBak;
  21. import com.sysmg.common.util.HttpContextUtils;
  22. import com.sysmg.common.util.IPUtils;
  23. import com.sysmg.system.domain.SysLog;
  24. import com.sysmg.system.domain.User;
  25. import com.sysmg.system.service.LogService;
  26. ?
  27. @Aspect
  28. @Component
  29. public class LogAspect {
  30. ?
  31. ?? ?@Autowired
  32. ?? ?private LogService logService;
  33. ?
  34. ?? ?@Autowired
  35. ?? ?ObjectMapper mapper;
  36. ?
  37. ?? ?@Pointcut("@annotation(com.sysmg.common.annotation.Log)")
  38. ?? ?public void pointcut() {
  39. ?? ?}
  40. ?
  41. ?? ?@Around("pointcut()")
  42. ?? ?public Object around(ProceedingJoinPoint point) {
  43. ?? ??? ?Object result = null;
  44. ?? ??? ?long beginTime = System.currentTimeMillis();
  45. ?? ??? ?try {
  46. ?? ??? ??? ?result = point.proceed();
  47. ?? ??? ?} catch (Throwable e) {
  48. ?? ??? ??? ?e.printStackTrace();
  49. ?? ??? ?}
  50. ?? ??? ?long time = System.currentTimeMillis() - beginTime;
  51. ?? ??? ?saveLog(point, time);
  52. ?? ??? ?return result;
  53. ?? ?}
  54. ?
  55. ?? ?private void saveLog(ProceedingJoinPoint joinPoint, long time) {
  56. ?? ??? ?User user = (User) SecurityUtils.getSubject().getPrincipal();
  57. ?? ??? ?MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  58. ?? ??? ?Method method = signature.getMethod();
  59. ?? ??? ?SysLog log = new SysLog();
  60. ?? ??? ?Log logAnnotation = method.getAnnotation(Log.class);
  61. ?? ??? ?if (logAnnotation != null) {
  62. ?? ??? ??? ?log.setOperation(logAnnotation.value());
  63. ?? ??? ?}
  64. ?? ??? ?String className = joinPoint.getTarget().getClass().getName();
  65. ?? ??? ?String methodName = signature.getName();
  66. ?? ??? ?log.setMethod(className + "." + methodName + "()");
  67. ?? ??? ?Object[] args = joinPoint.getArgs();
  68. ?? ??? ?LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
  69. ?? ??? ?String[] paramNames = u.getParameterNames(method);
  70. ?? ??? ?if (args != null && paramNames != null) {
  71. ?? ??? ??? ?String params = "";
  72. ?? ??? ??? ?for (int i = 0; i < args.length; i++) {
  73. ?? ??? ??? ??? ?params += " ?" + paramNames[i] + ": " + args[i];
  74. ?? ??? ??? ?}
  75. ?? ??? ??? ?log.setParams(params);
  76. ?? ??? ?}
  77. ?? ??? ?HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
  78. ?? ??? ?log.setIp(IPUtils.getIpAddr(request));
  79. ?? ??? ?log.setUsername(user.getUsername());
  80. ?? ??? ?log.setTime(time);
  81. ?? ??? ?log.setCreateTime(new Date());
  82. ?? ??? ?log.setLocation(AddressUtilsBak.getRealAddressByIP(log.getIp(), mapper));
  83. ?? ??? ?this.logService.save(log);
  84. ?? ?}
  85. }

这里的实现类中日志添加的方法中使用的淘宝的获取ip服务,后续会加上去,其实这里面可以随便写一个实现方法,因为我是留工具备份,所以记录的较多

具体的@Aspect、@Pointcut、@Around、@Before、@After等aop相关的注解和参数需要自己去巩固一下知识

4、然后就可以在你想要记录日志的地方使用即可

  1. package com.sysmg.controller;
  2. ?
  3. import java.util.List;
  4. import java.util.Map;
  5. ?
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.ResponseBody;
  10. ?
  11. import com.github.pagehelper.PageHelper;
  12. import com.github.pagehelper.PageInfo;
  13. import com.sysmg.common.annotation.Log;
  14. import com.sysmg.common.domain.QueryRequest;
  15. import com.sysmg.common.domain.ResponseBo;
  16. import com.sysmg.common.util.FileUtils;
  17. ?
  18. @Controller
  19. public class TestController{
  20. ?
  21. ?? ?@Log("规则")
  22. ?? ?@RequestMapping("test")
  23. ?? ?public String index() {
  24. ?? ??? ?return "test";
  25. ?? ?}
  26. }?? ?

大概这样就可以使用了,目前里面缺少aop相关知识的介绍以及获取访问ip的工具类,不过跟本课题关系不大,后续会更上去

到此这篇关于springboot自定义日志注解的实现的文章就介绍到这了,更多相关springboot自定义日志注解内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号