目錄
一、事務(wù)管理
1.1 事務(wù)回顧
1.2 Spring事務(wù)管理
1.2.1 案例
?1.2.1.1 EmpMapper新增deleteByDeptId方法
?1.2.1.2?DeptServiceImpl?
?1.2.1.3 啟動(dòng)服務(wù)-測試
?1.2.2 模擬異常
1.2.3? 分析問題
?1.2.4 Spring事務(wù)管理(一般用在類似多次delete)
?1.2.4.1 開啟事務(wù)開關(guān)application.yml
1.2.4.2??DeptServiceImpl?
1.2.4.3 啟動(dòng)服務(wù)-測試
1.3 事務(wù)進(jìn)階
1.3.1 rollbackFor 回滾
1.3.2 propagation 傳播行為
?1.3.2?案例
?1.3.2.1 創(chuàng)建部門日志表dept_log
?1.3.2.2 新建實(shí)體類DeptLog
1.3.2.3?DeptLogService接口
1.3.2.4?DeptLogServiceImpl實(shí)現(xiàn)類
1.3.2.5?DeptLogMapper
1.3.2.6?DeptServiceImpl
?1.3.2.7 啟動(dòng)服務(wù)-測試
?1.3.3 總結(jié)
1.4 擴(kuò)展插件Grep Console
二、AOP基礎(chǔ)
2.1 AOP概述
2.2 AOP 快速入門
?2.2.1 AOP依賴
2.2.2?TimeAspect 類
2.2.3 啟動(dòng)服務(wù)-測試
?2.2.4 AOP場景&優(yōu)勢(shì)
2.3 核心概念?
2.4 AOP 執(zhí)行流程
2.5 總結(jié)
?三、AOP 進(jìn)階
3.1 通知類型
3.2 通知順序
3.3 切入表達(dá)式
3.3.1 execution表達(dá)式?
3.3.2 annotation表達(dá)式
?3.3.3 總結(jié)
3.4 連接點(diǎn)
四、AOP案例-記錄操作日志
?4.1 思路
4.2??配置起步依賴AOP
4.3 創(chuàng)建數(shù)據(jù)庫表operate_log
?4.4 實(shí)體類OperateLog
?4.5 接口OperateLogMapper
4.6 新建一個(gè)自定義的Log注解
4.7 定義一個(gè)切面類LogAspect?
4.8?Deptcontroller 為新增、修改、刪除添加@Log
4.9?EmpController?為新增、修改、刪除添加@Log
4.10 啟動(dòng)服務(wù)-測試
前言:Spring 事務(wù)管理是 Spring Framework 提供的一種方便的事務(wù)管理方式,它主要解決了應(yīng)用程序中多數(shù)據(jù)源跨庫操作時(shí)的事務(wù)管理問題。Spring 事務(wù)管理的原理是使用代理模式,為目標(biāo)對(duì)象動(dòng)態(tài)地創(chuàng)建代理對(duì)象,代理對(duì)象攔截目標(biāo)對(duì)象的方法,實(shí)現(xiàn)事務(wù)的開啟、提交和回滾等操作。在 Spring 中,使用 @Transactional 注解來標(biāo)記需要進(jìn)行事務(wù)管理的方法,通過配置數(shù)據(jù)源和事務(wù)管理器,Spring 可以自動(dòng)為這些方法創(chuàng)建事務(wù)并進(jìn)行管理。在配置事務(wù)時(shí),可以指定事務(wù)的隔離級(jí)別、傳播行為、只讀屬性等選項(xiàng),以滿足不同的業(yè)務(wù)需求。Spring 事務(wù)管理的好處是簡化了事務(wù)管理的流程,減少了代碼的重復(fù)性,提高了代碼的可讀性和可維護(hù)性,并且在多線程環(huán)境下可以保證數(shù)據(jù)的一致性。
一、事務(wù)管理
1.1 事務(wù)回顧
1.2 Spring事務(wù)管理
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 {
/**
* 查詢總記錄數(shù)
* @return
*/
// @Select("select count(*) from emp")
// public Long count();
/**
* 分頁查詢 獲取列表數(shù)據(jù)
* @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的員工信息查詢(帶條件)--動(dòng)態(tài)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);
/**
* 根據(jù)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);
/**
* 根據(jù)部門dept_id刪除該部門下的員工數(shù)據(jù)
*/
@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 {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
/**
* 查詢部門
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根據(jù)ID刪除部門
* @param id
*/
@Override
public void delete(Integer id) {
// 1 根據(jù)ID 刪除部門
deptMapper.deleteById(id);
//2 根據(jù)部門id刪除該部門下的員工
empMapper.deleteByDeptId(id);
}
/**
* 新增部門
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
/**
* 根據(jù)id查詢部門
* @param id
* @return
*/
@Override
public Dept getById(Integer id) {
return deptMapper.getById(id);
}
/**
* 編輯部門
* @param dept
*/
@Override
public void update(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
}
?1.2.1.3 啟動(dòng)服務(wù)-測試
?
?1.2.2 模擬異常
1.2.3? 分析問題
?1.2.4 Spring事務(wù)管理(一般用在類似多次delete)
?1.2.4.1 開啟事務(wù)開關(guān)application.yml
#spring事務(wù)管理日志
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 {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
/**
* 查詢部門
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根據(jù)ID刪除部門
* @param id
*/
@Transactional //spring 事務(wù)管理
@Override
public void delete(Integer id) {
// 1 根據(jù)ID 刪除部門
deptMapper.deleteById(id);
//2 根據(jù)部門id刪除該部門下的員工
empMapper.deleteByDeptId(id);
}
/**
* 新增部門
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
/**
* 根據(jù)id查詢部門
* @param id
* @return
*/
@Override
public Dept getById(Integer id) {
return deptMapper.getById(id);
}
/**
* 編輯部門
* @param dept
*/
@Override
public void update(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
}
1.2.4.3 啟動(dòng)服務(wù)-測試
?
1.3 事務(wù)進(jìn)階
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 {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
/**
* 查詢部門
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根據(jù)ID刪除部門
* @param id
*/
@Transactional(rollbackFor = Exception.class) //spring 事務(wù)管理 .所有異?;貪L:rollbackFor = Exception.class
@Override
public void delete(Integer id) {
// 1 根據(jù)ID 刪除部門
deptMapper.deleteById(id);
//2 根據(jù)部門id刪除該部門下的員工
empMapper.deleteByDeptId(id);
}
/**
* 新增部門
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
/**
* 根據(jù)id查詢部門
* @param id
* @return
*/
@Override
public Dept getById(Integer id) {
return deptMapper.getById(id);
}
/**
* 編輯部門
* @param dept
*/
@Override
public void update(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
}
??
1.3.2 propagation 傳播行為
?
?1.3.2?案例
?1.3.2.1 創(chuàng)建部門日志表dept_log
create table dept_log(
id int auto_increment comment '主鍵ID' primary key,
create_time datetime null comment '操作時(shí)間',
description varchar(300) null comment '操作描述'
)comment '部門操作日志表';
?1.3.2.2 新建實(shí)體類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實(shí)現(xiàn)類
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 {
@Autowired
private DeptLogMapper deptLogMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public 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 {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
// 沒有使用下面的使用上面的是因?yàn)槭聞?wù)的原因
// @Autowired
// private DeptLogMapper deptLogMapper;
@Autowired
private DeptLogService deptLogService;
/**
* 查詢部門
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根據(jù)ID刪除部門
* @param id
*/
@Transactional(rollbackFor = Exception.class) //spring 事務(wù)管理 .所有異?;貪L:rollbackFor = Exception.class
@Override
public void delete(Integer id) {
try {
// 1 根據(jù)ID 刪除部門
deptMapper.deleteById(id);
// 模擬異常
int i = 1/0;
//2 根據(jù)部門id刪除該部門下的員工
empMapper.deleteByDeptId(id);
} finally {
DeptLog deptLog = new DeptLog();
deptLog.setCreateTime(LocalDateTime.now());
deptLog.setDescription("執(zhí)行了解散部門的操作,此次解散的是" + id + "號(hào)部門");
deptLogService.insert(deptLog);
//沒有使用下面的使用上面的是因?yàn)槭聞?wù)的原因
// deptLogMapper.insert(deptLog);
}
}
/**
* 新增部門
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
/**
* 根據(jù)id查詢部門
* @param id
* @return
*/
@Override
public Dept getById(Integer id) {
return deptMapper.getById(id);
}
/**
* 編輯部門
* @param dept
*/
@Override
public void update(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
}
?1.3.2.7 啟動(dòng)服務(wù)-測試
?1.3.3 總結(jié)
1.4 擴(kuò)展插件Grep Console
可以為日志設(shè)置顏色?
二、AOP基礎(chǔ)
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.*(..))") //切入點(diǎn)表達(dá)式
// @Around("com.runa.aop.MyAspect1.pt()")
@Around("execution(* com.runa.service.*.*(..))") //切入點(diǎn)表達(dá)式
public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
//1. 記錄開始時(shí)間
long begin = System.currentTimeMillis();
//2. 調(diào)用原始方法運(yùn)行
Object result = joinPoint.proceed();
//3. 記錄結(jié)束時(shí)間, 計(jì)算方法執(zhí)行耗時(shí)
long end = System.currentTimeMillis();
log.info(joinPoint.getSignature()+"方法執(zhí)行耗時(shí): {}ms", end-begin);
return result;
}
}
2.2.3 啟動(dòng)服務(wù)-測試
?2.2.4 AOP場景&優(yōu)勢(shì)
2.3 核心概念?
2.4 AOP 執(zhí)行流程
2.5 總結(jié)
?三、AOP 進(jìn)階
3.1 通知類型
?
?
?文章來源地址http://www.zghlxwxcb.cn/news/detail-671293.html
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,運(yùn)行項(xiàng)目要注釋
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 ...");
//調(diào)用目標(biāo)對(duì)象的原始方法執(zhí)行
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 //為了實(shí)驗(yàn),實(shí)際是要注釋的
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 //為了實(shí)驗(yàn),實(shí)際是要注釋的
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 //為了實(shí)驗(yàn),實(shí)際是要注釋的
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 切入表達(dá)式
3.3.1 execution表達(dá)式?
?
?
?
?
?
?
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 //項(xiàng)目運(yùn)行注釋掉
@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表達(dá)式
?
?
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) //運(yùn)行有效
@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 //為了實(shí)驗(yàn),實(shí)際是要注釋的
@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 總結(jié)
?
3.4 連接點(diǎn)
?
?
?
?
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 //為了實(shí)驗(yàn),實(shí)際是要注釋的
@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. 獲取 目標(biāo)對(duì)象的類名 .
String className = joinPoint.getTarget().getClass().getName();
log.info("目標(biāo)對(duì)象的類名:{}", className);
//2. 獲取 目標(biāo)方法的方法名 .
String methodName = joinPoint.getSignature().getName();
log.info("目標(biāo)方法的方法名: {}",methodName);
//3. 獲取 目標(biāo)方法運(yùn)行時(shí)傳入的參數(shù) .
Object[] args = joinPoint.getArgs();
log.info("目標(biāo)方法運(yùn)行時(shí)傳入的參數(shù): {}", Arrays.toString(args));
//4. 放行 目標(biāo)方法執(zhí)行 .
Object result = joinPoint.proceed();
//5. 獲取 目標(biāo)方法運(yùn)行的返回值 .
log.info("目標(biāo)方法運(yùn)行的返回值: {}",result);
log.info("MyAspect8 around after ...");
return result;
}
}
?
?
四、AOP案例-記錄操作日志
?
?4.1 思路
?
?
4.2??配置起步依賴AOP
略
4.3 創(chuàng)建數(shù)據(jù)庫表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 '操作時(shí)間',
class_name varchar(100) comment '操作的類名',
method_name varchar(100) comment '操作的方法名',
method_params varchar(1000) comment '方法參數(shù)',
return_value varchar(2000) comment '返回值',
cost_time bigint comment '方法執(zhí)行耗時(shí), 單位:ms'
) comment '操作日志表';
?4.4 實(shí)體類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; //ID
private Integer operateUser; //操作人ID
private LocalDateTime operateTime; //操作時(shí)間
private String className; //操作類名
private String methodName; //操作方法名
private String methodParams; //操作方法參數(shù)
private String returnValue; //操作方法返回值
private Long costTime; //操作耗時(shí)
}
?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 {
//插入日志數(shù)據(jù)
@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 新建一個(gè)自定義的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) //運(yùn)行時(shí)生效
@Target(ElementType.METHOD) //作用在方法上
public @interface Log {
}
4.7 定義一個(gè)切面類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 {
@Autowired
private HttpServletRequest request;
@Autowired //注入
private OperateLogMapper operateLogMapper;
@Around("@annotation(com.runa.anno.Log)") //環(huán)繞通知
public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
// 操作人ID - 當(dāng)前登錄員工ID
// 獲取請(qǐng)求頭中的jwt令牌,解析令牌
String jwt = request.getHeader("token");
Claims claims = JwtUtils.parseJWT(jwt);
Integer operateUser = (Integer) claims.get("id");
// 操作時(shí)間
LocalDateTime operateTime = LocalDateTime.now();
// 操作類名
String className = joinPoint.getTarget().getClass().getName();
// 操作方法名
String methodName = joinPoint.getSignature().getName();
// 操作方法參數(shù)
Object[] args = joinPoint.getArgs();
String methodParams = Arrays.toString(args);
long begin = System.currentTimeMillis();
//調(diào)用原始目標(biāo)方法運(yùn)行
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
// 方法返回值
String returnValue = JSONObject.toJSONString(result);
// 操作耗時(shí)
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 {
@Autowired
private DeptService deptService;
/**
* 查詢部門數(shù)據(jù)
* @return
*/
// private static Logger log = LoggerFactory.getLogger(Deptcontroller.class);
// @RequestMapping(value = "/depts", method = RequestMethod.GET) //指定請(qǐng)求方式為GET
@GetMapping //
public Result list(){
log.info("查詢?nèi)坎块T數(shù)據(jù)");
// 調(diào)用 service查詢部門數(shù)據(jù)
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 刪除部門
* @return
*/
@Log
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id){
log.info("根據(jù)id刪除部門:{}", id);
// 調(diào)用service刪除部門
deptService.delete(id);
return Result.success();
}
/**
* 添加部門
* @return
*/
@Log
@PostMapping
public Result add(@RequestBody Dept dept){
log.info("新增部門:{}",dept);
// // 調(diào)用service新增部門
deptService.add(dept);
return Result.success();
}
/**
* 根據(jù)ID查詢部門
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id){
log.info("根據(jù)id查詢部門:{}", id);
// 調(diào)用service查詢部門
Dept dept = deptService.getById(id);
return Result.success(dept);
}
/**
* 編輯部門
* @return
*/
@Log
@PutMapping
public Result update(@RequestBody Dept dept){
log.info("編輯部門:{}==={}", dept.getId(),dept.getName());
// 調(diào)用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 {
@Autowired
private EmpService empService;
/**
* 員工數(shù)據(jù)查詢列表 , 不帶條件
* @param page
* @param pageSize
* @return
*/
// @GetMapping
// public Result page(@RequestParam(defaultValue = "1") Integer page,
// @RequestParam(defaultValue = "10") Integer pageSize){
// log.info("分頁查詢,參數(shù):開始頁 {}, 每頁顯示:{}", page, pageSize);
// // 調(diào)用Service方法進(jìn)行查詢
// PageBean pageBean = empService.page(page,pageSize);
//
// return Result.success(pageBean);
// }
/**
* 員工數(shù)據(jù)查詢列表 , 帶條件組合查詢
* @param page
* @param pageSize
* @param name
* @param gender
* @param begin
* @param end
* @return
*/
@GetMapping
public 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("分頁查詢,參數(shù):開始頁 {}, 每頁顯示:{},姓名:{},性別:{}, 開始日期:{},結(jié)束日期:{}", page, pageSize, name, gender, begin, end);
// 調(diào)用Service方法進(jìn)行查詢
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("批量刪除的操作,刪除對(duì)象為:{}",ids);
empService.delete(ids);
return Result.success();
}
/**
* 新增員工
* @param emp
* @return
*/
@Log
@PostMapping
public Result save(@RequestBody Emp emp){
log.info("新增員工emp: {}",emp);
empService.save(emp);
return Result.success();
}
/**
* 根據(jù)id查詢員工
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id){
log.info("根據(jù)ID查詢員工信息:{}",id);
Emp emp = empService.getById(id);
return Result.success(emp);
}
/**
* 修改員工
* @param emp
* @return
*/
@Log
@PutMapping
public Result update(@RequestBody Emp emp){
log.info("更新員工: {}",emp);
empService.update(emp);
return Result.success();
}
}
4.10 啟動(dòng)服務(wù)-測試
文章來源:http://www.zghlxwxcb.cn/news/detail-671293.html
?
到了這里,關(guān)于[JavaWeb]【十二】web后端開發(fā)-事務(wù)管理&AOP的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!