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://www.pswp.cn/diannao/99220.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/99220.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/99220.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

檢索融合方法- Distribution-Based Score Fusion (DBSF)

在信息檢索&#xff08;IR&#xff09;、推薦系統和多模態檢索中&#xff0c;我們常常需要融合來自多個檢索器或模型的結果。不同檢索器可能對同一文檔打出的分數差異很大&#xff0c;如果直接簡單加權&#xff0c;很容易出現某個檢索器“主導融合結果”的情況。 Distribution…

Oracle體系結構-歸檔日志文件(Archive Log Files)

核心概念&#xff1a;什么是歸檔日志文件&#xff1f; 定義&#xff1a; 歸檔日志文件&#xff08;Archive Log Files&#xff09;是在線重做日志文件&#xff08;Online Redo Log Files&#xff09;在被覆蓋之前的一個完整副本。它們由 Oracle 的后臺進程 ARCn&#xff08;歸檔…

GoogLeNet實戰:用PyTorch實現經典Inception模塊

配套筆記&講解視頻&#xff0c;點擊文末名片獲取研究背景&#xff08;Background&#xff09; 1.1 領域現狀&#xff08;大環境與挑戰&#xff09; 想象一下&#xff0c;你和朋友們在看一大堆照片——貓、狗、汽車、蛋糕&#xff0c;大家要把每張照片貼上標簽。幾年前&…

【開題答辯全過程】以 “舊書驛站”微信小程序的設計與開發為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

【辦公類-112-01】20250912家園每周溝通指導(Deepseek擴寫完善+Python模擬點擊鼠標自動發送給家長微信)

背景需求 孩子剛上小班,家長比較關心孩子情況(情緒、社交、吃飯等) 所以我每周五晚上和家長溝通一下孩子的情況。 操作流程 第一周(9月5日)是“適應周”,我添加了所有孩子的一位家長的微信號 23份全部是手打,足足寫了4個小時。第一周案例多,所以寫了很多,措辭醞釀后…

Spark專題-第一部分:Spark 核心概述(1)-Spark 是什么?

眾所周知&#xff0c;教學文檔總該以理論部分作為開篇&#xff0c;于是我們這篇Spark專題同樣會以一堆理論和專有名詞開始&#xff0c;筆者會盡可能的讓專業詞匯通俗易懂 第一部分&#xff1a;Spark 核心概述 Spark 是什么&#xff1f; 1. 大數據時代的"超級賽車"…

從零到一上手 Protocol Buffers用 C# 打造可演進的通訊錄

一、為什么是 Protobuf&#xff08;而不是 XML/自定義字符串/.NET 二進制序列化&#xff09; 在需要把結構化對象持久化或跨進程/跨語言傳輸時&#xff0c;常見方案各有痛點&#xff1a; BinaryFormatter 等 .NET 二進制序列化&#xff1a;對類型簽名與版本極其脆弱、體積偏大&…

計算機網絡(三)網絡層

三、網絡層網絡層是五層模型中的第三層&#xff0c;位于數據鏈路層和傳輸層之間。它的核心任務是實現數據包在不同網絡之間&#xff08;跨網絡&#xff09;的邏輯傳輸。網絡層的數據傳輸單位是數據報&#xff08;Datagram&#xff09;或數據包&#xff08;Packet&#xff09;。…

互聯網大廠Java面試實錄:從基礎到微服務全棧技術答疑

互聯網大廠Java面試實錄&#xff1a;從基礎到微服務全棧技術答疑 本文以電商場景為背景&#xff0c;展現一場互聯網大廠Java開發職位的面試過程。嚴肅的面試官與搞笑的水貨程序員謝飛機展開三輪技術問答&#xff0c;涵蓋Java SE、Spring Boot、數據庫、微服務、安全以及CI/CD等…

StringBuilder 深度解析:數據結構與擴容機制的底層細節

文章目錄 前言 一、數據結構&#xff1a;不止是簡單的字符數組 1. 核心成員變量&#xff08;定義在 AbstractStringBuilder 中&#xff09; 2. 構造器與初始容量 二、擴容機制&#xff1a;從 "不夠用" 到 "換大容器" 的全過程 步驟 1&#xff1a;計算…

Elasticsearch面試精講 Day 17:查詢性能調優實踐

【Elasticsearch面試精講 Day 17】查詢性能調優實踐 在“Elasticsearch面試精講”系列的第17天&#xff0c;我們聚焦于查詢性能調優實踐。作為全文檢索與數據分析的核心引擎&#xff0c;Elasticsearch的查詢性能直接影響用戶體驗和系統吞吐能力。在高并發、大數據量場景下&…

WPF 數據綁定模式詳解(TwoWay、OneWay、OneTime、OneWayToSource、Default)

在WPF中&#xff0c;數據綁定模式&#xff08;Binding Mode&#xff09;用于指定數據流的方向。常見的模式有TwoWay、OneWay、OneTime、OneWayToSource和Default。TwoWay&#xff08;雙向綁定&#xff09;&#xff1a;數據從源&#xff08;通常是ViewModel或數據上下文&#xf…

使用 NVIDIA Dynamo 部署 PD 分離推理服務

1 Dynamo 介紹 NVIDIA Dynamo 是一個開源的模塊化推理框架&#xff0c;用于在分布式環境上實現生成式 AI 模型的服務化部署。Dynamo 通過動態資源調度、智能路由、內存優化與高速數據傳輸&#xff0c;無縫擴展大型 GPU 集群之間的推理工作負載。 Dynamo 采用推理引擎無關的設…

答題卡識別改分項目

目錄 核心思路 分步實現與代碼解析 1. 環境準備與工具函數定義 2. 圖片預處理 3. 輪廓提取與篩選 3. 輪廓提取與篩選 4. 透視變換&#xff08;矯正傾斜答題卡&#xff09; 5. 閾值處理&#xff08;突出填涂區域&#xff09; 6. 提取選項圓圈輪廓 7. 選項輪廓排序&…

Python爬蟲實戰:研究Pandas,構建新浪網股票數據采集和分析系統

1. 系統概述 股票數據分析系統旨在通過自動化手段獲取市場數據,進行深度分析,輔助投資決策。本系統主要包含以下核心模塊: 數據爬取模塊:從新浪財經獲取股票列表、基本信息及歷史交易數據 數據處理模塊:清洗原始數據,處理缺失值與異常值,計算技術指標 分析可視化模塊:…

【C++STL】list的詳細用法和底層實現

&#x1f31f;個人主頁&#xff1a;第七序章 &#x1f308;專欄系列&#xff1a;C&#xff0b;&#xff0b; 目錄 ??前言&#xff1a; &#x1f308;一&#xff1a;介紹 &#x1f308;二&#xff1a;list的創建 ??基本框架 &#x1f319;節點類 &#x1f319;構造函…

AI大模型開發(多模態+提示詞)

接著之前的例子&#xff0c;繼續測試模型對話&#xff0c;今天主要測試多模態加上系統提示詞。 一.多模態 多模態方法&#xff0c;主要添加了對圖片的測試。 public String chatWithMessage(UserMessage userMessage){ChatResponse chatResponse qwenChatModel.chat(userMess…

Qt程序單獨運行報錯問題

Qt程序單獨運行報錯問題介紹問題原因分析解決方案&#xff08;從最佳實踐到臨時方法&#xff09;方法一&#xff1a;使用 windeployqt 工具&#xff08;最推薦、最規范&#xff09;方法二&#xff1a;臨時修改系統 PATH&#xff08;適合開發調試&#xff09;方法三&#xff1a;…

Flask學習筆記(二)--路由和變量

一、路由Flask支持兩種路由1、使用route()裝飾器將URL綁定到函數app.route(/hello)def hello_world():return hello world2、使用應用程序對象的add_url_rule()函數def hello_world():return hello worldapp.add_url_rule(/, hello, hello_world)二、變量規則Flask開發中&#…

Skywalking告警配置+簡易郵件告警應用配置(保姆級)

Skywalking告警配置簡易郵件告警應用配置前言&#xff1a; 前文&#xff1a;SkyWalking Elasticsearch8 容器化部署指南&#xff1a;國內鏡像加速與生產級調優_skywalkinges-CSDN博客 ? SKywalking Agent配置Oracle監控插件安裝指南-CSDN博客 Skywalking版本&#xff1a;V10.…