代理模式概述

1.代理模式概述

學習內容

1)概述

為什么要有 “代理” ?

  • 生活中就有很多例子,比如委托業務,黃牛(票販子)等等
  • 代理就是被代理者沒有能力或者不愿意去完成某件事情,需要找個人代替自己去完成這件事,這才是“代理”存在的原因。
  • 例如要租房子,房產中介可以在我們住房前代理我們找房子。中介就是代理,而自己就是被代理了。

在代碼設計中,代理模式作用主要就是讓 “被代理對象” 的某個方法執行之或者執行之加入其他增強邏輯。

前增強 : 例如獲取當前時間被代理對象調用方法后增強 : 例如獲取當前時間計算方法執行的時間

2)代理的前提條件 : 掌握 !

  • 抽象角色 :聲明功能
  • 代理角色 :實現抽象功能 , 完成代理邏輯
  • 被代理角色 :實現抽象功能

意味著被代理角色和代理角色有著共同的父類型(既抽象角色) , 例如我要租房子, 我只能找房產中介, 不能找票販子
在這里插入圖片描述

  • 代理模式存在兩種實現方式:

    • 靜態代理
    • 動態代理

知識小結

  1. 請說出代碼中代理模式的作用?

    代理角色對 被代理就角色某個方法執行的前或者后進行 功能增強
    
  2. 請說出代理模式中的三個角色?

    抽象角色
    代理角色
    被代理角色
    

==============================================================================================================

1.1 靜態代理

學習目標

  • 能夠寫出靜態代理模式代碼

內容講解

  • 靜態代理是由程序員創建 或 工具生成代理類的源碼,再編譯代理類。

    在程序運行前就已經存在代理類的字節碼文件,代理類和被代理類的關系在運行前就確定了。

    簡單理解 : 在程序運行之前 , 代理類就存在了,這就是靜態代理 ; 動態代理是程序運行時動態生成代理類

  • 靜態代理實現的步驟 :

    • 存在一個抽象角色
    • 定義被代理角色
    • 定義代理,增強被代理角色的功能

案例實踐 :

  • 以現實中經紀人代理明星

已知存在接口:

// 1.抽象角色
interface Star {// 真人秀方法double liveShow(double money);void sleep();
}

定義被代理類:

  • 定義王寶強類,實現Star方法
// - 定義被代理角色(寶強)
class BaoQiang implements Star {@Overridepublic double liveShow(double money) {System.out.println("寶強參加了一個真人秀活動賺了" + money + "錢");return money;}@Overridepublic void sleep() {System.out.println("寶強累了 , 睡覺...");}
}

定義代理類:

  • 定義宋喆經紀人類
// - 定義代理角色(宋喆),增強被代理角色的功能
class SongZhe implements Star {private BaoQiang baoQiang;public SongZhe(BaoQiang baoQiang) {this.baoQiang = baoQiang;}@Overridepublic double liveShow(double money) {// 前增強System.out.println("宋喆幫寶強拉了一個真人秀的活動,獲取傭金" + money * 0.8 + "元");// 被代理角色的功能double result = baoQiang.liveShow(money * 0.2);// 后增強System.out.println("宋喆幫寶強把賺的錢存了起來...");return result;}@Overridepublic void sleep() {// 前增強System.out.println("宋喆幫寶強定了一家五星級大酒店");baoQiang.sleep();// 后增強System.out.println("宋喆幫寶強退房...");}
}

定義測試類進行測試

/*靜態代理實現的步驟  :- 存在一個抽象角色- 定義被代理角色(寶強)- 定義代理角色(宋喆),增強被代理角色的功能*/
public class StaticAgentDemo {public static void main(String[] args) {// 創建被代理角色 , 沒有任何增強BaoQiang baoQiang = new BaoQiang();double result = baoQiang.liveShow(1000);System.out.println(result);baoQiang.sleep();System.out.println("===========================");// 創建代碼角色對象 , 可以對被代理角色功能做前后增強SongZhe songZhe = new SongZhe(baoQiang);double result2 = songZhe.liveShow(1000);System.out.println(result2);songZhe.sleep();}
}

關系圖 :

在這里插入圖片描述
宋喆和寶強都有共同的父類型。他們的業務方法都是一樣。

靜態代理和裝飾模式的對比 :

? BufferedRead(FileRead)

? 1 裝飾設計模式是功能擴展功能,在原有的功能基礎之上增加了新的功能

? 2 而代理主要對功能的前后做了增強

知識小結

  • 請問什么叫做靜態代理?

    代碼執行前,已經確定了代理的代碼邏輯。

2. 動態代理

學習目標

  • 能夠知道什么是動態代理
  • 能夠熟悉動態代理相關API
  • 能夠熟悉動態代理代碼執行流程

內容講解

1)概述

在實際開發過程中往往我們自己不會去創建代理類而是通過JDK提供的Proxy類在程序運行時,運用反射機制動態創建而成

這就是我們所謂的動態代理

與靜態代理之間的區別,在于不用自己寫代理類

雖然我們不需要自己定義代理類創建代理對象

但是我們要定義對被代理對象直接訪問方法的攔截,原因就是對攔截的方法做增強

動態代理技術在框架中使用居多,例如:很快要學到的數據庫框架MyBatis框架等一些主流框架技術(Spring,SpringMVC)中都使用了動態代理技術。

2)API學習

Proxy類
  • java.lang.reflect.Proxy類提供了用于創建動態代理類和對象的靜態方法

? 它還是由這些方法創建的所有動態代理類的超類(代理類的父類是Proxy)。

public static Object newProxyInstance (ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h ) 獲取代理對象的方法 - 返回值:該方法返回就是動態生成的代理對象
- 參數列表說明:1. ClassLoader loader 	- 定義代理類的類加載器2. Class<?>[] interfaces 	- 代理類要實現的接口列表,要求與被代理類的接口一樣。3. InvocationHandler h 	- 就是具體實現代理邏輯的接口
InvocationHandler接口

源碼 :

interface InvocationHandler{public Object invoke(Object proxy, Method method, Object[] args);  //代理邏輯
}

java.lang.reflect.InvocationHandler是代理對象的實際處理代理邏輯的接口,具體代理實現邏輯在其 invoke 方法中。所有代理對象調用的方法,執行是都會經過invoke。因此如果要對某個方法進行代理增強,就可以在這個invoke方法中進行定義。

方法說明如下:

public Object invoke(Object proxy, Method method, Object[] args);1. 返回值:方法被代理后執行的結果。
2. 參數列表:1. proxy  - 就是代理對象2. method - 代理對象調用的方法3. args   - 代理對象調用方法傳入參數值的對象數組.

3)代碼實踐

將經紀人代理明星的案例使用動態代理實現

  1. 把父接口定義
  2. 定義被代理類:寶強
  3. 動態生成代理類
  4. 定義代理邏輯
package com.itheima.dynamicproxy_demo;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 測試類
/*1 Proxy類 :public static Object newProxyInstance (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h ) 獲取代理對象的方法- 返回值:該方法返回就是動態生成的代理對象- 參數列表說明:1. ClassLoader loader 	- 定義代理類的類加載器2. Class<?>[] interfaces 	- 代理類要實現的接口列表,要求與被代理類的接口一樣。3. InvocationHandler h 	- 就是具體實現代理邏輯的接口2 InvocationHandler接口public Object invoke(Object proxy, Method method, Object[] args);1. 返回值:方法被代理后執行的結果。2. 參數列表:1. proxy  - 就是代理對象2. method - 代理對象調用的方法3. args   - 代理對象調用方法傳入參數值的對象數組.*/
public class DynamicProxyDemo {public static void main(String[] args) {// Proxy.newProxyInstance(被代理角色的類加載器 , 被代理角色實現的所有接口 , 處理器);// 被代理角色的類加載器ClassLoader classLoader = BaoQiang.class.getClassLoader();// 被代理角色實現的所有接口Class<?>[] interfaces = BaoQiang.class.getInterfaces();// 創建被代理角色對象BaoQiang baoQiang = new BaoQiang();// 代理角色 , 動態生成Star songZhe = (Star) Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(baoQiang));// 代理角色調用liveShow方法songZhe.liveShow(1000);songZhe.sleep();}
}// 定義InvocationHandler接口的實現類
class MyInvocationHandler implements InvocationHandler {private BaoQiang baoQiang;public MyInvocationHandler(BaoQiang baoQiang) {this.baoQiang = baoQiang;}// invoke什么時候會執行????// 代理對象調用功能 , 就會觸發invoke方法// 此方法對被代理角色的功能做增強// method : 代理對象調用功能就會觸發invoke方法 , invoke方法中的method代表的就是調用的方法對象@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("liveShow")) {// 代理角色對象調用liveShow方法 , 此位置會攔截// 前增強System.out.println("宋喆幫寶強拉了一個真人秀的活動,獲取傭金" + (double) args[0] * 0.8 + "元");Object result = method.invoke(baoQiang, (double) args[0] * 0.2);// 后增強System.out.println("宋喆幫寶強把賺的錢存了起來...");return result;} else if (method.getName().equals("sleep")) {// 代理角色對象調用sleep方法 , 此位置會攔截method.invoke(baoQiang);} else {// 除了liveShow和sleep方法 , 會執行else代碼塊中的內容}return null;}
}//  1 抽象角色
interface Star {double liveShow(double money);void sleep();
}// 2 定義被代理角色(寶強)
class BaoQiang implements Star {@Overridepublic double liveShow(double money) {System.out.println("寶強參加了一個真人秀活動賺了" + money + "錢");return money;}@Overridepublic void sleep() {System.out.println("寶強累了 , 睡覺...");}
}

動態代理調用流程:

在這里插入圖片描述

小結

  1. 什么是動態代理?
    在代碼執行前,沒有代理類,代理類是在程序運行的時候動態生成.

    Proxy.newProxyInstance
    
  2. 動態代理有什么好處?
    動態代理可以為 “被代理對象” 的所有接口的所有方法做代理,動態代理可以在不改變方法源碼的情況下,實現對方法功能的增強。

  3. 動態代理相關的API有哪些?

    Proxypublic static Object newProxyInstance(類加載器,接口列表,調用處理器)類加載器 = 被代理對象.getClass().getClassLoader();接口列表 = 被代理對象.getClass().getInterfaces();調用處理器 = new InvocationHandler(){   實現  invoke 方法 };InvocationHandlerpublic Object invoke(代理對象,方法對象,方法的實參類別) 該方法執行時機是,代理對象調用方法時觸發執行
    
  4. 動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。

  5. 缺點 :只能針對接口的實現類做代理對象,普通類是不能做代理對象的。

    后面框架學習的時候會接觸到CGLib(Code Genneration Library ): 可以實現對類的代理。

    數據庫連接池與JDBC Template

數據庫連接池

1. 概念:其實就是一個容器(集合),存放數據庫連接的容器。當系統初始化好后,容器被創建,容器中會申請一些連接對象,當用戶來訪問數據庫時,從容器中獲取連接對象,用戶訪問完之后,會將連接對象歸還給容器。2. 好處:1. 節約資源2. 用戶訪問高效3. 實現:1. 標準接口:DataSource   javax.sql包下的1. 方法:* 獲取連接:getConnection()* 歸還連接:Connection.close()。如果連接對象Connection是從連接池中獲取的,那么調用Connection.close()方法,則不會再關閉連接了。而是歸還連接2. 一般我們不去實現它,有數據庫廠商來實現1. C3P0:數據庫連接池技術2. Druid:數據庫連接池實現技術,由阿里巴巴提供的4. C3P0:數據庫連接池技術* 步驟:1. 導入jar包 (兩個) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,* 不要忘記導入數據庫驅動jar包2. 定義配置文件:* 名稱: c3p0.properties 或者 c3p0-config.xml* 路徑:直接將文件放在src目錄下即可。3. 創建核心對象 數據庫連接池對象 ComboPooledDataSource4. 獲取連接: getConnection* 代碼://1.創建數據庫連接池對象DataSource ds  = new ComboPooledDataSource();//2. 獲取連接對象Connection conn = ds.getConnection();
5. Druid:數據庫連接池實現技術,由阿里巴巴提供的1. 步驟:1. 導入jar包 druid-1.0.9.jar2. 定義配置文件:* 是properties形式的* 可以叫任意名稱,可以放在任意目錄下3. 加載配置文件。Properties4. 獲取數據庫連接池對象:通過工廠來來獲取  DruidDataSourceFactory5. 獲取連接:getConnection* 代碼://3.加載配置文件Properties pro = new Properties();InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");pro.load(is);//4.獲取連接池對象DataSource ds = DruidDataSourceFactory.createDataSource(pro);//5.獲取連接Connection conn = ds.getConnection();2. 定義工具類1. 定義一個類 JDBCUtils2. 提供靜態代碼塊加載配置文件,初始化連接池對象3. 提供方法1. 獲取連接方法:通過數據庫連接池獲取連接2. 釋放資源3. 獲取連接池的方法* 代碼:public class JDBCUtils {//1.定義成員變量 DataSourceprivate static DataSource ds ;static{try {//1.加載配置文件Properties pro = new Properties();pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));//2.獲取DataSourceds = DruidDataSourceFactory.createDataSource(pro);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}/*** 獲取連接*/public static Connection getConnection() throws SQLException {return ds.getConnection();}/*** 釋放資源*/public static void close(Statement stmt,Connection conn){/* if(stmt != null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();//歸還連接} catch (SQLException e) {e.printStackTrace();}}*/close(null,stmt,conn);}

?

		    public static void close(ResultSet rs , Statement stmt, Connection conn){

?

		        if(rs != null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}

?

		        if(stmt != null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();//歸還連接} catch (SQLException e) {e.printStackTrace();}}}/*** 獲取連接池方法*/public static DataSource getDataSource(){return  ds;}}

Spring JDBC

* Spring框架對JDBC的簡單封裝。提供了一個JDBCTemplate對象簡化JDBC的開發
* 步驟:1. 導入jar包2. 創建JdbcTemplate對象。依賴于數據源DataSource* JdbcTemplate template = new JdbcTemplate(ds);3. 調用JdbcTemplate的方法來完成CRUD的操作* update():執行DML語句。增、刪、改語句* queryForMap():查詢結果將結果集封裝為map集合,將列名作為key,將值作為value 將這條記錄封裝為一個map集合* 注意:這個方法查詢的結果集長度只能是1* queryForList():查詢結果將結果集封裝為list集合* 注意:將每一條記錄封裝為一個Map集合,再將Map集合裝載到List集合中* query():查詢結果,將結果封裝為JavaBean對象* query的參數:RowMapper* 一般我們使用BeanPropertyRowMapper實現類。可以完成數據到JavaBean的自動封裝* new BeanPropertyRowMapper<類型>(類型.class)* queryForObject:查詢結果,將結果封裝為對象* 一般用于聚合函數的查詢4. 練習:* 需求:1. 修改1號數據的 salary 為 100002. 添加一條記錄3. 刪除剛才添加的記錄4. 查詢id為1的記錄,將其封裝為Map集合5. 查詢所有記錄,將其封裝為List6. 查詢所有記錄,將其封裝為Emp對象的List集合7. 查詢總記錄數* 代碼:import cn.itcast.domain.Emp;import cn.itcast.utils.JDBCUtils;import org.junit.Test;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import java.sql.Date;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;import java.util.Map;public class JdbcTemplateDemo2 {//Junit單元測試,可以讓方法獨立執行

?

			    //1. 獲取JDBCTemplate對象private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());/*** 1. 修改1號數據的 salary 為 10000*/@Testpublic void test1(){//2. 定義sqlString sql = "update emp set salary = 10000 where id = 1001";//3. 執行sqlint count = template.update(sql);System.out.println(count);}/*** 2. 添加一條記錄*/@Testpublic void test2(){String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";int count = template.update(sql, 1015, "郭靖", 10);System.out.println(count);}/*** 3.刪除剛才添加的記錄*/@Testpublic void test3(){String sql = "delete from emp where id = ?";int count = template.update(sql, 1015);System.out.println(count);}/*** 4.查詢id為1001的記錄,將其封裝為Map集合* 注意:這個方法查詢的結果集長度只能是1*/@Testpublic void test4(){String sql = "select * from emp where id = ? or id = ?";Map<String, Object> map = template.queryForMap(sql, 1001,1002);System.out.println(map);//{id=1001, ename=孫悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}}/*** 5. 查詢所有記錄,將其封裝為List*/@Testpublic void test5(){String sql = "select * from emp";List<Map<String, Object>> list = template.queryForList(sql);for (Map<String, Object> stringObjectMap : list) {System.out.println(stringObjectMap);}}/*** 6. 查詢所有記錄,將其封裝為Emp對象的List集合*/@Testpublic void test6(){String sql = "select * from emp";List<Emp> list = template.query(sql, new RowMapper<Emp>() {@Overridepublic Emp mapRow(ResultSet rs, int i) throws SQLException {Emp emp = new Emp();int id = rs.getInt("id");String ename = rs.getString("ename");int job_id = rs.getInt("job_id");int mgr = rs.getInt("mgr");Date joindate = rs.getDate("joindate");double salary = rs.getDouble("salary");double bonus = rs.getDouble("bonus");int dept_id = rs.getInt("dept_id");emp.setId(id);emp.setEname(ename);emp.setJob_id(job_id);emp.setMgr(mgr);emp.setJoindate(joindate);emp.setSalary(salary);emp.setBonus(bonus);emp.setDept_id(dept_id);return emp;}});

?

			        for (Emp emp : list) {System.out.println(emp);}}/*** 6. 查詢所有記錄,將其封裝為Emp對象的List集合*/@Testpublic void test6_2(){String sql = "select * from emp";List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));for (Emp emp : list) {System.out.println(emp);}}/*** 7. 查詢總記錄數*/@Testpublic void test7(){String sql = "select count(id) from emp";Long total = template.queryForObject(sql, Long.class);System.out.println(total);}}

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

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

相關文章

Nginx+Tomcat負載均衡、動靜分離實例詳細部署

一、反向代理兩種模式 四層反向代理 基于四層的iptcp/upd端口的代理 他是http塊同一級&#xff0c;一般配置在http塊上面。 他是需要用到stream模塊的&#xff0c;一般四層里面沒有自帶&#xff0c;需要編譯安裝一下。并在stream模塊里面添加upstream 服務器名稱&#xff0c;…

kafka生產者冪等與事務

目錄 前言&#xff1a; 冪等 事務 總結&#xff1a; 參考資料 前言&#xff1a; Kafka 消息交付可靠性保障以及精確處理一次語義的實現。 所謂的消息交付可靠性保障&#xff0c;是指 Kafka 對 Producer 和 Consumer 要處理的消息提供什么樣的承諾。常見的承諾有以下三…

No view found for id 0x7f0901c3 for fragment解決以及線上bug排查技巧

情景再現 開發這么久&#xff0c;不知道你們是否也經歷過這樣的情況&#xff0c;測試或者用戶&#xff0c;反饋app閃退&#xff0c;結果你自己打開開發工具&#xff0c;去調試&#xff0c;一切正常&#xff0c;然后閃退還是存在&#xff0c;只是在開發環境中不能重現。這種情況…

boost下的asio異步高并發tcp服務器搭建

C 網絡編程 asio 使用總結 - 知乎 (zhihu.com) 基于Boost::asio的多線程異步TCP服務器&#xff0c;實現了io_service線程池&#xff0c;測試了1萬左右的并發訪問&#xff0c;讀寫無壓力_boost asio支持最大并發_E404的博客-CSDN博客 單線程 server.cpp #include <cstdlib&g…

【ARM 嵌入式 編譯系列 11.1 -- GCC __attribute__((aligned(x)))詳細介紹】

文章目錄 __attribute__((aligned(x)))詳細介紹其它對齊方式 上篇文章&#xff1a;ARM 嵌入式 編譯系列 11 – GCC attribute&#xff08;(packed)&#xff09;詳細介紹 attribute((aligned(x)))詳細介紹 __attribute__((aligned(x))) 是 GCC 編譯器的一個特性&#xff0c;它可…

SpringBoot代理訪問本地靜態資源400 404

SpringBoot代理訪問靜態資源400 404 背景&#xff1a;pdf文件上傳到linux服務器上&#xff0c;使用SpringBoot代理訪問問題&#xff1a;訪問過程中可能會出現400、404問題 前提&#xff1a;保證有文件&#xff0c;并且文件路徑正確 SpringBoot如何配置靜態資源代理&#xff0…

Flutter實現倒計時功能,秒數轉時分秒,然后倒計時

Flutter實現倒計時功能 發布時間&#xff1a;2023/05/12 本文實例為大家分享了Flutter實現倒計時功能的具體代碼&#xff0c;供大家參考&#xff0c;具體內容如下 有一個需求&#xff0c;需要在頁面進行顯示倒計時&#xff0c;倒計時結束后&#xff0c;做相應的邏輯處理。 實…

Antd的日期選擇器中文化配置

當你使用antd的日期選擇器后&#xff0c;你會發現日期什么都是英文的&#xff1a;即便你已經在項目中配置了中文化&#xff1a; 我確實已經配置了中文化&#xff1a; 但是為啥沒生效&#xff1f;官網回答&#xff1a;FAQ - Ant Design dayjs中文網&#xff1a; 安裝 | Day…

零拷貝詳解

1、在沒有DMA技術之前的I/O過程是這樣的&#xff1a; CPU發出對應的指令給磁盤控制器&#xff0c;然后返回磁盤控制器收到指令后&#xff0c;于是就開始準備數據&#xff0c;會把數據放入到磁盤控制器的內部緩沖區&#xff0c;然后產生中斷CPU收到中斷信號后&#xff0c;停下手…

華為OD機試-5鍵鍵盤的輸出

題目描述 【5鍵鍵盤的輸出】有一個特殊的 5鍵鍵盤&#xff0c;上面有 a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五個鍵。 a鍵在屏幕上輸出一個字母 a; ctrl-c將當前選擇的字母復制到剪貼板; ctrl-x將當前選擇的 字母復制到剪貼板&#xff0c;并清空選擇的字母; ctrl-v將當前剪貼板里的字母…

HTML是什么?

HTML是什么&#xff1f; 超文本標記語言&#xff08;英語&#xff1a;HyperText Markup Language&#xff0c;簡稱&#xff1a;HTML&#xff09;是一種用于創建網頁的標準標記語言。 您可以使用 HTML 來建立自己的 WEB 站點&#xff0c;HTML 運行在瀏覽器上&#xff0c;由瀏覽器…

【業務功能篇63】Springboot聊聊 過濾器和攔截器

過濾器的場景&#xff1a;過濾器通常用于對數據或資源進行篩選、修改或轉換的場景。例如&#xff0c;在一個電子商務網站中&#xff0c;用戶進行商品搜索時&#xff0c;你可以使用過濾器來過濾特定的商品類別、價格范圍或其他條件&#xff0c;以便用戶僅看到符合篩選條件的結果…

人工智能時代的科學探索 | 《自然》評述

人工智能(AI)正越來越多地融入科學發現&#xff0c;以增強和加速研究&#xff0c;幫助科學家提出假設、設計實驗、收集和解釋大型數據集&#xff0c;并獲得僅靠傳統科學方法可能無法實現的洞察力。 過去十年間&#xff0c;AI取得了巨大的突破。其中就包括自監督學習和幾何深度學…

手機的發展歷史

目錄 一.人類的通信方式變化 二.手機對人類通信的影響 三.手機的發展過程 四.手機對現代人的影響 一.人類的通信方式變化 人類通信方式的變化是一個非常廣泛和復雜的話題&#xff0c;隨著技術的進步和社會的發展&#xff0c;人類通信方式發生了許多重大的變化。下面是一些主…

go mod使用最新提交依賴

例如一個項目在其中依賴了 github.com/linuxsuren/go-fake-runtime v0.0.1 go.mod內容&#xff1a; github.com/linuxsuren/go-fake-runtime v0.0.1 修改了github.com/linuxsuren/go-fake-runtime代碼&#xff0c;存在一個最新的commit hash值為25fa814c6232e545f5bce03bd…

【opencv】指定寬或高按比例縮放圖片 拼接圖片

指定寬或高按比例縮放圖片 import cv2def resize_by_ratio(image, widthNone, heightNone, intercv2.INTER_AREA):img_new_size None(h, w) image.shape[:2] # 獲得高度和寬度if width is None and height is None: # 如果輸入的寬度和高度都為空return image # 直接返回原圖…

應用程序運行報錯:First section must be [net] or [network]:No such file or directory

應用程序報錯環境&#xff1a; 在linux下&#xff0c;調用darknet訓練的模型&#xff0c;報錯&#xff1a;First section must be [net] or [network]:No such file or directory&#xff0c;并提示&#xff1a;"./src/utils.c:256: error: Assertion 0 failed." 如…

百日筑基篇——Pandas學習三(pyhton入門八)

百日筑基篇——Pandas學習三&#xff08;pyhton入門八&#xff09; 文章目錄 前言一、數據排序二、字符串處理三、數據合并方法1. merge方法2. concat方法 四、分組數據統計五、數據重塑1. stack2. pivot 總結 前言 上一篇文章介紹了一下pandas庫中的一些函數&#xff0c;而本…

MySQL數據類型

文章目錄 MySQL數據類型1. 數據類型分類2. 數值類型2.1 tinyint類型2.2 bit類型2.3 小數類型2.3.1 float2.3.2 decimal 2.4 字符串類型2.4.1 char2.4.2 varchar2.4.3 char和varchar比較 2.5 日期和時間類型2.6 enum和set MySQL數據類型 1. 數據類型分類 紅色標注是我主要講解…

【QT】 QFileQFileInfo文件操作

很高興在雪易的CSDN遇見你 &#xff0c;給你糖糖 歡迎大家加入雪易社區-CSDN社區云 前言 本文分享QT對文件的操作技術&#xff0c;希望對各位小伙伴有所幫助&#xff01; 感謝各位小伙伴的點贊關注&#xff0c;小易會繼續努力分享&#xff0c;一起進步&#xff01; 你的點…