SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见。
程序员每天的CV 与 板砖,也要知其所以然,本系列课程可以帮助初学者学习 SpringBooot 项目开发 与 SpringCloud 微服务系列项目开发
我的需求是 用户修改了基本信息,管理员从管理后台可以查询到相关的记录。
import java.lang.annotation.*;/*** 系统日志注解* * @author 早起的年轻人* @date 2023年3月8日*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {String value() default "";
}
@Retention修饰注解,用来表示注解的生命周期,生命周期的长短取决于@Retention的属性RetentionPolicy指定的值
RetentionPolicy.SOURCE 表示注解只保留在源文件,当java文件编译成class文件,就会消失 源文件 只是做一些检查性的操作,
RetentionPolicy.CLASS 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期 class文件(默认) 要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife)
RetentionPolicy.RUNTIME 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 运行时也存在 需要在运行时去动态获取注解信息
@Target 说明了Annotation所修饰的对象范围
添加依赖如下,版本要对应自己的 SpringBoot 版本,我这使用的是 2.7.9 版本
org.springframework.boot spring-boot-starter-aop 2.7.9
AOP:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。而@Aspect 就是把一个类定义为切面供容器读取。
@Aspect
@Component
public class SysLogAspect {@Autowiredprivate SysLogService sysLogService;/*** 自己定义的注解*/@Pointcut("@annotation(com.biglead.demo.anno.SysLog)")public void logPointCut() {}@Around("logPointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {long beginTime = System.currentTimeMillis();//执行方法Object result = point.proceed();//执行时长(毫秒)long time = System.currentTimeMillis() - beginTime;//保存日志saveSysLog(point, time);return result;}private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();SysLogEntity sysLog = new SysLogEntity();SysLog syslog = method.getAnnotation(SysLog.class);if (syslog != null) {//注解上的描述sysLog.setOperation(syslog.value());}//请求的方法名String className = joinPoint.getTarget().getClass().getName();String methodName = signature.getName();sysLog.setMethod(className + "." + methodName + "()");//请求的参数Object[] args = joinPoint.getArgs();try {String params = new Gson().toJson(args[0]);if (params.length() > 1000) {params = params.substring(0, 500);}sysLog.setParams(params);} catch (Exception e) {}//获取requestHttpServletRequest request = HttpContextUtils.getHttpServletRequest();//设置IP地址sysLog.setIp(IPUtils.getIpAddr(request));//用户名是用户IDString username = request.getHeader("userId");sysLog.setUsername(username);sysLog.setTime(time);sysLog.setCreateDate(new Date());//保存系统日志sysLogService.save(sysLog);}
}
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** 系统日志* * @author 早起的年轻人* @date 2012-03-08 */
@TableName("sys_log")
@Data
@AllArgsConstructor
public class SysLogEntity implements Serializable {private static final long serialVersionUID = 1L;@TableIdprivate Long id;//用户名private String username;//用户操作private String operation;//请求方法private String method;//请求参数private String params;//执行时长(毫秒)private Long time;//IP地址private String ip;//创建时间private Date createDate;
}
public interface SysLogService extends IService {/*** 管理后台 分页查询日志* @return*/Page queryPage(Integer pageInex, Integer pageSize);
}
@Service("sysLogService")
public class SysLogServiceImpl extends ServiceImpl implements SysLogService {@Overridepublic Page queryPage(Integer pageInex, Integer pageSize) {Page page = this.page(new Page<>(pageInex, pageSize), new QueryWrapper<>());return page;}
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.biglead.demo.pojo.SysLogEntity;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface SysLogDao extends BaseMapper {}
直接在 Controller 的方法上添加 @SysLog 注解就可以实现自动记录日志的行为
@Api(tags="用户模块")
@RestController
@RequestMapping("user")
public class UserController {@SysLog("修改用户信息")@PostMapping(value="/update")@ApiOperation(value = "修改用户信息")public Object updateUser(@RequestBody UserInfo userInfo) {return userService.updateUser(userInfo);}
}
项目源码在这里 :https://gitee.com/android.long/spring-boot-study/tree/master/biglead-api-13-quartz
有兴趣可以关注一下公众号:biglead