Spring 事務 以及攔截器的前后關系實驗 Mybatis 日志攔截

?

背景:當一個線程中,如果需要攔截所有當SQL日志,然后統一發送到一個同步器,就可以實現多個數據庫實現同步主庫,在進行紅綠上線,或者灰度部署時候,可以實現生產庫與測試庫實時同步,從而達到實時可切換的效果

通過實驗:

可知道攔截器中 按照以下順序

1、before

2、after

3、AfterReturning? AfterThrowing

4、afterCommit

?

實驗步驟:

有A() B()兩個在serviceImpl下定義帶方法,順序是A中調用B

?

public void A()
{
B();}public void B()
{//Inser的操作throw new Exception("001");
}

實驗結果

當B()聲明了@Transactional,A() 沒有聲明的時候,那么B()之后,就算拋出異常,也會完美的插入執行成功。

當A()聲明了@Transactional,就算B()沒有聲明的時候,B()只要拋出異常,數據也失敗。

?

所以,只有Controller調用Service層那一個方法是否有事務,來決定之后是否有事務。

?

package com.chinamobile.scm.masterdata.interceptor;import com.chinamobile.framework.common.context.InvokeTracer;
import com.chinamobile.framework.common.context.RequestContext;
import com.chinamobile.framework.utils.CollectionUtil;
import com.chinamobile.scm.masterdata.util.ThreadsMapUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ThreadUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;import java.lang.reflect.Method;
import java.util.Deque;
import java.util.List;/*** Intercept implementation for service component.<br>** @author YangHang*/
@Component
@Aspect
@Slf4j
public class MybatisServiceInterceptor {/*** Service切入點<br>*/@Pointcut("execution(* com.chinamobile.scm.*.service.*.*(..)) || execution(* com.chinamobile.scm.service.*.*(..))")public void pointCut() {}/*** 后置異常通知*/@AfterThrowing(pointcut = "pointCut()", throwing = "e")public void throwss(JoinPoint joinPoint, Throwable e) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();System.out.println("攔截方法異常時執行 本方法內不可事務 異常:"+method.getName());}@AfterReturning("pointCut()")public void afterreturning(JoinPoint joinPoint){MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();if(TransactionSynchronizationManager.isActualTransactionActive()) {String tid = String.valueOf(Thread.currentThread().getId());List<String> stringList= ThreadsMapUtil.getSqls(tid);if(CollectionUtils.isNotEmpty(stringList)){for(String item:stringList){log.info("SQL:"+item);}}ThreadsMapUtil.removeSQL(tid);}System.out.println("注解式攔截  本方法內可提交事務 返回"+method.getName());}@After("pointCut()")public void after(JoinPoint joinPoint){MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();
//
//            if(TransactionSynchronizationManager.isActualTransactionActive()) {
//                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
//                    @Override
//                    public void afterCommit() {
//                        System.out.println("send email after transaction commit...");
//                    }
//
//                });
//            }System.out.println("注解式攔截,結束"+method.getName());}@Before("pointCut()")public void before(JoinPoint joinPoint){Thread.currentThread().getId();MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();System.out.println("方法規則式攔截,開始:"+method.getName());}}
package com.chinamobile.scm.masterdata.interceptor;import com.alibaba.fastjson.JSON;
import com.chinamobile.scm.masterdata.util.ThreadsMapUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;/**Mybatis 攔截器 允許使用的插件來攔截的方法包括 Executor (update, query, flushStatements, commit, rollback, getTransaction, close,* isClosed) ParameterHandler (getParameterObject, setParameters)*/
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),@Signature(type = StatementHandler.class, method = "batch", args = { Statement.class })})
@Slf4j
@Component
public class ExecutorInterceptor implements Interceptor {/*** 是否本地*/public  boolean isSavedLocat=false;/*** 根目錄*/public  String sqllogpath="/Users/yh/sqllog";@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.debug("進入到開始整SQL到時候來:");Object target = invocation.getTarget();StatementHandler statementHandler = (StatementHandler)target;BoundSql boundSql = statementHandler.getBoundSql();String sql = showSql(boundSql);//boundSql.getSql();Object parameterObject = boundSql.getParameterObject();List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();// System.out.println(sql);String updatestr= JSON.toJSONString(boundSql);if(TransactionSynchronizationManager.isActualTransactionActive()) {String tid = String.valueOf(Thread.currentThread().getId());ThreadsMapUtil.setSQLs(tid, sql);}else{log.info("SQL:"+sql);}if(isSavedLocat) {writeFile(updatestr, sqllogpath);}return invocation.proceed();}@Overridepublic Object plugin(Object o) {return Plugin.wrap(o, this);}@Overridepublic void setProperties(Properties properties) {}private String getParameterValue(Object obj) {//to_timestamp(to_char(sysdate,'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS')String value = null;if (obj instanceof String) {value = "'" + obj.toString() + "'";} else if (obj instanceof java.sql.Timestamp) {DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);value = "to_timestamp(to_char(" + formatter.format(obj) + ",'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS')";}else if (obj instanceof Date) {DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);value = "'" + formatter.format(obj) + "'";
//	            System.out.println(value);} else {if (obj != null) {value = obj.toString();} else {value = "";}}return value;}public String showSql(BoundSql boundSql) {Object parameterObject = boundSql.getParameterObject();List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();String sql = boundSql.getSql().replaceAll("[\\s]+", " ");if (parameterMappings.size() > 0 && parameterObject != null) {//TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
//            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//                sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
//
//            } else {Configuration configuration=new Configuration();MetaObject metaObject = configuration.newMetaObject(parameterObject);for (ParameterMapping parameterMapping : parameterMappings) {String propertyName = parameterMapping.getProperty();if (metaObject.hasGetter(propertyName)) {Object obj = metaObject.getValue(propertyName);sql = sql.replaceFirst("\\?", getParameterValue(obj));} else if (boundSql.hasAdditionalParameter(propertyName)) {Object obj = boundSql.getAdditionalParameter(propertyName);sql = sql.replaceFirst("\\?", getParameterValue(obj));}}//   }}return sql;}public  void writeFile(String data,String resultfilepath){try {Date date = new Date();String path=resultfilepath+"/"+new SimpleDateFormat("yyyy-MM-dd/").format(date);File f = new File(path);if(!f.exists()){f.mkdirs(); //創建目錄}String filepath=path+ System.currentTimeMillis()+".json";File file = new File(filepath);if(!file.exists()){file.createNewFile();}FileWriter fw = null;//true:表示是追加的標志fw = new FileWriter(file, true);fw.write(data);fw.close();} catch (Exception e) {e.printStackTrace();}finally{}}
}

?

設置可以啟動攔截SQL的部分

package com.chinamobile.scm.masterdata.interceptor;import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;@Configuration
public class MybatisInterceptorConfig {@Beanpublic String myInterceptor(SqlSessionFactory sqlSessionFactory) {sqlSessionFactory.getConfiguration().addInterceptor(new ExecutorInterceptor());
//        sqlSessionFactory.getConfiguration().addInterceptor(executorInterceptor);
//        sqlSessionFactory.getConfiguration().addInterceptor(new ParamInterceptor());
//        sqlSessionFactory.getConfiguration().addInterceptor(new ResultInterceptor());return "interceptor";}
}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386766.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386766.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386766.shtml

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

相關文章

四級翻譯常用詞匯

ancient 古老的&#xff1b;古代的       achieve 獲得 v attract 吸引 v            achievement 成就 n attractive 吸引人的          advanced 先進的 account for 對....負有責任&#xff1b;占比   approach 接近&#xff1b;處理&#…

一般攔截器 serviceImpl部分

一般攔截器 serviceImpl部分 package com.chinamobile.scm.masterdata.interceptor;import com.chinamobile.framework.common.context.InvokeTracer; import com.chinamobile.framework.common.context.RequestContext; import com.chinamobile.framework.utils.CollectionUt…

營銷-營銷方式:營銷方式

ylbtech-營銷-營銷方式&#xff1a;營銷方式營銷方式是指營銷過程中所有可以使用的方法。包括服務營銷、體驗營銷、知識營銷、情感營銷、教育營銷、差異化營銷、直銷、網絡營銷等。要有好的營銷方式首先要創造行之有效的營銷工具。但這并不意味著要把預算的75%都花在印制宣傳資…

以后可能用到的一些OQL

Visual VM對OQL的支持 上面我們學會了如何查看堆內存快照&#xff0c;但是&#xff0c;堆內存快照十分龐大&#xff0c;快照中的類數量也很多。Visual VM提供了對OQL&#xff08;對象查詢語言&#xff09;的支持&#xff0c;以便于開發人員在龐大的堆內存數據中&#xff0c;快…

leetcode1041困于環中的機器人

題目如下&#xff0c;一道簡單的模擬 在無限的平面上&#xff0c;機器人最初位于 (0, 0) 處&#xff0c;面朝北方。機器人可以接受下列三條指令之一&#xff1a;"G"&#xff1a;直走 1 個單位 "L"&#xff1a;左轉 90 度 "R"&#xff1a;右轉 90…

一個拆分使用的存儲過程例子

set serverout on declare var_tmp varchar2(4000) :; var_element varchar2(4000) :; n_length Number : length(\/); begin values_array : VARCHAR_ARRAY(); -- 初始化數組 for i in (select * from sapsr3.zmdm_mthdr where zmtpre in(6200001…

python的pwntools工具的日常使用

1.安裝 操作系統&#xff1a; ubuntu16.04 環境準備&#xff1a; pythonpiplibssl-devlibffi-dev pwntools安裝&#xff1a; sudo apt-get install libffi-devsudo apt-get install libssl-devsudo apt-get install pythonsudo apt-get install python-pipsudo pip install pwn…

Kibana可視化管理頁面詳細使用說明

Kibana可視化管理頁面詳細使用說明 使用瀏覽器訪問 ip:5601 默認端口&#xff0c;進入首頁 Discover&#xff1a;日志管理視圖 主要進行搜索和查詢 Visualize&#xff1a;統計視圖 構建可視化的圖表 Dashboard&#xff1a;儀表視圖 將構…

OO_BLOG3_規格化設計(JML學習)

目錄 JML語言學習筆記理論基礎應用工具鏈情況JMLUnit/JMLUnitNGUNIT3 作業分析作業 3-1 實現兩個容器類Path和PathContainer作業 3-2 實現容器類Path和數據結構類Graph作業 3-3 實現容器類Path&#xff0c;地鐵系統類RailwaySystem規格撰寫的心得與體會最后&#xff0c;衷心感謝…

JAVA獲取JVM內存空間和物理內存空間

一、獲取JVM內存空間 系統環境&#xff1a;WIN JDK版本&#xff1a;1.8re 直接調用Runtime中相應的方法即可&#xff1a; public long maxMemory() Returns the maximum amount of memory that the Java virtual machine will attempt to use. If there is no inherent lim…

CMU Database Systems - Sorting,Aggregation,Join

Sorting 排序如果可在內存里面排&#xff0c;用經典的排序算法就ok&#xff0c;比如快排 問題在于&#xff0c;數據表中的的數據是很多的&#xff0c;沒法一下都放到內存里面進行排序 所以就需要用到&#xff0c;外排&#xff0c;多路并歸排序 看下最簡單的&#xff0c;2路并歸…

springboot線程池的使用和擴展

實戰環境 windowns10&#xff1b;jdk1.8&#xff1b;springboot 1.5.9.RELEASE&#xff1b;開發工具&#xff1a;IntelliJ IDEA&#xff1b; 實戰源碼 本次實戰的源碼可以在我的GitHub下載&#xff0c;地址&#xff1a;gitgithub.com:zq2599/blog_demos.git&#xff0c;項目主…

統計單詞個數

我是抄題解狂魔 /* 1.s.substr(x,len) 在s中取出從x位置開始&#xff0c;長度為len的字符串&#xff0c;并返回string類型的字符串。 2.s.find(a) 在s中查找字符串a,并返回起始下標&#xff08;從0開始&#xff09;&#xff0c;若不存在&#xff0c;返回1844674407370955161&am…

通過Rancher安裝K8s

說明 我們用kubernetes去管理Docker集群&#xff0c;即可以將Docker看成Kubernetes內部使用的低級別組件。另外&#xff0c;kubernetes不僅僅支持Docker&#xff0c;還支持Rocket&#xff0c;這是另一種容器技術。希望我這篇文章中簡單的描述能讓你對兩者有所理解和認識。 機…

35. 搜索插入位置-LeetCode

心得&#xff1a;這個題也是二分查找&#xff0c;但是有個小技巧&#xff1a;當left>right的時候 left就是要插入的位置。 代碼&#xff1a; 1 class Solution {2 public int searchInsert(int[] nums, int target) {3 if(numsnull||nums.length0)4 …

Kubectl指令集

1 Kubectl指令集 1.1 Master查詢節點信息 [rootmaster1 kubernetes-1.10]# kubectl get nodes 1.2 查詢所有Pod信息 [rootmaster1 ~]# kubectl get pods --namespacekube-system 1.3 查詢故障的Pod信息 [rootmaster1 ~]# kubectl get pods -n kube-sys…

SQL基礎培訓實戰教程[全套]

學習簡介&#xff1a;林楓山根據網上搜索資料進行參考&#xff0c;編寫制作的SQL Server實操學習教程&#xff0c;歡迎下載學習。 下載鏈接目錄如下&#xff1a; 進度0-SQL基礎語法 下載學習文檔 進度1-建數據表-美化版-2018-6-12 下載學習文檔 進度2-關于主鍵-美化…

K8S儀表板Service unavailable故障的解決辦法

K8S儀表板Service unavailable故障的解決辦法 &#xff08;使用Rancher部署Kubernetes后訪問儀表板提示Service unavailable的問題&#xff09; 一、逐項檢查&#xff1a; 1、操作系統Kernel版本&#xff08;3.10以上&#xff09; 2、檢查OS版本&#xff08;Ubuntu16.04.x、…

實驗五報告

一、實驗結論&#xff1a; 1. 二分查找&#xff1a;補足程序ex1_1.cpp// 練習&#xff1a;使用二分查找&#xff0c;在一組有序元素中查找數據項 // 形參是數組&#xff0c;實參是數組名 #include <stdio.h> const int N5; int binarySearch(int x[], int n, int item…

關于瀏覽器內核

介紹一下對瀏覽器內核的理解主要分成兩個部分&#xff1a;渲染引擎(Render Engine)和JS引擎。常見的瀏覽器內核有哪些&#xff1f;Trident內核&#xff1a;IE&#xff0c;360&#xff0c;搜過瀏覽器&#xff1b;Gecko內核&#xff1a;Netscape6及以上版本&#xff0c;Presto內核…