最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring JDBC的使用詳解

 更新時(shí)間:2021年05月03日 09:33:05   作者:黑色的燈塔  
這篇文章主要介紹了Spring JDBC的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot框架,感興趣的朋友可以了解下

JDBC介紹

從這篇文章開始,我們將會(huì)介紹SpringBoot另外一個(gè)核心的技術(shù),即數(shù)據(jù)庫(kù)訪問(wèn)技術(shù),提到數(shù)據(jù)訪問(wèn),學(xué)習(xí)Java的同學(xué)瞬間能就想起JDBC技術(shù),JDBC 是 Java Database Connectivity 的全稱,是Java語(yǔ)言中用來(lái)規(guī)范客戶端程序如何來(lái)訪問(wèn)數(shù)據(jù)庫(kù)的應(yīng)用程序接口,提供了諸如查詢和更新數(shù)據(jù)庫(kù)中數(shù)據(jù)的一套標(biāo)準(zhǔn)的API,這套標(biāo)準(zhǔn)不同的數(shù)據(jù)庫(kù)廠家之間共同準(zhǔn)守,并提供各自的具體實(shí)現(xiàn)。如圖所示:

這樣設(shè)計(jì)的好處,就是Java程序只需要和JDBC API交互,從而屏蔽了訪問(wèn)數(shù)據(jù)庫(kù)的復(fù)雜的實(shí)現(xiàn),大大降低了Java程序訪問(wèn)數(shù)據(jù)庫(kù)的復(fù)雜度。對(duì)于日常開發(fā)而言,我們只需要掌握J(rèn)DBC API 規(guī)范中的幾個(gè)核心編程對(duì)象即可,這些對(duì)象包括DriverManger、Connection、Statement及ResultSet。

DriverManager

DriverManager主要負(fù)責(zé)加載不同數(shù)據(jù)庫(kù)廠家提供的驅(qū)動(dòng)程序包(Driver),并且根據(jù)不同的請(qǐng)求向Java程序返回?cái)?shù)據(jù)庫(kù)連接(Connection)對(duì)象,先看下Driver接口的定義:

public interface Driver {
    //獲取數(shù)據(jù)庫(kù)連接
    Connection connect(String url, java.util.Properties info)
        throws SQLException;
    boolean acceptsURL(String url) throws SQLException;
    DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)
                         throws SQLException;
    int getMajorVersion();
    int getMinorVersion();
    boolean jdbcCompliant();
    public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}

Driver中有個(gè)重要的方法 connect,來(lái)提供Connection對(duì)象

不同的數(shù)據(jù)庫(kù)對(duì)Driver,有具體的實(shí)現(xiàn),以MySql為例:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    // 通過(guò) DriverManager 注冊(cè) Driver
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
	}
	…
}

這里用到了DriverManager,DriverManager通過(guò) registerDriver來(lái)注冊(cè)不同數(shù)據(jù)庫(kù)的Driver,并且還提供了getConnection返回?cái)?shù)據(jù)庫(kù)連接對(duì)象。

Connection

通過(guò)DriverManager可以獲取Connetion對(duì)象,Connection對(duì)象可以理解與數(shù)據(jù)庫(kù)連接的一種會(huì)話(Session),一個(gè)Connection對(duì)象代表一個(gè)數(shù)據(jù)庫(kù)的連接,負(fù)責(zé)完成與數(shù)據(jù)庫(kù)底層的通訊。

Connection對(duì)象提供了一組重載的方法來(lái)創(chuàng)建Statement和PreparedStatement,Statement和PreparedStatement是SQL執(zhí)行的載體,另外Connection對(duì)象還會(huì)涉及事務(wù)相關(guān)的操作。

Connection對(duì)象最核心的幾個(gè)方法如下:

public interface Connection  extends Wrapper, AutoCloseable {
	//創(chuàng)建 Statement
	Statement createStatement() throws SQLException;
	//創(chuàng)建 PreparedStatement
	PreparedStatement prepareStatement(String sql) throws SQLException;
	//提交
	void commit() throws SQLException;
	//回滾
	void rollback() throws SQLException;
	//關(guān)閉連接
	void close() throws SQLException;
}

Statement/PreparedStatement

Statement和PreparedStatement是由Connection對(duì)象來(lái)創(chuàng)建的,用來(lái)執(zhí)行靜態(tài)的SQL語(yǔ)句并且返回生成的結(jié)果集對(duì)象,這里存在兩種類型,一種是普通的Statement,另外一種支持預(yù)編譯的PreparedStatement。

所謂預(yù)編譯,是指數(shù)據(jù)庫(kù)的編譯器會(huì)對(duì) SQL 語(yǔ)句提前編譯,然后將預(yù)編譯的結(jié)果緩存到數(shù)據(jù)庫(kù)中,下次執(zhí)行時(shí)就可以通過(guò)替換參數(shù)并直接使用編譯過(guò)的語(yǔ)句,從而大大提高 SQL 的執(zhí)行效率。

以Statement為例,看下Statement最核心的方法:

public interface Statement extends Wrapper, AutoCloseable {
	//執(zhí)行查詢語(yǔ)句
	ResultSet executeQuery(String sql) throws SQLException; 
	//執(zhí)行更新語(yǔ)句
	int executeUpdate(String sql) throws SQLException; 
	//執(zhí)行 SQL 語(yǔ)句
	boolean execute(String sql) throws SQLException; 
	//執(zhí)行批處理
    int[] executeBatch() throws SQLException;
}

ResultSet

通過(guò)Statement或PreparedStatement執(zhí)行SQL語(yǔ)句,我們引出了另外一個(gè)對(duì)象即為ResultSet對(duì)象,代碼如下:

public interface ResultSet extends Wrapper, AutoCloseable {
	//獲取下一個(gè)結(jié)果
	boolean next() throws SQLException;
	//獲取某一個(gè)類型的結(jié)果值
	Value getXXX(int columnIndex) throws SQLException;
	…
}

ResultSet對(duì)象提供了next()方法,用來(lái)對(duì)整個(gè)結(jié)果集遍歷操作,如果next()方法返回為true,說(shuō)明還有下一條記錄,

我們可以調(diào)用 ResultSet 對(duì)象的一系列 getXXX() 方法來(lái)取得對(duì)應(yīng)的結(jié)果值。

JDBC訪問(wèn)數(shù)據(jù)庫(kù)流程

對(duì)于開發(fā)人員而言,通過(guò)JDBC的API是Java訪問(wèn)數(shù)據(jù)庫(kù)的主要途徑,下面用代碼來(lái)展示下訪問(wèn)數(shù)據(jù)庫(kù)的一個(gè)整體流程:

String url = "jdbc:mysql://localhost:3306/test" ;
String username = "root" ;
String password = "root" ;

//1.通過(guò)DriverManager獲取connection連接
Connection connection = DriverManager.getConnection(url,username,password);

//2.創(chuàng)建preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement("select * from user");

//3.執(zhí)行SQL返回ResultSet
ResultSet resultSet = preparedStatement.executeQuery();

//4.遍歷resultSet結(jié)果集
while (resultSet.next()){
    //resultSet.getString("1");
}

//5.釋放資源
resultSet.close();
preparedStatement.close();
connection.close();

配置數(shù)據(jù)源

上面我們?cè)诮榻BJDBC的時(shí)候,Connection對(duì)象是通過(guò)DriverManager獲取,Connection對(duì)象代表著和數(shù)據(jù)庫(kù)的連接,每次通過(guò)DriverManager獲取比較耗時(shí),影響了系統(tǒng)的性能。那有沒有辦法能夠復(fù)用Connection對(duì)象呢,答案是肯定的

JDBC給我們提供了DataSource接口來(lái)實(shí)現(xiàn)Connection的復(fù)用,核心代碼如下:

public interface DataSource  extends CommonDataSource, Wrapper {
 
  Connection getConnection() throws SQLException;
 
  Connection getConnection(String username, String password)
    throws SQLException;
}

作為一種基礎(chǔ)組件,不需要開發(fā)人員自己實(shí)現(xiàn) DataSource,因?yàn)闃I(yè)界已經(jīng)存在了很多優(yōu)秀的實(shí)現(xiàn)方案,如 DBCP、C3P0 、Druid 、Hikari等

SpringBoot默認(rèn)HikariDataSource作為DataSource的實(shí)現(xiàn),現(xiàn)在我們SpringBoot為例,看下SpringBoot如何通過(guò)JDBC來(lái)操作數(shù)據(jù)庫(kù)的,在進(jìn)行數(shù)據(jù)庫(kù)操作之前,我們首先需要先配置DataSource,SpringBoot配置DataSource非常簡(jiǎn)單,只需要在配置文件中添加DataSource的配置:

spring:
  # datasource 數(shù)據(jù)源配置內(nèi)容
  datasource:
    url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root

使用JDBC操縱數(shù)據(jù)庫(kù)

DataSource配好后,我們?cè)诒镜氐臄?shù)據(jù)庫(kù)服務(wù)中,創(chuàng)建一個(gè)test數(shù)據(jù)庫(kù),并且執(zhí)行以下DDL創(chuàng)建user表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `username` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用戶名',
  `password` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密碼',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

接下來(lái)我們創(chuàng)建一個(gè)實(shí)體類,實(shí)體類中屬性和user表中字段一一對(duì)應(yīng)

@Data
public class User {
    /**
     * 主鍵
     */
    private Integer id;
    /**
     * 用戶名
     */
    private String username;
    /**
     * 密碼
     */
    private String password;
    /**
     * 創(chuàng)建時(shí)間
     */
    private Date createTime;

}

注意:這里使用了Lombok的@Data注解來(lái)生成get/set方法。

我們?cè)俣x一個(gè)UserDao接口,

public interface UserDao {
    /**
     *  新增
     * @param user
     * @return
     */
    Integer insert(User user);
    /**
     *  根據(jù)ID查詢
     * @param id
     * @return
     */
    User selectById(Integer id);
    /**
     *  根據(jù)ID更新
     * @param user
     * @return
     */
    Integer updateById(User user);
    /**
     *  根據(jù)ID刪除
     * @param id
     * @return
     */
    Integer deleteById(Integer id);
}

這里之所以要抽離出一個(gè)UserDao一層有兩個(gè)原因:第一UserDao只封裝了對(duì)use表的數(shù)據(jù)庫(kù)操作,代碼易于維護(hù)和管理,第二我們可以基于UserDao接口提供不同的實(shí)現(xiàn)來(lái)訪問(wèn)數(shù)據(jù)庫(kù),比如我們可以提供基于原生JDBC的實(shí)現(xiàn),也可以用JDBCTemplate實(shí)現(xiàn)數(shù)據(jù)庫(kù)的訪問(wèn),還可以通過(guò)Mybatis等

接下來(lái)將通過(guò)代碼形式來(lái)展示下SpringBoot是如何通過(guò)JDBC API對(duì)數(shù)據(jù)庫(kù)進(jìn)行CRUD操作的。我們來(lái)定義UserDao的具體實(shí)現(xiàn)類命名為:UserRawJdbcDao實(shí)現(xiàn)以下方法:

新增數(shù)據(jù)

@Override
    public Integer insert(User user) {
      	final String SQL_INSERT = "INSERT INTO user(username, password, create_time) VALUES(?, ?, ?)";
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        Integer count = 0;
        try{
            connection = dataSource.getConnection();
            statement = connection.prepareStatement(SQL_INSERT, Statement.RETURN_GENERATED_KEYS);
            statement.setString(1,user.getUsername());
            statement.setString(2,user.getPassword());
            statement.setTimestamp(3,new Timestamp(user.getCreateTime().getTime()));
            count = statement.executeUpdate();
            rs = statement.getGeneratedKeys();
            if(rs.next()){
                user.setId(rs.getInt(1));
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            try {
                if(rs != null){
                    rs.close();
                }
                if(statement != null){
                    statement.close();
                }
                if(connection != null){
                    connection.close();
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return count;
    }

查詢數(shù)據(jù)

@Override
    public User selectById(Integer id) {
        final String SQL_SELECT_ID = "SELECT id,username,password,create_time FROM user WHERE id = ?";
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        User user = null;
        try{
            connection = dataSource.getConnection();
            statement = connection.prepareStatement(SQL_SELECT_ID);
            statement.setInt(1, id);
            rs = statement.executeQuery();
            if(rs.next()){
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
                user.setCreateTime(rs.getTimestamp("create_time"));
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            try {
                if(rs != null){
                    rs.close();
                }
                if(statement != null){
                    statement.close();
                }
                if(connection != null){
                    connection.close();
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return user;
    }

更新數(shù)據(jù)

@Override
    public Integer updateById(User user) {
        final String SQL_UPDATE = "UPDATE user SET username = ?, password = ? WHERE id = ?";
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        Integer count = 0;

        try{
            connection = dataSource.getConnection();
            statement = connection.prepareStatement(SQL_UPDATE);
            statement.setString(1,user.getUsername());
            statement.setString(2,user.getPassword());
            statement.setInt(3,user.getId());
            count = statement.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            try {
                if(rs != null){
                    rs.close();
                }
                if(statement != null){
                    statement.close();
                }
                if(connection != null){
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return count;
    }

刪除數(shù)據(jù)

@Override
    public Integer deleteById(Integer id) {
        final String SQL_DELETE = "DELETE FROM user WHERE id = ?";
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        Integer count = 0;
        try{
            connection = dataSource.getConnection();
            statement = connection.prepareStatement(SQL_DELETE);
            statement.setInt(1,id);
            count = statement.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            try {
                if(rs != null){
                    rs.close();
                }
                if(statement != null){
                    statement.close();
                }
                if(connection != null){
                    connection.close();
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return count;
    }

到此,SpringBoot通過(guò)調(diào)用原生的JDBC的API完成對(duì)user表的CRUD操作,這代碼對(duì)有代碼潔癖的同學(xué)簡(jiǎn)直不能忍,有大量共性的代碼,如創(chuàng)建Connection、Statement、ResultSet、資源的釋放和異常的處理。這部分封裝和優(yōu)化SpringBoot已經(jīng)處理過(guò)了,SpringBoot提供了JdbcTemplate模板工具類實(shí)現(xiàn)數(shù)據(jù)訪問(wèn),它簡(jiǎn)化了JDBC API的使用方法。

使用JdbcTemplate操縱數(shù)據(jù)庫(kù)

同UserRawJdbcDao,我們?cè)俣xUserDao的另外一套實(shí)現(xiàn)類命名為:UserJdbcDao,這套實(shí)現(xiàn)類是通過(guò)JdbcTemplate完成對(duì)數(shù)據(jù)庫(kù)的操作,完成接口定義的方法如下:

新增數(shù)據(jù)

 
@Override
public Integer insert(User user){
  
    // 創(chuàng)建 KeyHolder 對(duì)象,設(shè)置返回的主鍵 ID
    KeyHolder keyHolder = new GeneratedKeyHolder();
    int count = jdbcTemplate.update(INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.newPreparedStatementCreator(
            Arrays.asList(user.getUsername(),user.getPassword(),user.getCreateTime())),keyHolder);
    // 設(shè)置 ID 主鍵到 entity 實(shí)體中
    if (keyHolder.getKey() != null) {
        user.setId(keyHolder.getKey().intValue());
    }
    // 返回影響行數(shù)
    return count;
}

查詢數(shù)據(jù)

  @Override
    public User selectById(Integer id){
        User result = jdbcTemplate.queryForObject("SELECT id, username, password, create_time FROM user WHERE id=?",
                new BeanPropertyRowMapper<>(User.class), id);
        return result;
    }

更新數(shù)據(jù)

  @Override
    public Integer updateById(User user) {
        return jdbcTemplate.update("UPDATE user SET username = ?, password = ? WHERE id = ?",
                user.getUsername(),user.getPassword(),user.getId());
    }

刪除數(shù)據(jù)

@Override
    public Integer deleteById(Integer id){
        return jdbcTemplate.update("DELETE FROM user WHERE id = ?", id);
    }

小結(jié)

通過(guò)對(duì)比我們發(fā)現(xiàn)使用JdbcTemplate模板工具類可以大大減少JDBC訪問(wèn)數(shù)據(jù)庫(kù)的代碼復(fù)雜度,作為開發(fā)人員我們應(yīng)該只關(guān)心業(yè)務(wù)邏輯的具體實(shí)現(xiàn)過(guò)程,對(duì)JDBC底層對(duì)象的創(chuàng)建,資源的釋放,異常的捕獲,應(yīng)該交給框架統(tǒng)一維護(hù)和管理。

雖然JdbcTemplate減少的我們?cè)L問(wèn)數(shù)據(jù)庫(kù)的代碼量,不過(guò)使用也有一些問(wèn)題,比如:新增數(shù)據(jù)的時(shí)候默認(rèn)無(wú)法返回生成主鍵的id,將SQL硬編碼到Java代碼中,如果SQL修改,需要重新編譯Java代碼,不利于系統(tǒng)的維護(hù)等。這時(shí)我們需要另外一個(gè)框架,它就是大名鼎鼎的Mybatis,下一篇我將會(huì)介紹SpringBoot如何整合Mybatis。

項(xiàng)目源碼

github:github.com/dragon8844/…

以上就是Spring JDBC的使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring JDBC的使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何讓W(xué)in10實(shí)現(xiàn)Java文件的開機(jī)自啟動(dòng)

    如何讓W(xué)in10實(shí)現(xiàn)Java文件的開機(jī)自啟動(dòng)

    這篇文章主要介紹了如何讓W(xué)in10實(shí)現(xiàn)Java文件的開機(jī)自啟動(dòng),對(duì)于一些想要一直運(yùn)行的Java文件,就會(huì)造成每次系統(tǒng)更新之后的重啟導(dǎo)致Java文件無(wú)法繼續(xù)運(yùn)行。,需要的朋友可以參考下
    2019-06-06
  • Java打印出所有的水仙花數(shù)的實(shí)現(xiàn)代碼

    Java打印出所有的水仙花數(shù)的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java打印出所有的水仙花數(shù)的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2017-02-02
  • 將Java程序包打包為.exe文件的操作步驟

    將Java程序包打包為.exe文件的操作步驟

    將Java程序打包為為.exe文件分為倆個(gè)步驟:將Java程序打包成Jar包和打包為.exe文件,文中通過(guò)圖文結(jié)合的方式給大家講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-06-06
  • Netty分布式Server啟動(dòng)流程服務(wù)端初始化源碼分析

    Netty分布式Server啟動(dòng)流程服務(wù)端初始化源碼分析

    本章主要講解server啟動(dòng)的關(guān)鍵步驟,?讀者只需要了解server啟動(dòng)的大概邏輯,?知道關(guān)鍵的步驟在哪個(gè)類執(zhí)行即可,?并不需要了解每一步的運(yùn)作機(jī)制,?之后會(huì)對(duì)每個(gè)模塊進(jìn)行深度分析
    2022-03-03
  • SpringCloud配置客戶端ConfigClient接入服務(wù)端

    SpringCloud配置客戶端ConfigClient接入服務(wù)端

    這篇文章主要為大家介紹了SpringCloud配置客戶端ConfigClient接入服務(wù)端,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Spring Junit單元測(cè)試加載配置文件失敗問(wèn)題

    Spring Junit單元測(cè)試加載配置文件失敗問(wèn)題

    這篇文章主要介紹了Spring Junit加載配置文件失敗問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 基于SpringBoot的Dubbo泛化調(diào)用的實(shí)現(xiàn)代碼

    基于SpringBoot的Dubbo泛化調(diào)用的實(shí)現(xiàn)代碼

    這篇文章主要介紹了基于SpringBoot的Dubbo泛化調(diào)用的實(shí)現(xiàn),從泛化調(diào)用實(shí)現(xiàn)的過(guò)程來(lái)看,我們可以對(duì)自己提供所有服務(wù)進(jìn)行測(cè)試,不需要引入調(diào)用的接口,減少代碼的侵入,需要的朋友可以參考下
    2022-04-04
  • Java細(xì)數(shù)IO流底層原理到方法使用

    Java細(xì)數(shù)IO流底層原理到方法使用

    IO主要用于設(shè)備之間的數(shù)據(jù)傳輸,Java將操作數(shù)據(jù)流的功能封裝到了IO包中,這篇文章主要給大家介紹了關(guān)于Java新手學(xué)習(xí)之IO流簡(jiǎn)單使用的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • Spring?Boot開發(fā)時(shí)Java對(duì)象和Json對(duì)象之間的轉(zhuǎn)換

    Spring?Boot開發(fā)時(shí)Java對(duì)象和Json對(duì)象之間的轉(zhuǎn)換

    在Spring?Boot開發(fā)中,我們經(jīng)常需要處理Java對(duì)象和Json對(duì)象之間的轉(zhuǎn)換,本文將介紹如何在Spring?Boot項(xiàng)目中實(shí)現(xiàn)Java對(duì)象和Json對(duì)象之間的轉(zhuǎn)換,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • Spring Boot Starter 自動(dòng)裝配原理全解析

    Spring Boot Starter 自動(dòng)裝配原理全解析

    Spring Boot Starter 的核心設(shè)計(jì)理念是 約定優(yōu)于配置,其核心實(shí)現(xiàn)基于 自動(dòng)配置(Auto-Configuration) 和 條件化注冊(cè)(Conditional Registration),這篇文章主要介紹了Spring Boot Starter 自動(dòng)裝配原理全解析,需要的朋友可以參考下
    2025-04-04

最新評(píng)論

获嘉县| 垣曲县| 汾西县| 伊川县| 崇左市| 乐安县| 元谋县| 板桥市| 宽城| 丰县| 铅山县| 长垣县| 军事| 高阳县| 吉林省| 孟州市| 临西县| 神池县| 凤阳县| 延吉市| 双鸭山市| 仁怀市| 茂名市| 临西县| 延津县| 克拉玛依市| 宁都县| 烟台市| 巴彦淖尔市| 衡阳市| 普兰店市| 桂平市| 桓台县| 鹤庆县| 襄垣县| 六枝特区| 茂名市| 搜索| 资阳市| 依安县| 巢湖市|