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

这篇具有很好参考价值的文章主要介绍了[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 事务回顾

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

1.2 Spring事务管理

1.2.1 案例

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 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 {
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;

    /**
     * 查询部门
     * @return
     */
    @Override
    public List<Dept> list() {

        return deptMapper.list();
    }

    /**
     * 根据ID删除部门
     * @param id
     */
    @Override
    public void delete(Integer id) {
        // 1 根据ID 删除部门
        deptMapper.deleteById(id);
        
        //2 根据部门id删除该部门下的员工
        empMapper.deleteByDeptId(id);


    }

    /**
     * 新增部门
     * @param dept
     */
    @Override
    public void add(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.insert(dept);
    }

    /**
     * 根据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 启动服务-测试

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 1.2.2 模拟异常

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

1.2.3  分析问题

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 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 {
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;

    /**
     * 查询部门
     * @return
     */
    @Override
    public List<Dept> list() {

        return deptMapper.list();
    }

    /**
     * 根据ID删除部门
     * @param id
     */
    @Transactional //spring 事务管理
    @Override
    public void delete(Integer id) {
        // 1 根据ID 删除部门
        deptMapper.deleteById(id);

        //2 根据部门id删除该部门下的员工
        empMapper.deleteByDeptId(id);


    }

    /**
     * 新增部门
     * @param dept
     */
    @Override
    public void add(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.insert(dept);
    }

    /**
     * 根据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 启动服务-测试

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

1.3 事务进阶

1.3.1 rollbackFor 回滚

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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();
    }

    /**
     * 根据ID删除部门
     * @param id
     */
    @Transactional(rollbackFor = Exception.class) //spring 事务管理  .所有异常回滚:rollbackFor = Exception.class
    @Override
    public void delete(Integer id) {
        // 1 根据ID 删除部门
        deptMapper.deleteById(id);

        //2 根据部门id删除该部门下的员工
        empMapper.deleteByDeptId(id);


    }

    /**
     * 新增部门
     * @param dept
     */
    @Override
    public void add(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.insert(dept);
    }

    /**
     * 根据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 传播行为

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 1.3.2 案例

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 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

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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接口

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

package com.runa.service;

import com.runa.pojo.DeptLog;

public interface DeptLogService {

    void insert(DeptLog deptLog);
}
1.3.2.4 DeptLogServiceImpl实现类

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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;
//  没有使用下面的使用上面的是因为事务的原因
//    @Autowired  
//    private DeptLogMapper deptLogMapper;

    @Autowired
    private DeptLogService deptLogService;



    /**
     * 查询部门
     * @return
     */
    @Override
    public List<Dept> list() {

        return deptMapper.list();
    }

    /**
     * 根据ID删除部门
     * @param id
     */
    @Transactional(rollbackFor = Exception.class) //spring 事务管理  .所有异常回滚:rollbackFor = Exception.class
    @Override
    public 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
     */
    @Override
    public void add(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.insert(dept);
    }

    /**
     * 根据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 启动服务-测试

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 1.3.3 总结

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

1.4 扩展插件Grep Console

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

可以为日志设置颜色 

二、AOP基础

2.1 AOP概述

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

2.2 AOP 快速入门

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 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 类

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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 启动服务-测试

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 2.2.4 AOP场景&优势

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

2.3 核心概念 

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

2.4 AOP 执行流程

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

2.5 总结

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 三、AOP 进阶

3.1 通知类型

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 文章来源地址https://www.toymoban.com/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,运行项目要注释
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 ...");
    }
}

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

3.2 通知顺序

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis 

 

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 切入表达式

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

3.3.1 execution表达式 

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis 

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

 

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

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表达式

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis 

 

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 {
}

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

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 总结

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

3.4 连接点

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

 

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;
    }
}

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis 

 

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

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

 4.1 思路

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

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

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

  

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; //操作时间
    private String className; //操作类名
    private String methodName; //操作方法名
    private String methodParams; //操作方法参数
    private String returnValue; //操作方法返回值
    private Long costTime; //操作耗时
}

 4.5 接口OperateLogMapper

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

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注解

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 [JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

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 

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

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)")  //环绕通知
    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 {

    @Autowired
    private 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
    @PostMapping
    public 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
    @PutMapping
    public 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 {

    @Autowired
    private 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
     */
    @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("分页查询,参数:开始页 {}, 每页显示:{},姓名:{},性别:{}, 开始日期:{},结束日期:{}", 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
    @PostMapping
    public 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
    @PutMapping
    public Result update(@RequestBody Emp emp){
        log.info("更新员工: {}",emp);
        empService.update(emp);
        return Result.success();
    }

}

4.10 启动服务-测试

[JavaWeb]【十二】web后端开发-事务管理&AOP,java,数据库,mysql,mybatis

 

到了这里,关于[JavaWeb]【十二】web后端开发-事务管理&AOP的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [JavaWeb]【七】web后端开发-MYSQL

    目录 一 数据库介绍 1.1 什么是数据库  1.2 数据库产品 二 MySQL概述 2.1 下载 2.2 解压 2.3 配置 2.3.1. 添加环境变量 2.3.2. 初始化MySQL 2.3.3. 注册MySQL服务 2.3.4. 启动MySQL服务  2.3.5. 修改默认账户密码 2.4 登录MySQL 2.5卸载MySQL 2.2 数据模型 2.3 SQL简介 三 数据库设计-DDL 3.1 数据库操作 3

    2024年02月12日
    浏览(33)
  • [JavaWeb]【六】web后端开发-请求响应

    目录 一  引子 二 请求 2.1 Postman 2.1.1 安装 2.1.2 创建工作空间  2.1.3 添加接口 2.2 简单参数 2.2.1 原始方式(不推荐)  2.2.2 SpringBoot方式-GET(参数名与形参变量名相同)  2.2.3 SpringBoot方式-POST(参数名与形参变量名相同) 2.2.4 SpringBoot方式-POST(参数名与形参变量名不相同) 2.2.5 @Req

    2024年02月12日
    浏览(33)
  • [JavaWeb]【四】web后端开发-SpringBootWeb入门

    目录 一 Spring  二 SpringBootWeb入门 2.1 入门需求  2.2 分析  2.3 开始创建SpringBootWeb  2.4 创建类实现需求  2.5 启动程序 2.6 访问 三 HTTP协议 3.1 HTTP-概述 3.2 HTTP-请求协议 3.3 HTTP-响应协议 3.3.1 响应状态码 响应类型 3.4 HTTP-协议解析 前言:web的后端开发springbootweb入门开篇      

    2024年02月12日
    浏览(30)
  • [JavaWeb]【十四】web后端开发-MAVEN高级

    目录 一、分模块设计与开发 1.1 分模块设计  1.2 分模块设计-实践​编辑 1.2.1 复制老项目改为spring-boot-management 1.2.2 新建maven模块runa-pojo 1.2.2.1 将原项目pojo复制到runa-pojo模块  1.2.2.2 runa-pojo引入新依赖 1.2.2.3 删除原项目pojo包 1.2.2.4 在spring-boot-management(原项目)引入runa-pojo依赖

    2024年02月11日
    浏览(26)
  • spring事务管理详解和实例(事务传播机制、事务隔离级别)

    目录 1 理解spring事务 2 核心接口 2.1 事务管理器 2.1.1 JDBC事务 2.1.2 Hibernate事务 2.1.3 Java持久化API事务(JPA) 2.2 基本事务属性的定义 2.2.1 传播行为 2.2.2 隔离级别 2.2.3 只读 2.2.4 事务超时 2.2.5 回滚规则 2.3 事务状态 3 编程式事务 3.1 编程式和声明式事务的区别 3.2 如何实现编程式

    2024年02月06日
    浏览(33)
  • [JavaWeb]【九】web后端开发-SpringBootWeb案例(菜单)

    目录 一、准备工作 1.1 需求 1.2 环境搭建 1.2.1 准备数据库表  1.2.2 创建springboot工程 1.2.3 配置application.properties 准备对应实体类  1.2.3.1 application.properties  1.2.3.2 实体类  1.2.3.2.1 Emp类  1.2.3.2.2 Dept类 1.2.4 准备对应的Mapper、Service(接口实现类)、Controller基础结构 1.2.4.1 Mapper

    2024年02月11日
    浏览(37)
  • 【MySQL系列】MySQL的事务管理的学习(一)_ 事务概念 | 事务操作方式 | 事务隔离级别

    「前言」文章内容大致是MySQL事务管理。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 事务的概念 MySQL事务是指一系列的数据库操作(一组 DML 语句),这些操作要么全部成功执行,要么全部失败回滚。事务的目的是确保数据库的一致性和完整性 事务就是要

    2024年02月09日
    浏览(28)
  • 【掌握Spring事务管理】深入理解事务传播机制的秘密

    🎉🎉🎉 点进来你就是我的人了 博主主页: 🙈🙈🙈 戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔 🤺🤺🤺 目录 1.Spring 中事务的实现方式 1.1 Spring 编程式事务 (了解) 1.2 Spring 声明式事务 ( @Transactional ) 【异常情况一】(自动回滚成功) 【异常情况二】(自动回滚失效

    2024年02月10日
    浏览(35)
  • Spring使用@Transactional 管理事务,Java事务详解。

    B站视频:https://www.bilibili.com/video/BV1eV411u7cg 技术文档:https://d9bp4nr5ye.feishu.cn/wiki/HX50wdHFyiFoLrkfEAAcTBdinvh 简单来说事务就是一组对数据库的操作 要么都成功,要么都失败。 事务要保证可靠性,必须具备四个特性:ACID。 A:原子性:事务是一个原子操作单元,要么完全执行,要么

    2024年02月11日
    浏览(24)
  • [JavaWeb]【五】web后端开发-Tomcat && SpringBoot解析

    目录 一 介绍Tomcat  二 基本使用 2.1 解压绿色版 2.2 启动TOMCAT 2.3 关闭TOMCAT 2.4 常见问题  2.5 修改端口号  2.6 部署应用程序 三 SpringBootWeb入门程序解析 前言:tomcat与SpringBoot解析                            

    2024年02月12日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包