[JavaWeb]【十二】web后端开发-事务管理AOP

目录

一、事务管理

1.1 事务回顾

1.2 Spring事务管理

1.2.1 案例

 1.2.1.1 EmpMapper新增deleteByDeptId方法

 1.2.1.2 DeptServiceImpl 

 1.2.1.3 启动服务-测试

 1.2.2 模拟异常

1.2.3  分析问题

 1.2.4 Spring事务管理(一般用在类似多次delete)

 1.2.4.1 开启事务开关application.yml

1.2.4.2  DeptServiceImpl 

1.2.4.3 启动服务-测试

1.3 事务进阶

1.3.1 rollbackFor 回滚

1.3.2 propagation 传播行为

 1.3.2 案例

 1.3.2.1 创建部门日志表dept_log

 1.3.2.2 新建实体类DeptLog

1.3.2.3 DeptLogService接口

1.3.2.4 DeptLogServiceImpl实现类

1.3.2.5 DeptLogMapper

1.3.2.6 DeptServiceImpl

 1.3.2.7 启动服务-测试

 1.3.3 总结

1.4 扩展插件Grep Console

二、AOP基础

2.1 AOP概述

2.2 AOP 快速入门

 2.2.1 AOP依赖

2.2.2 TimeAspect 类

2.2.3 启动服务-测试

 2.2.4 AOP场景&优势

2.3 核心概念 

2.4 AOP 执行流程

2.5 总结

 三、AOP 进阶

3.1 通知类型

3.2 通知顺序

3.3 切入表达式

3.3.1 execution表达式 

3.3.2 annotation表达式

 3.3.3 总结

3.4 连接点

四、AOP案例-记录操作日志

 4.1 思路

4.2  配置起步依赖AOP

4.3 创建数据库表operate_log

 4.4 实体类OperateLog

 4.5 接口OperateLogMapper

4.6 新建一个自定义的Log注解

4.7 定义一个切面类LogAspect 

4.8 Deptcontroller 为新增、修改、删除添加@Log

4.9 EmpController 为新增、修改、删除添加@Log

4.10 启动服务-测试


前言:Spring 事务管理是 Spring Framework 提供的一种方便的事务管理方式,它主要解决了应用程序中多数据源跨库操作时的事务管理问题。Spring 事务管理的原理是使用代理模式,为目标对象动态地创建代理对象,代理对象拦截目标对象的方法,实现事务的开启、提交和回滚等操作。在 Spring 中,使用 @Transactional 注解来标记需要进行事务管理的方法,通过配置数据源和事务管理器,Spring 可以自动为这些方法创建事务并进行管理。在配置事务时,可以指定事务的隔离级别、传播行为、只读属性等选项,以满足不同的业务需求。Spring 事务管理的好处是简化了事务管理的流程,减少了代码的重复性,提高了代码的可读性和可维护性,并且在多线程环境下可以保证数据的一致性。

一、事务管理

1.1 事务回顾

1.2 Spring事务管理

1.2.1 案例

 1.2.1.1 EmpMapper新增deleteByDeptId方法

package com.runa.mapper;import com.runa.pojo.Emp;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.time.LocalDate;
import java.util.List;/*** 员工管理*/
@Mapper
public interface EmpMapper {/*** 查询总记录数* @return*/
//    @Select("select count(*) from emp")
//    public Long count();/*** 分页查询 获取列表数据* @param start* @param pageSize* @return*/
//    @Select("select * from emp limit #{start}, #{pageSize}")
//    public List<Emp> page(Integer start, Integer pageSize);/*** 使用pagehelper的员工信息查询* @return*/
//    @Select("select * from emp")
//    public List<Emp> list();/*** 使用pagehelper的员工信息查询(带条件)--动态sql* 使用xml注解sql* @return*/public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);/*** 批量删除员工* @param ids*/void delete(List<Integer> ids);/*** 新增员工* @param emp*/@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +" values(#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")void insert(Emp emp);/*** 根据id查询员工* @param id* @return*/@Select("select * from emp where id = #{id}")Emp getByID(Integer id);/*** 修改员工* @param emp*/void update(Emp emp);/*** 登录* @param emp* @return*/@Select("select * from emp where username = #{username} and password = #{password}")Emp getByUsernameAndPassword(Emp emp);/*** 根据部门dept_id删除该部门下的员工数据*/@Select("delete  from emp where dept_id = #{deptId}")void deleteByDeptId(Integer deptId);
}

 1.2.1.2 DeptServiceImpl 

package com.runa.service.impl;import com.runa.mapper.DeptMapper;
import com.runa.mapper.EmpMapper;
import com.runa.pojo.Dept;
import com.runa.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;@Service
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;@Autowiredprivate EmpMapper empMapper;/*** 查询部门* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根据ID删除部门* @param id*/@Overridepublic void delete(Integer id) {// 1 根据ID 删除部门deptMapper.deleteById(id);//2 根据部门id删除该部门下的员工empMapper.deleteByDeptId(id);}/*** 新增部门* @param dept*/@Overridepublic void add(Dept dept) {dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.insert(dept);}/*** 根据id查询部门* @param id* @return*/@Overridepublic Dept getById(Integer id) {return deptMapper.getById(id);}/*** 编辑部门* @param dept*/@Overridepublic void update(Dept dept) {dept.setUpdateTime(LocalDateTime.now());deptMapper.update(dept);}}

 1.2.1.3 启动服务-测试

 

 1.2.2 模拟异常

1.2.3  分析问题

 1.2.4 Spring事务管理(一般用在类似多次delete)

 1.2.4.1 开启事务开关application.yml

#spring事务管理日志
logging:level:org.springframework.jdbc.support.JdbcTransactionManager: debug

1.2.4.2  DeptServiceImpl 

package com.runa.service.impl;import com.runa.mapper.DeptMapper;
import com.runa.mapper.EmpMapper;
import com.runa.pojo.Dept;
import com.runa.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.time.LocalDateTime;
import java.util.List;@Service
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;@Autowiredprivate EmpMapper empMapper;/*** 查询部门* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根据ID删除部门* @param id*/@Transactional //spring 事务管理@Overridepublic void delete(Integer id) {// 1 根据ID 删除部门deptMapper.deleteById(id);//2 根据部门id删除该部门下的员工empMapper.deleteByDeptId(id);}/*** 新增部门* @param dept*/@Overridepublic void add(Dept dept) {dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.insert(dept);}/*** 根据id查询部门* @param id* @return*/@Overridepublic Dept getById(Integer id) {return deptMapper.getById(id);}/*** 编辑部门* @param dept*/@Overridepublic void update(Dept dept) {dept.setUpdateTime(LocalDateTime.now());deptMapper.update(dept);}}

1.2.4.3 启动服务-测试

 

1.3 事务进阶

1.3.1 rollbackFor 回滚

package com.runa.service.impl;import com.runa.mapper.DeptMapper;
import com.runa.mapper.EmpMapper;
import com.runa.pojo.Dept;
import com.runa.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.time.LocalDateTime;
import java.util.List;@Service
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;@Autowiredprivate EmpMapper empMapper;/*** 查询部门* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根据ID删除部门* @param id*/@Transactional(rollbackFor = Exception.class) //spring 事务管理  .所有异常回滚:rollbackFor = Exception.class@Overridepublic void delete(Integer id) {// 1 根据ID 删除部门deptMapper.deleteById(id);//2 根据部门id删除该部门下的员工empMapper.deleteByDeptId(id);}/*** 新增部门* @param dept*/@Overridepublic void add(Dept dept) {dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.insert(dept);}/*** 根据id查询部门* @param id* @return*/@Overridepublic Dept getById(Integer id) {return deptMapper.getById(id);}/*** 编辑部门* @param dept*/@Overridepublic void update(Dept dept) {dept.setUpdateTime(LocalDateTime.now());deptMapper.update(dept);}}

  

1.3.2 propagation 传播行为

 

 1.3.2 案例

 1.3.2.1 创建部门日志表dept_log

create table dept_log(id int auto_increment comment '主键ID' primary key,create_time datetime null comment '操作时间',description varchar(300) null comment '操作描述'
)comment '部门操作日志表';

 1.3.2.2 新建实体类DeptLog

package com.runa.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDateTime;@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptLog {private Integer id;private LocalDateTime createTime;private String description;
}

1.3.2.3 DeptLogService接口

package com.runa.service;import com.runa.pojo.DeptLog;public interface DeptLogService {void insert(DeptLog deptLog);
}

1.3.2.4 DeptLogServiceImpl实现类

package com.runa.service.impl;import com.runa.mapper.DeptLogMapper;
import com.runa.mapper.DeptLogMapper;
import com.runa.pojo.DeptLog;
import com.runa.service.DeptLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class DeptLogServiceImpl implements DeptLogService {@Autowiredprivate DeptLogMapper deptLogMapper;@Transactional(propagation = Propagation.REQUIRES_NEW)@Overridepublic void insert(DeptLog deptLog) {deptLogMapper.insert(deptLog);}
}

1.3.2.5 DeptLogMapper

package com.runa.mapper;import com.runa.pojo.DeptLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface DeptLogMapper {@Insert("insert into dept_log(create_time,description) values(#{createTime},#{description})")void insert(DeptLog log);}

1.3.2.6 DeptServiceImpl

package com.runa.service.impl;import com.runa.mapper.DeptLogMapper;
import com.runa.mapper.DeptMapper;
import com.runa.mapper.EmpMapper;
import com.runa.pojo.Dept;
import com.runa.pojo.DeptLog;
import com.runa.service.DeptLogService;
import com.runa.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.time.LocalDateTime;
import java.util.List;@Service
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;@Autowiredprivate EmpMapper empMapper;
//  没有使用下面的使用上面的是因为事务的原因
//    @Autowired  
//    private DeptLogMapper deptLogMapper;@Autowiredprivate DeptLogService deptLogService;/*** 查询部门* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根据ID删除部门* @param id*/@Transactional(rollbackFor = Exception.class) //spring 事务管理  .所有异常回滚:rollbackFor = Exception.class@Overridepublic void delete(Integer id) {try {// 1 根据ID 删除部门deptMapper.deleteById(id);// 模拟异常int i =  1/0;//2 根据部门id删除该部门下的员工empMapper.deleteByDeptId(id);} finally {DeptLog deptLog = new DeptLog();deptLog.setCreateTime(LocalDateTime.now());deptLog.setDescription("执行了解散部门的操作,此次解散的是" + id + "号部门");deptLogService.insert(deptLog);//没有使用下面的使用上面的是因为事务的原因
//            deptLogMapper.insert(deptLog);}}/*** 新增部门* @param dept*/@Overridepublic void add(Dept dept) {dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.insert(dept);}/*** 根据id查询部门* @param id* @return*/@Overridepublic Dept getById(Integer id) {return deptMapper.getById(id);}/*** 编辑部门* @param dept*/@Overridepublic void update(Dept dept) {dept.setUpdateTime(LocalDateTime.now());deptMapper.update(dept);}}

 1.3.2.7 启动服务-测试

 1.3.3 总结

1.4 扩展插件Grep Console

可以为日志设置颜色 

二、AOP基础

2.1 AOP概述

2.2 AOP 快速入门

 2.2.1 AOP依赖

    <!--AOP--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>3.1.2</version></dependency>

2.2.2 TimeAspect 类

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Slf4j
@Component
@Aspect //AOP类
public class TimeAspect {//@Around("execution(* com.runa.service.impl.DeptServiceImpl.*(..))") //切入点表达式
//    @Around("com.runa.aop.MyAspect1.pt()")@Around("execution(* com.runa.service.*.*(..))") //切入点表达式public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {//1. 记录开始时间long begin = System.currentTimeMillis();//2. 调用原始方法运行Object result = joinPoint.proceed();//3. 记录结束时间, 计算方法执行耗时long end = System.currentTimeMillis();log.info(joinPoint.getSignature()+"方法执行耗时: {}ms", end-begin);return result;}}

2.2.3 启动服务-测试

 2.2.4 AOP场景&优势

2.3 核心概念 

2.4 AOP 执行流程

2.5 总结

 三、AOP 进阶

3.1 通知类型

 

 

 

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Slf4j
@Component
@Aspect   //demo,运行项目要注释
public class MyAspect1Delete {@Pointcut("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void pt(){}@Before("pt()")public void before(){log.info("before ...");}@Around("pt()")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {log.info("around before ...");//调用目标对象的原始方法执行Object result = proceedingJoinPoint.proceed();log.info("around after ...");return result;}@After("pt()")public void after(){log.info("after ...");}@AfterReturning("pt()")public void afterReturning(){log.info("afterReturning ...");}@AfterThrowing("pt()")public void afterThrowing(){log.info("afterThrowing ...");}
}

 

3.2 通知顺序

 

 

 

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Order(2)
@Slf4j
@Component
@Aspect //为了实验,实际是要注释的
public class MyAspect2Delete {@Before("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void before(){log.info("before ...2");}@After("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void after(){log.info("after ...2");}}
package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Order(3)
@Slf4j
@Component
@Aspect //为了实验,实际是要注释的
public class MyAspect3Delete {@Before("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void before(){log.info("before ...3");}@After("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void after(){log.info("after ...3");}}

 

 

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Order(1)
@Slf4j
@Component
@Aspect //为了实验,实际是要注释的
public class MyAspect4Delete {@Before("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void before(){log.info("before ...4");}@After("execution(* com.runa.service.impl.DeptServiceImpl.*(..))")public void after(){log.info("after ...4");}}

 

3.3 切入表达式

3.3.1 execution表达式 

 

 

 

 

 

 

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;//切面类
@Slf4j
@Aspect //项目运行注释掉
@Component
public class MyAspect6Delete {//@Pointcut("execution(public void com.runa.service.impl.DeptServiceImpl.delete(java.lang.Integer))")//@Pointcut("execution(void com.runa.service.impl.DeptServiceImpl.delete(java.lang.Integer))")//@Pointcut("execution(void delete(java.lang.Integer))") //包名.类名不建议省略//@Pointcut("execution(void com.runa.service.DeptService.delete(java.lang.Integer))")//@Pointcut("execution(void com.runa.service.DeptService.*(java.lang.Integer))")//@Pointcut("execution(* com.*.service.DeptService.*(*))")//@Pointcut("execution(* com.runa.service.*Service.delete*(*))")//@Pointcut("execution(* com.runa.service.DeptService.*(..))")//@Pointcut("execution(* com..DeptService.*(..))")//@Pointcut("execution(* com..*.*(..))")//@Pointcut("execution(* *(..))") //慎用@Pointcut("execution(* com.runa.service.DeptService.list()) || " +"execution(* com.runa.service.DeptService.delete(java.lang.Integer))")private void pt(){}@Before("pt()")public void before(){log.info("MyAspect6 ... before ...");}}

3.3.2 annotation表达式

 

 

package com.runa.aop;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)  //运行有效
@Target(ElementType.METHOD)
public @interface MyDeleteLog {
}

 

 

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;//切面类
@Slf4j
@Aspect //为了实验,实际是要注释的
@Component
public class MyAspect7Delete {//匹配DeptServiceImpl中的 list() 和 delete(Integer id)方法//@Pointcut("execution(* com.runa.service.DeptService.list()) || execution(* com.itheima.service.DeptService.delete(java.lang.Integer))")@Pointcut("@annotation(com.runa.aop.MyDeleteLog)")private void pt(){}@Before("pt()")public void before(){log.info("MyAspect7 ... before ...");}}

 3.3.3 总结

 

3.4 连接点

 

 

 

 

package com.runa.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.util.Arrays;//切面类
@Slf4j
//@Aspect //为了实验,实际是要注释的
@Component
public class MyAspect8Delete {@Pointcut("execution(* com.runa.service.DeptService.*(..))")private void pt(){}@Before("pt()")public void before(JoinPoint joinPoint){log.info("MyAspect8 ... before ...");}@Around("pt()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {log.info("MyAspect8 around before ...");//1. 获取 目标对象的类名 .String className = joinPoint.getTarget().getClass().getName();log.info("目标对象的类名:{}", className);//2. 获取 目标方法的方法名 .String methodName = joinPoint.getSignature().getName();log.info("目标方法的方法名: {}",methodName);//3. 获取 目标方法运行时传入的参数 .Object[] args = joinPoint.getArgs();log.info("目标方法运行时传入的参数: {}", Arrays.toString(args));//4. 放行 目标方法执行 .Object result = joinPoint.proceed();//5. 获取 目标方法运行的返回值 .log.info("目标方法运行的返回值: {}",result);log.info("MyAspect8 around after ...");return result;}
}

 

 

四、AOP案例-记录操作日志

 

 4.1 思路

 

 

4.2  配置起步依赖AOP

4.3 创建数据库表operate_log

-- 操作日志表
create table operate_log(id int unsigned primary key auto_increment comment 'ID',operate_user int unsigned comment '操作人ID',operate_time datetime comment '操作时间',class_name varchar(100) comment '操作的类名',method_name varchar(100) comment '操作的方法名',method_params varchar(1000) comment '方法参数',return_value varchar(2000) comment '返回值',cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';

 4.4 实体类OperateLog

  

package com.runa.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDateTime;@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {private Integer id; //IDprivate Integer operateUser; //操作人IDprivate LocalDateTime operateTime; //操作时间private String className; //操作类名private String methodName; //操作方法名private String methodParams; //操作方法参数private String returnValue; //操作方法返回值private Long costTime; //操作耗时
}

 4.5 接口OperateLogMapper

 

package com.runa.mapper;import com.runa.pojo.OperateLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface OperateLogMapper {//插入日志数据@Insert("insert into operate_log (operate_user, operate_time, class_name, method_name, method_params, return_value, cost_time) " +"values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")public void insert(OperateLog log);}

4.6 新建一个自定义的Log注解

 

 

package com.runa.anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME) //运行时生效
@Target(ElementType.METHOD)  //作用在方法上
public @interface Log {
}

4.7 定义一个切面类LogAspect 

package com.runa.aop;import com.alibaba.fastjson.JSONObject;
import com.runa.mapper.OperateLogMapper;
import com.runa.pojo.OperateLog;
import com.runa.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;@Slf4j
@Component
@Aspect  //切面类
public class LogAspect {@Autowiredprivate HttpServletRequest request;@Autowired  //注入private OperateLogMapper operateLogMapper;@Around("@annotation(com.runa.anno.Log)")  //环绕通知public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {// 操作人ID  - 当前登录员工ID// 获取请求头中的jwt令牌,解析令牌String jwt = request.getHeader("token");Claims claims = JwtUtils.parseJWT(jwt);Integer operateUser = (Integer) claims.get("id");// 操作时间LocalDateTime operateTime = LocalDateTime.now();// 操作类名String className = joinPoint.getTarget().getClass().getName();// 操作方法名String methodName = joinPoint.getSignature().getName();// 操作方法参数Object[] args = joinPoint.getArgs();String methodParams = Arrays.toString(args);long begin = System.currentTimeMillis();//调用原始目标方法运行Object result = joinPoint.proceed();long end = System.currentTimeMillis();// 方法返回值String returnValue = JSONObject.toJSONString(result);// 操作耗时Long costTime = end - begin;// 记录操作日志OperateLog operateLog = new OperateLog(null, operateUser, operateTime, className, methodName, methodParams, returnValue, costTime);operateLogMapper.insert(operateLog);log.info("AOP 记录操作日志:{}",operateLog);return result;}
}

 

4.8 Deptcontroller 为新增、修改、删除添加@Log

package com.runa.controller;import com.runa.anno.Log;
import com.runa.pojo.Dept;
import com.runa.pojo.Result;
import com.runa.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** 部门管理Controller*/
@Slf4j
@RestController
@RequestMapping("/depts")
public class Deptcontroller {@Autowiredprivate DeptService deptService;/*** 查询部门数据* @return*/
//    private static Logger log = LoggerFactory.getLogger(Deptcontroller.class);
//    @RequestMapping(value = "/depts", method = RequestMethod.GET)  //指定请求方式为GET@GetMapping  //public Result list(){log.info("查询全部部门数据");// 调用 service查询部门数据List<Dept> deptList = deptService.list();return Result.success(deptList);}/*** 删除部门* @return*/@Log@DeleteMapping("/{id}")public Result delete(@PathVariable Integer id){log.info("根据id删除部门:{}", id);//   调用service删除部门deptService.delete(id);return Result.success();}/*** 添加部门* @return*/@Log@PostMappingpublic Result add(@RequestBody Dept dept){log.info("新增部门:{}",dept);// //   调用service新增部门deptService.add(dept);return Result.success();}/*** 根据ID查询部门* @return*/@GetMapping("/{id}")public Result getById(@PathVariable Integer id){log.info("根据id查询部门:{}", id);//   调用service查询部门Dept dept = deptService.getById(id);return Result.success(dept);}/*** 编辑部门* @return*/@Log@PutMappingpublic Result update(@RequestBody Dept dept){log.info("编辑部门:{}==={}", dept.getId(),dept.getName());//   调用service编辑部门deptService.update(dept);return Result.success();}
}

4.9 EmpController 为新增、修改、删除添加@Log

package com.runa.controller;import com.runa.anno.Log;
import com.runa.pojo.Emp;
import com.runa.pojo.PageBean;
import com.runa.pojo.Result;import com.runa.service.EmpService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;import java.time.LocalDate;
import java.util.List;/*** 员工管理Controller*/
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {@Autowiredprivate EmpService empService;/*** 员工数据查询列表 ,  不带条件* @param page* @param pageSize* @return*///    @GetMapping
//    public Result page(@RequestParam(defaultValue = "1") Integer page,
//                       @RequestParam(defaultValue = "10") Integer pageSize){
//        log.info("分页查询,参数:开始页 {}, 每页显示:{}", page, pageSize);
//        // 调用Service方法进行查询
//        PageBean pageBean = empService.page(page,pageSize);
//
//        return Result.success(pageBean);
//    }/*** 员工数据查询列表 ,  带条件组合查询* @param page* @param pageSize* @param name* @param gender* @param begin* @param end* @return*/@GetMappingpublic Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize,String name, Short gender,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd")  LocalDate end){log.info("分页查询,参数:开始页 {}, 每页显示:{},姓名:{},性别:{}, 开始日期:{},结束日期:{}", page, pageSize, name, gender, begin, end);// 调用Service方法进行查询PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);return Result.success(pageBean);}/*** 批量删除员工* @param ids* @return*/@Log@DeleteMapping("/{ids}")public Result delete(@PathVariable List<Integer> ids){log.info("批量删除的操作,删除对象为:{}",ids);empService.delete(ids);return Result.success();}/*** 新增员工* @param emp* @return*/@Log@PostMappingpublic Result save(@RequestBody Emp emp){log.info("新增员工emp: {}",emp);empService.save(emp);return Result.success();}/*** 根据id查询员工* @param id* @return*/@GetMapping("/{id}")public Result getById(@PathVariable Integer id){log.info("根据ID查询员工信息:{}",id);Emp emp = empService.getById(id);return Result.success(emp);}/*** 修改员工* @param emp* @return*/@Log@PutMappingpublic Result update(@RequestBody Emp emp){log.info("更新员工: {}",emp);empService.update(emp);return Result.success();}}

4.10 启动服务-测试

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/105431.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

现学现用,人脸识别让会议签到更轻松!

会议签到作为组织和管理任何规模的会议、研讨会或活动的重要环节&#xff0c;在确保参会人员准确到场的同时&#xff0c;也直接影响了会议的整体效率和顺利进行。 传统的纸质签到方式存在着繁琐、时间消耗较多等问题&#xff0c;而随着科技的不断发展&#xff0c;智能化会议签到…

Qt --- QTimer

在Qt开发界面的时候&#xff0c;非常多的时候都得使用定时器&#xff0c;定时器具体可以干什么呢&#xff1f;比如&#xff1a;控制时钟、定时改变样式、改变进度等。。。说到这里&#xff0c;经常使用QQ&#xff0c;而不同的时段都会显示不同的背景&#xff0c;我认为如果用Qt…

人工智能如何颠覆和改变信息安全格局

当谈及网络信息安全领域&#xff0c;人工智能&#xff08;AI&#xff09;正扮演着关键的角色。其作用是分析庞大的风险数据&#xff0c;以及企业信息系统中不同威胁之间的关联&#xff0c;从而识别出全新类型的攻击方式。这一过程的成果为各类网络安全团队提供了重要情报&#…

PostgreSQL-研究学习-介绍与安装

PostgreSQL-预研 是个很厉害的数据库的样子 ψ(*&#xff40;ー)ψ 官方文档&#xff1a;http://www.postgres.cn/docs/12/ 总的结论和备注 PgSQL 支持对JSON的支持很强大&#xff0c;以及提供了很多数学几何相关的数据类型【例&#xff1a;点&#xff0c;线条&#xff0c;几何…

FastJson在Java后端方面解析使用(二)

​ JSON现在常用来做前后端数据交互&#xff0c;两个蝴蝶飞只是简单的对JSON做一下讲解和简单使用。关于JSON,我还了解的远远不够。由于本人经验有限&#xff0c;嘴皮子不溜&#xff0c;所以学术性&#xff0c;概念性&#xff0c;底层性的知识点暂时不做介绍。文章中有错误之处…

爬虫逆向实战(二十)--某99网站登录

一、数据接口分析 主页地址&#xff1a;某99网站 1、抓包 通过抓包可以发现登录接口是AC_userlogin 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”可以发现txtPassword和aws是加密参数 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 无…

SSL/TLS协议的概念、工作原理、作用以及注意事项

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、SSL/TLS协议的基本概念 二、SSL/TLS的工作…

抖音短视频seo矩阵系统源代码技术开发方案分享

一、 功能结构设计 1. 视频管理&#xff1a;对于不同平台&#xff0c;不同账号&#xff0c;不同格式&#xff0c;不同内容短视频进行管理&#xff0c;素材分组等&#xff0c;实现多资源数据汇和统一管理 2. 数据挖掘分析&#xff1a;通过数据挖掘和数据分析&#xff0c;提供数…

Apache Hudi初探(二)(与flink的结合)--flink写hudi的操作(JobManager端的提交操作)

背景 在Apache Hudi初探(一)(与flink的结合)中&#xff0c;我们提到了Pipelines.hoodieStreamWrite 写hudi文件,这个操作真正写hudi是在Pipelines.hoodieStreamWrite方法下的transform(opName("stream_write", conf), TypeInformation.of(Object.class), operatorFa…

NVIDIA vGPU License许可服务器高可用全套部署秘籍

第1章 前言 近期遇到比较多的场景使用vGPU&#xff0c;比如Citrix 3D场景、Horizon 3D场景&#xff0c;还有AI等&#xff0c;都需要使用显卡设计研发等&#xff0c;此时许可服务器尤为重要&#xff0c;许可断掉会出现掉帧等情况&#xff0c;我们此次教大家部署HA许可服务器。 …

爬虫异常处理:异常捕获与容错机制设计

作为一名专业的爬虫程序员&#xff0c;每天使用爬虫IP面对各种异常情况是我们每天都会遇到的事情。 在爬取数据的过程中&#xff0c;我们经常会遇到网络错误、页面结构变化、被反爬虫机制拦截等问题。在这篇文章中&#xff0c;我将和大家分享一些关于如何处理爬虫异常情况的经…

怎么制作sip网络寻呼话筒,sip任意呼叫主机,

怎么制作sip网络寻呼话筒&#xff0c;sip任意呼叫主机&#xff0c; 所需材料一&#xff1a;SV-2103VP sip网络音频模块 功能如下&#xff1a; SV-2101VP/ SV-2103VP使用了AT32F437VGT7处理器构架加专业的双向音频Codec编解码器&#xff0c; 处理器负责数据的传输&#xff0c…

【李群李代数】李群控制器(lie-group-controllers)介绍——控制 SO(3) 空间中的系统的比例控制器Demo...

李群控制器SO(3)测试 测试代码是一个用于控制 SO(3) 空间中的系统的比例控制器。它通过计算控制策略来使当前状态逼近期望状态。该控制器使用比例增益 kp 进行参数化&#xff0c;然后进行一系列迭代以更新系统状态&#xff0c;最终检查状态误差是否小于给定的阈值。这个控制器用…

Checkstyle安装、使用

Checkstyle简介 Checkstyle是SourceForge下的一个项目&#xff0c;官网&#xff1a; https://checkstyle.sourceforge.io/ 在官网有详细的说明。 Checkstyle是一个开发工具&#xff0c;可以帮助开发者自动检查java代码是否遵循编程规范&#xff0c;将开发者从枯燥繁琐的手工…

ArcGIS Serve Windows下用户密码变更导致Server服务无法启动问题

问题&#xff1a; 因未知原因Windows下的Server安装账户密码变更&#xff0c;但是又忘记了密码&#xff0c;导致&#xff0c;Server服务启动失败&#xff0c;错误1069&#xff1a; 解决方法&#xff1a; 在账户管理界面&#xff0c;重置对应的arcgis账户的密码&#xff0c;…

VUE之jspreadsheet电子excel表格动态高度设置

问题&#xff1a;excel电子表格在不同屏幕大小下横向滚动条会被遮挡 排查原因&#xff1a;由于excel高度固定导致 解决方法&#xff1a;设计页面较多&#xff0c;所以封装公共方法 步骤&#xff1a; 1.使用混入封装动态设置excel高度方法&#xff1a; const mixinJexcel …

“分布式”与“集群”初学者的技术总结

一、“分布式”与“集群”的解释&#xff1a; 分布式&#xff1a;把一个囊肿的系统分成无数个单独可运行的功能模块 集群&#xff1a; 把相同的项目复制进行多次部署&#xff08;可以是一台服务器多次部署&#xff0c;例如使用8080部署一个&#xff0c;8081部署一个&#xff0c…

Unity 物体的运动之跟随鼠标

你想让鼠标点击哪里&#xff0c;你的运动的对象就运动到哪里吗&#xff1f; Please follow me ! 首先&#xff0c;你要先添加一个Plane ,以及你的围墙&#xff0c;你的移动的物体 想要实现跟随鼠标移动&#xff0c;我们先创建一个脚本 using System.Collections; using Syst…

html学习第2篇---标签(1)

html学习第2篇---标签 1、标题标签h1---h62、段落标签p3、换行标签br4、文本格式化标签5、div标签和span标签6、图像标签img6.1、图像属性6.2、相对路径、绝对路径 7、超链接标签a7.1、属性7.2、分类 8、注释标签和特殊字符8.1、注释8.2、特殊字符 1、标题标签h1—h6 为了使网…

SpringBoot案例-文件上传

目录 简介 文件上传前端页面三要素 服务端接收文件 小结 本地储存 实现 代码优化 小结 阿里云OSS 阿里云 阿里云OSS 使用第三方服务--通用思路 准备工作 参照官方SDK代码&#xff0c;编写入门程序 集成使用 阿里云OSS-使用步骤 阿里云OSS使用步骤 参照SDK编写入…