当前位置: 首页 > news >正文

9.13 9.15 JavaWeb(事务管理、AOP P172-P182)

事务管理

事务

概念

事务是一组操作的集合,是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败

操作

开启事务(一组操作开始前,开启事务):start transaction / begin

提交事务(这组操作全部成功后,提交事务):commit

回滚事务(中间任何一个操作出现异常,回滚事务):rollback

Spring事务管理

案例:解散部门,删除部门的同时要删除该部门下的员工

注解:@Transactional

位置:业务(Service)层的方法、类、接口上

作用:将当前方法交给spring进行事务管理,方法执行前开启事务,成功执行完毕提交事务;出现异常回滚事务

在两次删除操作之间添加异常代码

    @Transactional@Overridepublic void delete(Integer id) {deptMapper.deleteById(id); //根据id删除部门int i = 1/0;empMapper.deleteByDeptId(id); //根据部门id删除员工}

再进行删除操作

这样就成功实现事务管理

事务进阶

rollbackFor

默认情况下,只有出现RuntimeException才会回滚异常,rollbackFor属性用于控制出现何种异常类型,回滚事务

    @Transactional(rollbackFor = Exception.class)@Overridepublic void delete(Integer id) {deptMapper.deleteById(id); //根据id删除部门int i = 1/0;empMapper.deleteByDeptId(id); //根据部门id删除员工}

propagation

事务传播行为:当一个方法事务被另一个方法事务方法调用时,这个事务应该如何进行事务控制

REQUIRED:大部分情况下用该传播行为即可

REQURIRES_NEW:不希望事务之间相互影响时,使用该传播行为。比如:下订单前需要记录日志,不论订单成功保存与否,都需要保证日志记录能够成功记录

AOP基础

AOP概述

AOP:Aspect Oriented Programming(面向切面编程),其实是面向特定方法编程

场景:

实现:

动态代理是面向切面编程的主流实现。SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程

AOP快速入门

统计业务层各个方法的执行耗时

1.导入AOP的相关依赖

2.编写AOP程序,针对特定方法根据业务进行编程

首先再pom文件中添加AOP的依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

再编写AOP程序,新建一个aop.TimeAspect类

package com.itheima.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.itheima.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;}
}

查询部门信息时,日志信息如下

场景:记录操作日志,权限控制,事务管理

优点:代码无侵入,减少重复代码,提高开发效率,维护方便

AOP核心概念

AOP进阶

通知类型

@PointCut注解:该注解的作用是将公共的切入点表达式抽取出来,需要用到是引入该切入点表达式即可

通知顺序

当多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被运行

1.不同切面类中,默认按照不同切面类的类名字母排序

    目标方法前的通知方法:字母排序靠前的先执行

    目标方法后的通知方法:字母排序靠前的后执行

2.用 @Order(数字) 加在切面类上来控制顺序

    目标方法前的通知方法:数字小的先执行

    目标方法后的通知方法:数字小的后执行

切入点表达式

即描述切入点方法的一种表达式,主要用来决定项目中的哪些方法要加入通知

execution

根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为

带?的表示是可以省略的部分

1.访问修饰符:可省略(比如:public、protected)

2.包名.类名:可省略

3.throws异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常

可以使用通配符描述切入点

1. * :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分

     

2. .. :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

    

可以根据业务需要,使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式

@annotation

如果想要匹配DeptServiceImpl中的list()和delete(Integer id)方法,使用execution写切入点表达式比较复杂

@PointCut("execution(* com.itheima.service.DeptService.list())" || "execution(* com.itheima.service.DeptService.delete(java.lang.Integer))")
private void pt(){}

@annotation切入点表达式用于匹配标识有特定注解的方法

连接点

在Spring中使用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等

对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint

对于其他四种通知,获取连接点信息只能使用JoinPoint,他是ProceedingJoinPoint的父类

AOP案例

需求:将案例中增、删、改相关接口的操作日志记录到数据库表中,日志信息包含:操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时长

思路:需要对所有业务类中的增、删、改 方法添加统一功能,使用AOP技术最为方便;由于增、删、改 方法名没有规律,可以自定义@Log注解完成目标方法匹配

首先在pom文件中添加AOP相关依赖

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

接着新建一个操作日志表

-- 操作日志表
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 '操作日志表';

再新建一个日志表对应的实体类

package com.itheima.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; //操作耗时
}

编写Log注解(@annotation切面表达式)

package com.itheima.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 {
}

编写通知,定义切面类

package com.itheima.aop;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itheima.mapper.OperateLogMapper;
import com.itheima.pojo.OperateLog;
import com.itheima.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import jakarta.servlet.http.HttpServletRequest;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.util.Arrays;@Slf4j
@Component
@Aspect //切面类
public class LogAspect {@Autowiredprivate HttpServletRequest request;@Autowiredprivate OperateLogMapper operateLogMapper;@Around("@annotation(com.itheima.anno.Log)")public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {//操作人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;}
}

然后要在需要在目标对象(DeptServiceImpl、EmpServiceImpl)的连接点方法(增、删、改)上添加刚刚写的Log注解,执行启动类,进行一次新增部门操作和一次删除部门操作,日志成功记录在operate_log表中


文章转载自:

http://5Ve5QCRQ.cpgtL.cn
http://K4Z2izO8.cpgtL.cn
http://RZlSX2pW.cpgtL.cn
http://cRqSgONF.cpgtL.cn
http://G2KliFlR.cpgtL.cn
http://X2t2KrIC.cpgtL.cn
http://lwh6b3tX.cpgtL.cn
http://Ww99VNDY.cpgtL.cn
http://hCPDDNze.cpgtL.cn
http://QpfCSfgX.cpgtL.cn
http://7F6QGMcJ.cpgtL.cn
http://ZiuNPYpC.cpgtL.cn
http://2RxjsbtE.cpgtL.cn
http://ZH267Qqi.cpgtL.cn
http://gZHsdKX8.cpgtL.cn
http://e2f3nDdl.cpgtL.cn
http://NnQOZo7O.cpgtL.cn
http://ett9CPxd.cpgtL.cn
http://dUpplJk0.cpgtL.cn
http://AkT8vMn7.cpgtL.cn
http://owx6Hj6V.cpgtL.cn
http://JTObPRjR.cpgtL.cn
http://E9EJXYqa.cpgtL.cn
http://QguOeu5W.cpgtL.cn
http://k3qG9WXu.cpgtL.cn
http://zDhV5EqT.cpgtL.cn
http://fWRNLvw4.cpgtL.cn
http://VckrkHgf.cpgtL.cn
http://HQuGZ7mD.cpgtL.cn
http://ybgqp96Y.cpgtL.cn
http://www.dtcms.com/a/384136.html

相关文章:

  • 九、vue3后台项目系列——tag标签逻辑
  • 数据结构入门指南:计算机专业核心课精要
  • 贪心算法应用:DNS缓存问题详解
  • Python爬虫实战——使用NetNut网页解锁器获取亚马逊电商数据
  • 知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
  • NGUI--游戏登录、注册和服务器选择系统​​
  • C++ std::vector
  • 知微集:Transformer
  • 大数据毕业设计选题推荐-基于大数据的客户购物订单数据分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • C# JPG转PDF实现方案
  • 单变量单步时序预测 | TCN-BiLSTM时间卷积结合长短期记忆神经网络(MATLAB)
  • uniapp scroll-view 设置scrollTop无效
  • Day24_【深度学习(2)—PyTorch框架安装】
  • 未来汽车电气/电子(E/E)架构——迈向全新电气/电子范式之路上的复杂性掌控
  • 【Linux手册】mmap 接口:内存映射实现高效 IO 的
  • 如何使用代理 IP 实现爬虫代理
  • Ubuntu 录制 gif
  • Day24_【深度学习(3)—PyTorch使用—张量的创建和类型转换】
  • IP-Prefix 配置核心要点与典型应用场景
  • 为什么企业需要高防IP
  • 通过 DNS 解析SCAN IP
  • 网络:TCP/IP协议
  • 【后端】数据库四大范式详细解析
  • 银河麒麟部署mysql8.0并连接应用
  • Mysql中有那些锁
  • React 状态管理(手写实现react-redux)
  • C++:类和对象(下)
  • 智能驾驶再加速:L4 级 AI 系统落地难点与城市试点经验总结
  • 第4章:CPU进阶命令
  • brew@homebrew@linux通用包管理工具linuxbrew