前言
在之前的日志记录的写法中,我们大多是写一个工具类,在这个类里面定义日志保存的方法,然后再controller中执行请求的时候调用即可,虽然调用仅仅一行代码,但是不够友好;所有可以写一个类似于@Controller等的注解,在需要保存日志的方法上面加上一个注解,这样不用在每个都写一端代码;话不多说上代码
1、首先一个log的实体类,这个无关紧要
2、定义一个注解接口
- package com.sysmg.common.annotation;
- ?
- 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)
- public @interface Log {
- ? ? String value() default "";
- }
@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 ""
这个代表是要传递的参数,类似
- @Autowired(required=true)
- ?
- ?
- public @interface Autowired {
- ?
- ?? ?/**
- ?? ? * Declares whether the annotated dependency is required.
- ?? ? * <p>Defaults to {@code true}.
- ?? ? */
- ?? ?boolean required() default true;
- ?
- }
springmvc项目还需要开启切面编程
- <aop:aspectj-autoproxy proxy-target-class="true"/>
springboot默认是开启的
3、定义注解的实现类,也就是这个注解要做什么事
- package com.sysmg.common.aspect;
- ?
- import java.lang.reflect.Method;
- import java.util.Date;
- ?
- import javax.servlet.http.HttpServletRequest;
- ?
- import org.apache.shiro.SecurityUtils;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
- import org.springframework.stereotype.Component;
- ?
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.sysmg.common.annotation.Log;
- import com.sysmg.common.util.AddressUtilsBak;
- import com.sysmg.common.util.HttpContextUtils;
- import com.sysmg.common.util.IPUtils;
- import com.sysmg.system.domain.SysLog;
- import com.sysmg.system.domain.User;
- import com.sysmg.system.service.LogService;
- ?
- @Aspect
- @Component
- public class LogAspect {
- ?
- ?? ?@Autowired
- ?? ?private LogService logService;
- ?
- ?? ?@Autowired
- ?? ?ObjectMapper mapper;
- ?
- ?? ?@Pointcut("@annotation(com.sysmg.common.annotation.Log)")
- ?? ?public void pointcut() {
- ?? ?}
- ?
- ?? ?@Around("pointcut()")
- ?? ?public Object around(ProceedingJoinPoint point) {
- ?? ??? ?Object result = null;
- ?? ??? ?long beginTime = System.currentTimeMillis();
- ?? ??? ?try {
- ?? ??? ??? ?result = point.proceed();
- ?? ??? ?} catch (Throwable e) {
- ?? ??? ??? ?e.printStackTrace();
- ?? ??? ?}
- ?? ??? ?long time = System.currentTimeMillis() - beginTime;
- ?? ??? ?saveLog(point, time);
- ?? ??? ?return result;
- ?? ?}
- ?
- ?? ?private void saveLog(ProceedingJoinPoint joinPoint, long time) {
- ?? ??? ?User user = (User) SecurityUtils.getSubject().getPrincipal();
- ?? ??? ?MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- ?? ??? ?Method method = signature.getMethod();
- ?? ??? ?SysLog log = new SysLog();
- ?? ??? ?Log logAnnotation = method.getAnnotation(Log.class);
- ?? ??? ?if (logAnnotation != null) {
- ?? ??? ??? ?log.setOperation(logAnnotation.value());
- ?? ??? ?}
- ?? ??? ?String className = joinPoint.getTarget().getClass().getName();
- ?? ??? ?String methodName = signature.getName();
- ?? ??? ?log.setMethod(className + "." + methodName + "()");
- ?? ??? ?Object[] args = joinPoint.getArgs();
- ?? ??? ?LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
- ?? ??? ?String[] paramNames = u.getParameterNames(method);
- ?? ??? ?if (args != null && paramNames != null) {
- ?? ??? ??? ?String params = "";
- ?? ??? ??? ?for (int i = 0; i < args.length; i++) {
- ?? ??? ??? ??? ?params += " ?" + paramNames[i] + ": " + args[i];
- ?? ??? ??? ?}
- ?? ??? ??? ?log.setParams(params);
- ?? ??? ?}
- ?? ??? ?HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
- ?? ??? ?log.setIp(IPUtils.getIpAddr(request));
- ?? ??? ?log.setUsername(user.getUsername());
- ?? ??? ?log.setTime(time);
- ?? ??? ?log.setCreateTime(new Date());
- ?? ??? ?log.setLocation(AddressUtilsBak.getRealAddressByIP(log.getIp(), mapper));
- ?? ??? ?this.logService.save(log);
- ?? ?}
- }
这里的实现类中日志添加的方法中使用的淘宝的获取ip服务,后续会加上去,其实这里面可以随便写一个实现方法,因为我是留工具备份,所以记录的较多
具体的@Aspect、@Pointcut、@Around、@Before、@After等aop相关的注解和参数需要自己去巩固一下知识
4、然后就可以在你想要记录日志的地方使用即可
- package com.sysmg.controller;
- ?
- import java.util.List;
- import java.util.Map;
- ?
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- ?
- import com.github.pagehelper.PageHelper;
- import com.github.pagehelper.PageInfo;
- import com.sysmg.common.annotation.Log;
- import com.sysmg.common.domain.QueryRequest;
- import com.sysmg.common.domain.ResponseBo;
- import com.sysmg.common.util.FileUtils;
- ?
- @Controller
- public class TestController{
- ?
- ?? ?@Log("规则")
- ?? ?@RequestMapping("test")
- ?? ?public String index() {
- ?? ??? ?return "test";
- ?? ?}
- }?? ?
大概这样就可以使用了,目前里面缺少aop相关知识的介绍以及获取访问ip的工具类,不过跟本课题关系不大,后续会更上去
到此这篇关于springboot自定义日志注解的实现的文章就介绍到这了,更多相关springboot自定义日志注解内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!