一看就會的AOP事務

文章目錄

  • AOP
    • AOP簡介
      • AOP簡介和作用
      • AOP的應用場景
      • 為什么要學習AOP
    • AOP入門案例
      • 思路分析
      • 代碼實現
      • AOP中的核心概念
    • AOP工作流程
      • AOP工作流程
      • AOP核心概念
      • 在測試類中驗證代理對象
    • AOP切入點表達式
      • 語法格式
      • 通配符
      • 書寫技巧
    • AOP通知類型
      • AOP通知分類
      • AOP通知詳解
  • AOP案例
    • 案例-測量業務層接口萬次執行效率
      • 需求和分析
      • 代碼實現
    • AOP切入點數據獲取
      • 獲取參數
      • 獲取返回值
      • 獲取異常
    • 案例-百度網盤密碼數據兼容處理
      • 需求和分析
      • 代碼實現
  • Spring事務管理
    • Spring事務簡介
      • Spring事務作用
      • 需求和分析
      • 代碼實現
    • Spring事務角色
    • Spring事務相關配置
      • 事務配置
      • 案例-轉賬業務追加日志
      • 代碼實現
      • 事務傳播行為

AOP

AOP簡介

AOP簡介和作用

  • AOP(Aspect Oriented Programming)面向切面編程,一種編程范式,指導開發者如何組織程序結構
  • 作用:在不改變方法源代碼的基礎上對方法進行功能增強
  • Spring理念:無入侵式

AOP的應用場景

  • 在工程運行慢的過程中,對目標方法進行運行耗時統計
  • 對目標方法添加事務管理
  • 對目標方法添加權限訪問控制

為什么要學習AOP

1、簡化開發

  • AOP減少了手動創建動態代理的步驟
  • AOP減少了手動創建動態代理的代碼量

2、靈活性強

  • 手動創建動態代理一次只能代理一個對象
  • AOP可以批量代理多個對象

3、spring事務使用AOP實現

  • Spring的事務管理使用AOP實現

AOP入門案例

思路分析

  1. 導入坐標(pom.xml)
  2. 制作連接點方法(原始操作,dao接口與實現類)
  3. 制作共性功能(通知類與通知)
  4. 定義切入點
  5. 綁定切入點與通知關系(切面)

代碼實現

  1. 導入aop相關坐標
<dependencies><!--spring核心依賴,會將spring-aop傳遞進來--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><!--切入點表達式依賴,目的是找到切入點方法,也就是找到要增強的方法--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>
</dependencies>

image.png

  1. 定義dao接口和實現類
public interface BookDao {public void save();public void update();
}@Repository
public class BookDaoImpl implements BookDao {public void save() {System.out.println(System.currentTimeMillis());System.out.println("book dao save ...");}public void update(){System.out.println("book dao update ...");}
}
  1. 定義通知類,制作通知方法
//通知類必須配置成Spring管理的bean
@Component
public class MyAdvice {public void method(){System.out.println(System.currentTimeMillis());}
}
  1. 定義切點表達式,配置切面(綁定切入點與通知關系)
//通知類必須配置成Spring管理的bean
@Component
//設置當前類為切面類類
@Aspect
public class MyAdvice {//設置切入點,@Pointcut注解要求配置在方法上方@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}//設置在切入點pt()的前面運行當前操作(前置通知)@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
}
  1. 在配置類中進行Spring注解包掃描和開啟AOP功能
@Configuration
@ComponentScan("com.itheima")
//開啟注解開發AOP功能
@EnableAspectJAutoProxy
public class SpringConfig {
}
  1. 編寫測試類和運行結果
public class App {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.update();}
}

AOP中的核心概念

  • 連接點(JoinPoint):正在執行的方法,例如:update()
  • 切入點(PointCut):匹配連接點的式子
    • 在SpringAOP中,一個切入點可以只描述一個具體方法,也可以匹配多個方法
      • 一個具體方法:com.itheima.dao包下的BookDao接口中的無形參無返回值的save方法
      • 匹配多個方法:所有的save方法,所有的get開頭的方法,所有以Dao結尾的接口中的任意方法,所有帶有一個參數的方法
  • 通知(Advice):在切入點前后執行的操作,也就是增強的共性功能
    • 在SpringAop中,功能最終以方法的形式呈現
  • 通知類:通知方法所在的類叫做通知類
  • 切面(Aspect):描述通知與切入點的對應關系,也就是哪些通知方法對應哪些切入點方法

AOP工作流程

AOP工作流程

  1. Spring容器啟動
  2. 讀取所有切面配置中的切入點
  3. 初始化bean,判定bean對應的類中的方法是否匹配到任意切入點
    • 匹配失敗,創建原始對象
    • 匹配成功,創建原始對象(目標對象)的代理對象
  4. 獲取bean執行方法
    • 獲取的bean是原始對象時,調用方法并執行,完成操作
    • 獲取的bean是代理對象時,根據代理對象的運行模式運行原始方法與增強的內容,完成操作

AOP核心概念

  • 目標對象(Target):被代理的對象,也叫原始對象,該對象中的方法沒有任何功能增強。
  • 代理對象(Proxy):代理后生成的對象,由Spring幫我們創建代理對象。

在測試類中驗證代理對象

public class App {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.update();//打印對象的類名System.out.println(bookDao.getClass());}
}

image.png

AOP切入點表達式

語法格式

  • 切入點:要進行增強的方法
  • 切入點表達式:要進行增強的方法的描述方式
    • 描述方式一:執行com.itheima.dao包下的BookDao接口中的無參數update方法
execution(void com.itheima.dao.BookDao.update())
  • 描述方式二:執行com.itheima.dao.impl包下的BookDaoImpl類中的無參數update方法
execution(void com.itheima.dao.impl.BookDaoImpl.update())
  • 切入點表達式標準格式:動作關鍵字(訪問修飾符 返回值 包名.類/接口名.方法名(參數) 異常名)
execution(public User com.itheima.service.UserService.findById(int))
  • 動作關鍵字:描述切入點的行為動作,例如execution表示執行到指定切入點
  • 訪問修飾符:public,private等,可以省略
  • 返回值:寫返回值類型
  • 包名:多級包使用點連接
  • 類/接口名:
  • 方法名:
  • 參數:直接寫參數的類型,多個類型用逗號隔開
  • 異常名:方法定義中拋出指定異常,可以省略

通配符

目的:可以使用通配符描述切入點,快速描述

  • * :單個獨立的任意符號,可以獨立出現,也可以作為前綴或者后綴的匹配符出現

匹配com.itheima包下的任意包中的UserService類或接口中所有find開頭的帶有一個參數的方法

execution(public * com.itheima.*.UserService.find*(*))
  • . . :多個連續的任意符號,可以獨立出現,常用于簡化包名與參數的書寫

匹配com包下的任意包中的UserService類或接口中所有名稱為findById的方法

execution(public User com..UserService.findById(..))
  • + :專用于匹配子類類型
execution(* *..*Service+.*(..))

書寫技巧

  • 所有代碼按照標準規范開發,否則以下技巧全部失效
  • 描述切入點通常描述接口,而不描述實現類
  • 訪問控制修飾符針對接口開發均采用public描述(可省略訪問控制修飾符描述
  • 返回值類型對于增刪改類使用精準類型加速匹配,對于查詢類使用*通配快速描述
  • 包名書寫盡量不使用. .匹配,效率過低,常用*做單個包描述匹配,或精準匹配
  • 接口名/類名書寫名稱與模塊相關的采用*匹配,例如UserService書寫成*Service,綁定業務層接口名
  • 方法名書寫以動詞進行精準匹配,名詞采用_匹配,例如getById書寫成getBy_,selectAll書寫成selectAll
  • 參數規則較為復雜,根據業務方法靈活調整
  • 通常不使用異常作為匹配規則

AOP通知類型

AOP通知分類

  • AOP通知描述了抽取的共性功能,根據共性功能抽取的位置不同,最終運行代碼時要將其加入到合理的位置
  • AOP通知共分為5種類型
    • 前置通知:在切入點方法執行之前執行
    • 后置通知:在切入點方法執行之后執行,無論切入點方法內部是否出現異常,后置通知都會執行。
    • **環繞通知(重點):**手動調用切入點方法并對其進行增強的通知方式。
    • 返回后通知(了解):在切入點方法執行之后執行,如果切入點方法內部出現異常將不會執行。
    • 拋出異常后通知(了解):在切入點方法執行之后執行,只有當切入點方法內部出現異常之后才執行。

AOP通知詳解

  • 前置通知:@Before,當前通知方法在原始切入點方法前運行
  • 后置通知:@After,當前通知方法在原始切入點方法后運行
  • 返回后通知:@AfterReturning,當前通知方法在原始切入點方法正常執行完畢后運行
  • 拋出異常后通知:@AfterThrowing,當前通知方法在原始切入點方法運行拋出異常后執行
  • 環繞通知:@Around,當前通知方法在原始切入點方法前后運行

環繞通知代碼

@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("around before advice ...");Object ret = pjp.proceed();System.out.println("around after advice ...");return ret;
}

環繞通知注意事項

  1. 環繞通知方法形參必須是ProceedingJoinPoint,表示正在執行的連接點,使用該對象的proceed()方法表示對原始對象方法進行調用,返回值為原始對象方法的返回值。
  2. 環繞通知方法的返回值建議寫成Object類型,用于將原始對象方法的返回值進行返回,哪里使用代理對象就返回到哪里。

AOP案例

案例-測量業務層接口萬次執行效率

需求和分析

需求:任意業務層接口執行均可顯示其執行效率(執行時長)
分析

  1. 業務功能:業務層接口執行前后分別記錄時間,求差值得到執行效率
  2. 通知類型選擇前后均可以增強的類型–環繞通知

代碼實現

在上面代碼的基礎上

  1. 編寫通知類
@Component
@Aspect
public class Advice {@Pointcut("execution(public * org.example.dao.BookDao.save())")public void pc(){}@Around("pc()")public Object around(ProceedingJoinPoint pjp) throws Throwable {//獲取執行的簽名對象Signature signature = pjp.getSignature();//獲取類名/類全限定名String className = signature.getDeclaringTypeName();//獲取方法名String methodName = signature.getName();long startTime = System.currentTimeMillis();Object proceed = null;for (int i = 0; i < 10000; i++) {proceed = pjp.proceed();}long endTime = System.currentTimeMillis();System.out.println("萬次執行:"+ className+"."+methodName+"---->" +(endTime-startTime) + "ms");return proceed;}
}
  1. 在Spring配置類中開啟AOP注解功能
@Configuration
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy //開啟AOP注解功能
public class SpringConfig {
}
  1. 運行測試類,查看結果
public class App {public static void main( String[] args ) {//創建ioc容器ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);//獲取beanBookDao bookDao = ctx.getBean(BookDao.class);//執行方法Integer result = bookDao.save();System.out.println(result);
//
//        System.out.println(bookDao.getClass());}
}

AOP切入點數據獲取

獲取參數

  • JoinPoint對象描述了連接點方法的運行狀態,可以獲取到原始方法的調用參數(除了環繞的其他通知)
@Before("pt()")
public void before(JoinPoint jp) {Object[] args = jp.getArgs(); //獲取連接點方法的參數們System.out.println(Arrays.toString(args));
}
  • ProccedingJointPoint是JoinPoint的子類
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {Object[] args = pjp.getArgs(); //獲取連接點方法的參數們System.out.println(Arrays.toString(args));Object ret = pjp.proceed();return ret;
}

獲取返回值

  • 返回后通知可以獲取切入點方法返回值信息,使用形參可以接收對應的返回值
@AfterReturning(value = "pt()",returning = "ret")
public void afterReturning(String ret) { //變量名要和returning="ret"的屬性值一致System.out.println("afterReturning advice ..."+ret);
}
  • 環繞通知中可以手工書寫對原始方法的調用,得到的結果即為原始方法的返回值
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {// 手動調用連接點方法,返回值就是連接點方法的返回值Object ret = pjp.proceed();return ret;
}

獲取異常

  • 拋出異常后通知可以獲取切入點方法中出現的異常信息,使用形參可以接收對應的異常對象
@AfterThrowing(value = "pt()",throwing = "t")
public void afterThrowing(Throwable t) {//變量名要和throwing = "t"的屬性值一致System.out.println("afterThrowing advice ..."+ t);
}
  • 拋出異常后通知可以獲取切入點方法運行的異常信息,使用形參可以接收運行時拋出的異常對象
@Around("pt()")
public Object around(ProceedingJoinPoint pjp)  {Object ret = null;//此處需要try...catch處理,catch中捕獲到的異常就是連接點方法中拋出的異常try {ret = pjp.proceed();} catch (Throwable t) {t.printStackTrace();}return ret;
}

案例-百度網盤密碼數據兼容處理

需求和分析

需求:對百度網盤分享鏈接輸入密碼時尾部多輸入的空格做兼容處理
image.png
分析

  1. 在業務方法執行之前對所有的輸入參數進行格式處理——trim()
  2. 使用處理后的參數調用原始方法——環繞通知中存在對原始方法的調用

代碼實現

  1. 編寫service類和dao類
//-------------service層代碼-----------------------
public interface ResourcesService {public boolean openURL(String url ,String password);
}
@Service
public class ResourcesServiceImpl implements ResourcesService {@Autowiredprivate ResourcesDao resourcesDao;public boolean openURL(String url, String password) {return resourcesDao.readResources(url,password);}
}
//-------------dao層代碼-----------------------
public interface ResourcesDao {boolean readResources(String url, String password);
}
@Repository
public class ResourcesDaoImpl implements ResourcesDao {public boolean readResources(String url, String password) {System.out.println(password.length());//模擬校驗return password.equals("root");}
}
  1. 編寫通知類
@Component
@Aspect
public class DataAdvice {@Pointcut("execution(boolean com.itheima.service.*Service.*(*,*))")private void servicePt(){}@Around("DataAdvice.servicePt()")public Object trimStr(ProceedingJoinPoint pjp) throws Throwable {Object[] args = pjp.getArgs();for (int i = 0; i < args.length; i++) {//判斷參數是不是字符串if(args[i].getClass().equals(String.class)){args[i] = args[i].toString().trim();}}Object ret = pjp.proceed(args);return ret;}
}
  1. 在Spring配置類上開啟AOP注解功能
@Configuration
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy
public class SpringConfig {
}
  1. 運行測試類,查看結果
public class App {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);ResourcesService resourcesService = ctx.getBean(ResourcesService.class);boolean flag = resourcesService.openURL("http://pan.baidu.com/haha", "root ");System.out.println(flag);}
}

Spring事務管理

Spring事務簡介

Spring事務作用

  • 事務作用:在數據層保障一系列的數據庫操作同成功同失敗
  • Spring事務作用:在數據層或業務層保障一系列的數據庫操作同成功同失敗

image.png

需求和分析

  • 需求:實現任意兩個賬戶間轉賬操作
  • 需求微縮:A賬戶減錢,B賬戶加錢
  • 分析:
    ①:數據層提供基礎操作,指定賬戶減錢(outMoney),指定賬戶加錢(inMoney)
    ②:業務層提供轉賬操作(transfer),調用減錢與加錢的操作
    ③:提供2個賬號和操作金額執行轉賬操作
    ④:基于Spring整合MyBatis環境搭建上述操作
  • 結果分析:
    ①:程序正常執行時,賬戶金額A減B加,沒有問題
    ②:程序出現異常后,轉賬失敗,但是異常之前操作成功,異常之后操作失敗,整體業務失敗

代碼實現

環境準備
Spring整合Mybatis相關代碼(依賴、JdbcConfig、MybatisConfig、SpringConfig)省略。

public interface AccountDao {@Update("update tbl_account set money = money + #{money} where name = #{name}")void inMoney(@Param("name") String name, @Param("money") Double money);@Update("update tbl_account set money = money - #{money} where name = #{name}")void outMoney(@Param("name") String name, @Param("money") Double money);
}public interface AccountService {/*** 轉賬操作* @param out 傳出方* @param in 轉入方* @param money 金額*/public void transfer(String out,String in ,Double money) ;
}@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;public void transfer(String out,String in ,Double money) {accountDao.outMoney(out,money);int i = 1/0;accountDao.inMoney(in,money);}
}
  1. 在業務層接口上添加Spring事務管理
public interface AccountService {//配置當前接口方法具有事務@Transactionalpublic void transfer(String out,String in ,Double money) ;
}

注意事項

  • Spring注解式事務通常添加在業務層接口中而不會添加到業務層實現類中,降低耦合
  • 注解式事務可以添加到業務方法上表示當前方法開啟事務,也可以添加到接口上表示當前接口所有方法開啟事務
  1. 設置事務管理器(將事務管理器添加到IOC容器中)

可以在JdbcConfig中配置事務管理器

//配置事務管理器,mybatis使用的是jdbc事務
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;
}

注意事項

  • 事務管理器要根據實現技術進行選擇
  • MyBatis框架使用的是JDBC事務
  1. 開啟注解式事務驅動
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//開啟注解式事務驅動
@EnableTransactionManagement
public class SpringConfig {
}
  1. 運行測試類,查看結果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {@Autowiredprivate AccountService accountService;@Testpublic void testTransfer() throws IOException {accountService.transfer("Tom","Jerry",100D);}
}

Spring事務角色

  • 事務管理員:發起事務方,在Spring中通常指代業務層開啟事務的方法
  • 事務協調員:加入事務方,在Spring中通常指代數據層方法,也可以是業務層方法

image.png

Spring事務相關配置

事務配置

image.png
說明:對于RuntimeException類型異常或者Error錯誤,Spring事務能夠進行回滾操作。但是對于編譯器異常,Spring事務是不進行回滾的,所以需要使用rollbackFor來設置回滾的異常。

案例-轉賬業務追加日志

需求和分析

  • 需求:實現任意兩個賬戶間轉賬操作,并對每次轉賬操作在數據庫進行留痕
  • 需求微縮:A賬戶減錢,B賬戶加錢,數據庫記錄日志
  • 分析:
    ①:基于轉賬操作案例添加日志模塊,實現數據庫中記錄日志
    ②:業務層轉賬操作(transfer),調用減錢、加錢與記錄日志功能
  • 實現效果預期:
    無論轉賬操作是否成功,均進行轉賬操作的日志留痕
  • 存在的問題:
    日志的記錄與轉賬操作隸屬同一個事務,同成功同失敗
  • 實現效果預期改進:
    無論轉賬操作是否成功,日志必須保留
  • 事務傳播行為:事務協調員對事務管理員所攜帶事務的處理態度

image.png

代碼實現

準備工作

USE spring_db;
CREATE TABLE tbl_log(id INT PRIMARY KEY AUTO_INCREMENT,info VARCHAR(255),createDate DATE
);
public interface LogService {//propagation設置事務屬性:傳播行為設置為當前操作需要新事務@Transactionalvoid log(String out, String in, Double money);
}@Service
public class LogServiceImpl implements LogService {@Autowiredprivate LogDao logDao;public void log(String out,String in,Double money ) {logDao.log("轉賬操作由"+out+"到"+in+",金額:"+money);}
}public interface LogDao {@Insert("insert into tbl_log (info,createDate) values(#{info},now())")void log(String info);
}
  1. 在AccountServiceImpl中調用logService中添加日志的方法
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Autowiredprivate LogService logService;public void transfer(String out,String in ,Double money) {try{accountDao.outMoney(out,money);int i = 1/0;accountDao.inMoney(in,money);}finally {logService.log(out,in,money);}}
}
  1. 在LogService的log()方法上設置事務的傳播行為
public interface LogService {//propagation設置事務屬性:傳播行為設置為當前操作需要新事務@Transactional(propagation = Propagation.REQUIRES_NEW)void log(String out, String in, Double money);
}
  1. 運行測試類,查看結果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {@Autowiredprivate AccountService accountService;@Testpublic void testTransfer() throws IOException {accountService.transfer("Tom","Jerry",50D);}
}

事務傳播行為

image.png

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

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

相關文章

Linux bc命令(bc指令)(基本計算器)(任意精度計算語言:支持浮點數運算、變量賦值和自定義函數等)

文章目錄 bc命令文檔英文中文 Linux bc 命令詳解bc 命令的基本用法啟動 bc 環境進行基本計算退出 bc bc 中的數學功能執行高級數學計算平方根和指數函數對數函數 處理精度問題 變量和數組變量賦值和使用數組的使用 創建和使用自定義函數 bc 命令的高級用法在腳本中使用 bc基本腳…

Google I/O 大會 | 精彩看點一覽

作者 / 開發者關系和開源總監 Timothy Jordan 2024 年 Google I/O 大會于北京時間 5 月 15 日 1:00am 在加利福尼亞的山景城以 Google 主題演講直播拉開序幕。隨后&#xff0c;在北京時間 4:30am 舉行開發者主題演講。大家可前往回看 "Google 主題演講" 以及 "開…

AIGC時代已至,你準備好抓住機遇了嗎?

一、行業前景 AIGC&#xff0c;即人工智能生成內容&#xff0c;是近年來人工智能領域中發展迅猛的一個分支。隨著大數據、云計算、機器學習等技術的不斷進步&#xff0c;AIGC已經取得了顯著的成果&#xff0c;并且在廣告、游戲、自媒體、教育、電商等多個領域實現了廣泛應用。…

AI寫算法:支持向量機(SVM)

在Python中&#xff0c;我們可以使用scikit-learn庫來實現支持向量機&#xff08;SVM&#xff09;。以下是一個簡單的示例&#xff0c;演示如何使用scikit-learn的SVC類來訓練一個SVM分類器&#xff0c;并使用它對一些數據進行預測。 python復制代碼 # 導入必要的庫 from skle…

圖像中的attention及QKV機制解釋

簡單記錄/推薦兩篇博客&#xff0c;后續細化寫一下&#xff1a; 圖像中的各類 attention https://blog.csdn.net/weixin_44505185/article/details/127013204 Cross-attention的直觀理解 首先理解&#xff0c;cross-attention 是兩個不同向量間的相關計算&#xff0c;一般Q…

DolphinScheduler(海豚調度)- docker部署實戰

1.官方文檔 https://dolphinscheduler.apache.org/zh-cn/docs/3.2.1/guide/start/docker 2.docker環境安裝 版本情況&#xff08;這個地方踩了不少坑&#xff09;&#xff1a;docker-26.1.2&#xff0c;docker-compose-v2.11.0。 具體可使用我上傳的安裝包&#xff0c;一鍵安…

leetcode題目55

跳躍游戲 中等 給你一個非負整數數組 nums &#xff0c;你最初位于數組的 第一個下標 。數組中的每個元素代表你在該位置可以跳躍的最大長度。 判斷你是否能夠到達最后一個下標&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 示例 1…

MT3037 新月軒就餐

思路&#xff1a; 此題每道菜的價錢相同&#xff0c;想最小化付的錢即求最小區間長度可以滿足“品嘗到所有名廚手藝”。 使用雙端隊列存儲元素&#xff0c;隊尾不斷向后遍歷&#xff1a;頭->尾 如果隊頭隊尾&#xff0c;則隊頭往右移一格&#xff0c;直到區間不同元素數m…

Docker部署MaxKB詳細步驟(window系統)

上面章節已經實現了ollama李現部署llama3&#xff0c;并實現了一些簡單的問答&#xff0c;但是問答的界面是在命令提示符中&#xff0c;交互很不友好&#xff0c;也不方便局域網其他用戶訪問&#xff0c;所以這節用docker部署MaxKB實現網頁訪問llama3&#xff0c;首先電腦上需要…

分布式系統的一致性與共識算法(四)

Etcd與Raft算法 Raft保證讀請求Linearizability的方法: 1.Leader把每次讀請求作為一條日志記錄&#xff0c;以日志復制的形式提交&#xff0c;并應用到狀態機后&#xff0c;讀取狀態機中的數據返回(一次RTT、一次磁盤寫)2.使用Leader Lease&#xff0c;保證整個集群只有一個L…

使用Flask-RESTful構建RESTful API

文章目錄 安裝Flask-RESTful導入模塊和類創建一個資源類運行應用測試API總結 Flask是一個輕量級的Python web開發框架&#xff0c;而Flask-RESTful是一個基于Flask的擴展&#xff0c;專門用于構建RESTful API。它提供了一些幫助類和方法&#xff0c;使構建API變得更加簡單和高效…

詳細分析Vue3中的reactive(附Demo)

目錄 1. 基本知識2. 用法3. Demo 1. 基本知識 reactive 是一個函數&#xff0c;用于將一個普通的 JavaScript 對象轉換為響應式對象 當對象的屬性發生變化時&#xff0c;Vue 會自動追蹤這些變化&#xff0c;并觸發相應的更新 Vue2沒有&#xff0c;而Vue3中有&#xff0c;為啥…

公司郵箱是什么?公司郵箱和個人郵箱有什么不同?

公司郵箱是企業用來收發郵件的專業版電子郵箱&#xff0c;不同于個人郵箱的簡單功能和有限的存儲空間&#xff0c;公司郵箱的功能更加豐富&#xff0c;能夠滿足企業的日常辦公和協作需求。本文將為您詳細講解公司郵箱和個人郵箱的區別&#xff0c;以供您選擇更適合自己的郵箱類…

嵌入式——C51版本Keil環境搭建

&#x1f3ac; 秋野醬&#xff1a;《個人主頁》 &#x1f525; 個人專欄:《Java專欄》《Python專欄》 ??心若有所向往,何懼道阻且長 文章目錄 目標搭建流程下載與安裝激活STC環境添加校驗是否導入STC環境 目標 ● 了解C51版本Keil開發環境的概念和用途 ● 掌握C51版本Keil環…

2024年NOC大賽創客智慧(西瓜創客)Python復賽編程真題模擬試卷包含答案

NOC復賽python模擬題 1.編寫一個程序&#xff0c;提示用戶輸人一個矩形的長度和寬度&#xff0c;并輸出其面積, 2.試計算在區間 1 到 n的所有整數中,數字x(0≤x≤9)共出現了多少次?例如在 1到11 中&#xff0c;即在 1,2,3.45,6.7,8.9,10,11 中&#xff0c;數字 1出現了 4 次.…

鴻蒙生態融合進行時!菊風啟動適配HarmonyOS NEXT,賦能原生應用實時

??今日話題 鴻蒙HarmonyOS NEXT 自華為公開宣布鴻蒙 HarmonyOS NEXT 系統以來&#xff0c;該系統受到了業內廣泛關注&#xff0c;和以往鴻蒙系統不同的是該系統底座完全由華為自研&#xff0c;摒棄了 Linux 內核和安卓 AOSP 代碼&#xff0c;僅兼容鴻蒙內核及鴻蒙系統的應用…

Leetcode---1.兩數之和 (詳解加哈希表解釋和使用)

文章目錄 題目 [兩數之和](https://leetcode.cn/problems/two-sum/)方法一&#xff1a;暴力枚舉代碼方法二&#xff1a;哈希表代碼 哈希表哈希表的基本概念哈希函數&#xff08;Hash Function&#xff09;&#xff1a;沖突&#xff08;Collision&#xff09;&#xff1a;鏈地址…

windows驅動開發-PCI討論(一)

前面描述中斷的時候&#xff0c;我們曾經多次體積PCI&#xff0c;甚至提供了一些PCI的相關知識&#xff0c;但是整個PCI是一個很大的體系&#xff0c;專門記錄這個體系超出了這個系列的范疇&#xff0c;有興趣的可以到PCI官網了解詳細的情況。 但是還是會花費一些時間討論PCI技…

Pytorch入門實戰 P10-使用pytorch實現車牌識別

目錄 前言 一、MyDataset文件 二、完整代碼&#xff1a; 三、結果展示&#xff1a; 四、添加accuracy值 &#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 | 接輔導、項目定制 本周的學習內容是&#xff0…

SEO:搜索引擎蜘蛛名稱UA(user-agent)

最近網站在做統計功能&#xff0c;想著統計下蜘蛛爬行記錄&#xff0c;看看都有哪些搜索引擎蜘蛛經常關顧&#xff0c;故而好進行相應的對策改變。都知道搜索引擎對一個網站很重要,是很多網站重要的流量來源。熟悉各大搜索引擎的蜘蛛就顯得必要。 做SEO優化的通常會說蜘蛛爬得越…