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

SpringBoot配置多數(shù)據(jù)源的四種方式分享

 更新時間:2023年07月03日 11:50:54   作者:中國胖子風(fēng)清揚(yáng)  
在日常開發(fā)中我們都是以單個數(shù)據(jù)庫進(jìn)行開發(fā),在小型項(xiàng)目中是完全能夠滿足需求的,但是,當(dāng)我們牽扯到大型項(xiàng)目的時候,單個數(shù)據(jù)庫就難以承受用戶的CRUD操作,那么此時,我們就需要使用多個數(shù)據(jù)源進(jìn)行讀寫分離的操作,本文就給大家介紹SpringBoot配置多數(shù)據(jù)源的方式

1、所需的資源

  • Spring boot
  • Mybatis-plus
  • Alibab Druid數(shù)據(jù)庫連接池
  • MySql 數(shù)據(jù)庫

2、Spring Boot配置多數(shù)據(jù)源

數(shù)據(jù)庫

在YAML文件中定義數(shù)據(jù)源所需的數(shù)據(jù)

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource ## 聲明數(shù)據(jù)源的類型
    mysql-datasource1: ## 聲明第一個數(shù)據(jù)源所需的數(shù)據(jù)
      url: jdbc:mysql://localhost:3306/mybatis?useSSL=true&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    mysql-datasource2: ## 聲明第二個數(shù)據(jù)源所需的數(shù)據(jù)
      url: jdbc:mysql://localhost:3306/bookstore?useSSL=true&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    druid: ## druid數(shù)據(jù)庫連接池的基本初始化屬性
      initial-size: 5 ## 連接池初始化的大小
      min-idle: 1 ## 最小空閑的線程數(shù)
      max-active: 20 ## 最大活動的線程數(shù)
mybatis-plus:
  mapper-locations: classpath:/mapper/*.xml ## 配置MyBatis-Plus掃描Mapper文件的位置
  type-aliases-package: com.example.sqlite.entity ## 創(chuàng)建別名的類所在的包

mysql-datasource1、mysql-datasource2是自定義的數(shù)據(jù)。

定義多個數(shù)據(jù)源

@Configuration
public class DataSourceConfig {
    @Bean(name = "mysqlDataSource1")
    @ConfigurationProperties(prefix = "spring.datasource.mysql-datasource1")
    public DataSource dataSource1(){
        DruidDataSource build = DruidDataSourceBuilder.create().build();
        return build;
    }
    @Bean(name = "mysqlDataSource2")
    @ConfigurationProperties(prefix = "spring.datasource.mysql-datasource2")
    public DataSource dataSource2(){
        DruidDataSource build = DruidDataSourceBuilder.create().build();
        return build;
    }
}

@ConfigurationProperties注解用于將YAML中指定的數(shù)據(jù)創(chuàng)建成指定的對象,但是,YAML中的數(shù)據(jù)必須要與對象對象中的屬性同名,不然無法由Spring Boot完成賦值。

由于我們要定義多個數(shù)據(jù)源,所以在Spring Boot數(shù)據(jù)源自動配置類中就無法確定導(dǎo)入哪個數(shù)據(jù)源來完成初始化,所以我們就需要禁用掉Spring Boot的數(shù)據(jù)源自動配置類,然后使用我們自定義的數(shù)據(jù)源配置類來完成數(shù)據(jù)源的初始化與管理。

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DatasourceDomeApplication {
    public static void main(String[] args) {
        SpringApplication.run(DatasourceDomeApplication.class, args);
    }
}

在啟動類上聲明需要禁用的自動配置類:exclude = {DataSourceAutoConfiguration.class}

2.1、實(shí)現(xiàn)DataSource接口

缺點(diǎn):產(chǎn)生大量的代碼冗余,在代碼中存在硬編碼。

2.1.1、代碼

@Component
@Primary
public class DynamicDataSource implements DataSource {
//使用ThreadLocal而不是String,可以在多線程的時候保證數(shù)據(jù)的可靠性
    public static ThreadLocal<String> flag = new ThreadLocal<>();
    @Resource
    private DataSource mysqlDataSource1; // 注入第一個數(shù)據(jù)源
    @Resource
    private DataSource mysqlDataSource2; // 注入第二個數(shù)據(jù)源
    public DynamicDataSource(){ // 使用構(gòu)造方法初始化ThreadLocal的值
        flag.set("r");
    }
    @Override
    public Connection getConnection() throws SQLException {
    	// 通過修改ThreadLocal來修改數(shù)據(jù)源,
    	// 為什么通過修改狀態(tài)就能改變已經(jīng)注入的數(shù)據(jù)源? 這就得看源碼了。
        if(flag.get().equals("r")){ 
            return mysqlDataSource1.getConnection();
        } 
        return mysqlDataSource2.getConnection();
    }
    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }
    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }
    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
    }
    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
    }
    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }
    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }
    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

實(shí)現(xiàn)DataSource接口我們本質(zhì)上只使用了一個方法,就是getConnection()這個無參的方法,但是DataSource接口中所有的方法我們也都需要實(shí)現(xiàn),只是不用寫方法體而已,也就是存在了很多的 “廢方法” 。
@Primary注解 == @Order(1),用于設(shè)置此類的注入順序。

2.1.2、使用

// 訪問第一個數(shù)據(jù)庫的t_user表
@RestController
public class UserController {
    @Resource
    private UserService userService;
    @GetMapping(value = "/user_list")
    public List<User> showUserList(){
        DynamicDataSource.flag.set("read"); // 修改數(shù)據(jù)源的狀態(tài)
        List<User> list = userService.list();
        return list;
    }
}
// 訪問第二個數(shù)據(jù)庫的Book表
@RestController
public class BookController {
    @Resource
    private BookService BookService;
    @GetMapping(value = "/Book_list")
    public List<Book> getBookList(){
        DynamicDataSource.flag.set("write"); // 修改數(shù)據(jù)源的狀態(tài)
        List<Book> list = BookService.list();
        return list;
    }
}

2.2、繼承AbstrictRoutingDataSource類

減少了代碼的冗余,但是還是會存在硬編碼。

2.2.1、代碼

@Primary
@Component
public class DynamicDataSource extends AbstractRoutingDataSource {
    public static ThreadLocal<String> flag = new ThreadLocal<>();
    @Resource
    private DataSource mysqlDataSource1;
    @Resource
    private DataSource mysqlDataSource2;
    public DynamicDataSource(){
        flag.set("read");
    }
    @Override
    protected Object determineCurrentLookupKey() { // 通過Key來得到數(shù)據(jù)源
        return flag.get();
    }
    @Override
    public void afterPropertiesSet() {
        Map<Object,Object> targetDataSource = new ConcurrentHashMap<>();
        targetDataSource.put("read",mysqlDataSource1);
        // 將第一個數(shù)據(jù)源設(shè)置為默認(rèn)的數(shù)據(jù)源。
        super.setDefaultTargetDataSource(mysqlDataSource1);
        targetDataSource.put("write",mysqlDataSource2);
         // 將Map對象賦值給AbstrictRoutingDataSource內(nèi)部的Map對象中。
        super.setTargetDataSources(targetDataSource);
        super.afterPropertiesSet();
    }
}

AbstrictRoutingDataSource的本質(zhì)就是利用一個Map將數(shù)據(jù)源存儲起來,然后通過Key來得到Value來修改數(shù)據(jù)源。

2.2.2、使用

// 訪問第一個數(shù)據(jù)庫的t_user表
@RestController
public class UserController {
    @Resource
    private UserService userService;
    @GetMapping(value = "/user_list")
    public List<User> showUserList(){
        DynamicDataSource.flag.set("read"); // 修改數(shù)據(jù)源的狀態(tài)
        List<User> list = userService.list();
        return list;
    }
}
// 訪問第二個數(shù)據(jù)庫的Book表
@RestController
public class BookController {
    @Resource
    private BookService BookService;
    @GetMapping(value = "/Book_list")
    public List<Book> getBookList(){
        DynamicDataSource.flag.set("write"); // 修改數(shù)據(jù)源的狀態(tài)
        List<Book> list = BookService.list();
        return list;
    }
}

2.3、使用Spring AOP + 自定義注解的形式

Spring AOP + 自定義注解的形式是一種推薦的寫法,減少代碼的冗余且不存在硬編碼。
此方法適合對指定功能操作指定數(shù)據(jù)庫的模式。

2.3.1、導(dǎo)入依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.3.2、開啟AOP支持

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableAspectJAutoProxy //開啟Spring Boot對AOP的支持
public class AopDatasourceApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopDatasourceApplication.class, args);
    }
}

2.3.3、定義枚舉來表示數(shù)據(jù)源的標(biāo)識

public enum DataSourceType {
    MYSQL_DATASOURCE1,
    MYSQL_DATASOURCE2,
}

2.3.4、繼承AbstractRoutingDataSource類

@Primary
@Component
public class DataSourceManagement extends AbstractRoutingDataSource {
    public static ThreadLocal<String> flag = new ThreadLocal<>();
    @Resource
    private DataSource mysqlDataSource1;
    @Resource
    private DataSource mysqlDataSource2;
    public DataSourceManagement(){
        flag.set(DataSourceType.MYSQL_DATASOURCE1.name());
    }
    @Override
    protected Object determineCurrentLookupKey() {
        return flag.get();
    }
    @Override
    public void afterPropertiesSet() {
        Map<Object,Object> targetDataSource = new ConcurrentHashMap<>();
        targetDataSource.put(DataSourceType.MYSQL_DATASOURCE1.name(),mysqlDataSource1);
        targetDataSource.put(DataSourceType.MYSQL_DATASOURCE2.name(),mysqlDataSource2);
        super.setTargetDataSources(targetDataSource);
        super.setDefaultTargetDataSource(mysqlDataSource1);
        super.afterPropertiesSet();
    }
}

2.3.5、自定義注解

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    DataSourceType value() default DataSourceType.MYSQL_DATASOURCE1;
}

2.3.6、定義注解的實(shí)現(xiàn)類

@Component
@Aspect
@Slf4j
public class TargetDataSourceAspect {
    @Before("@within(TargetDataSource) || @annotation(TargetDataSource)")
    public void beforeNoticeUpdateDataSource(JoinPoint joinPoint){
        TargetDataSource annotation = null;
        Class<? extends Object> target = joinPoint.getTarget().getClass();
        if(target.isAnnotationPresent(TargetDataSource.class)){
            // 判斷類上是否標(biāo)注著注解
             annotation = target.getAnnotation(TargetDataSource.class);
             log.info("類上標(biāo)注了注解");
        }else{
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            if(method.isAnnotationPresent(TargetDataSource.class)){
                // 判斷方法上是否標(biāo)注著注解,如果類和方法上都沒有標(biāo)注,則報(bào)錯
                annotation = method.getAnnotation(TargetDataSource.class);
                log.info("方法上標(biāo)注了注解");
            }else{
                throw new RuntimeException("@TargetDataSource注解只能用于類或者方法上, 錯誤出現(xiàn)在:[" +
                        target.toString() +" " + method.toString() + "];");
            }
        }
        // 切換數(shù)據(jù)源
        DataSourceManagement.flag.set(annotation.value().name());
    }
}

在有的博客中也會使用@Around環(huán)繞通知的方式,但是環(huán)繞通知需要執(zhí)行joinPoint.process()方法來調(diào)用目標(biāo)對象的方法,最后返回執(zhí)行的值,不然得不到所需要的數(shù)據(jù)。
我這里使用了@Before前置通知,效果是一樣的,因?yàn)锧Around就會包含@Before。

 @Around("@within(TargetDataSource) || @annotation(TargetDataSource)")
    public Object beforeNoticeUpdateDataSource(ProceedingJoinPoint joinPoint){
       	// 省略邏輯代碼
       	Object result = null;
       	try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

ProceedingJoinPoint 對象只能在@Around環(huán)繞通知中使用,在其他通知中使用就會報(bào)錯。

2.3.7、使用

// 訪問第一個數(shù)據(jù)源。
@RestController
// 將注解標(biāo)注在類上,表示本類中所有的方法都是使用數(shù)據(jù)源1
@TargetDataSource(value = DataSourceType.MYSQL_DATASOURCE1)
public class UserController {
    @Resource
    private UserService userService;
    @GetMapping(value = "/user_list")
    public List<User> showUserList(){
        System.out.println(DataSourceType.MYSQL_DATASOURCE1.name());
        List<User> list = userService.list();
        return list;
    }
}
// 訪問第二個數(shù)據(jù)源
@RestController
public class BookController {
    @Resource
    private BookService BookService;
    @GetMapping(value = "/Book_list")
    // 將注解標(biāo)注在方法上,表示此方法使用數(shù)據(jù)源2
    @TargetDataSource(value = DataSourceType.MYSQL_DATASOURCE2)
    public List<Book> getBookList(){
        List<Book> list = BookService.list();
        return list;
    }
}

2.4、通過SqlSessionFactory指定的數(shù)據(jù)源來操作指定目錄的XML文件

使用此方法則不會與上面所述的類有任何關(guān)系,本方法會重新定義類。本方法也是一種推薦的方法,適用于對指定數(shù)據(jù)庫的操作,也就是適合讀寫分離。不會存在代碼冗余和存在硬編碼。

2.4.1、項(xiàng)目的目錄結(jié)構(gòu)

對所需要操作的數(shù)據(jù)庫的Mapper層和dao層分別建立一個文件夾。

2.4.2、配置YAML文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    mysql-datasource:
      jdbc-url: jdbc:mysql://localhost:3306/mybatis?useSSL=true&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    sqlite-datasource:
      jdbc-url: jdbc:mysql://localhost:3306/bookstore?useSSL=true&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    druid:
      initial-size: 5
      min-idle: 1
      max-active: 20
mybatis-plus:
  mapper-locations: classpath:/mapper/*.xml
  type-aliases-package: com.example.sqlite.entity

2.4.3、針對Mapper層通過SqlSessionFactory指定數(shù)據(jù)源來操作

2.4.3.1、創(chuàng)建MySql數(shù)據(jù)源

@Configuration
@MapperScan(basePackages = "com.example.sqlite.dao.mysql", sqlSessionFactoryRef = "MySQLSqlSessionFactory")
public class MySQLDataSourceConfig {
    @Bean(name = "MySQLDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.mysql-datasource")
    public DataSource getDateSource1() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "MySQLSqlSessionFactory")
    @Primary
    public SqlSessionFactory test1SqlSessionFactory(
            @Qualifier("MySQLDataSource") DataSource datasource) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean ();
        bean.setDataSource(datasource);
        bean.setMapperLocations(// 設(shè)置mybatis的xml所在位置
                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/mysql/*.xml"));
        return bean.getObject();
    }
    @Bean("MySQLSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate test1SqlSessionTemplate(
            @Qualifier("MySQLSqlSessionFactory") SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }
    @Bean
    public PlatformTransactionManager transactionManager(@Qualifier("MySQLDataSource")DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

2.4.3.2、創(chuàng)建Sqlite數(shù)據(jù)源

@Configuration
@MapperScan(basePackages = "com.example.sqlite.dao.sqlite", sqlSessionFactoryRef = "SqliteSqlSessionFactory")
public class SqliteDataSourceConfig {
    @Bean(name = "SqliteDateSource")
    @ConfigurationProperties(prefix = "spring.datasource.sqlite-datasource")
    public DataSource getDateSource1() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "SqliteSqlSessionFactory")
    public SqlSessionFactory test1SqlSessionFactory(
            @Qualifier("SqliteDateSource") DataSource datasource) throws Exception {
        MybatisSqlSessionFactoryBean  bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(datasource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/sqlite/*.xml"));
        return bean.getObject();
    }
    @Bean("SqliteSqlSessionTemplate")
    public SqlSessionTemplate test1SqlSessionTemplate(
            @Qualifier("SqliteSqlSessionFactory") SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }
    @Bean
    public PlatformTransactionManager transactionManager(@Qualifier("SqliteDateSource")DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
  1. @MapperScan注解中的basePackages指向的是指定的Dao層。
  2. @MapperScan注解中sqlSessionFactoryRef 用來指定使用某個SqlSessionFactory來操作數(shù)據(jù)源。
  3. bean.setMapperLocations(
    new PathMatchingResourcePatternResolver()
    .getResources(“classpath*:mapper/sqlite/*.xml”)); 指向的是操作執(zhí)行數(shù)據(jù)庫的Mapper層。

如果使用SQLite數(shù)據(jù)庫,那么就必須在項(xiàng)目中內(nèi)嵌SQLite數(shù)據(jù)庫,這個一個輕量級的數(shù)據(jù)庫,不同于Mysql,SQLite不需要服務(wù)器,SQLite適合使用于移動APP開發(fā)。
像微信,用戶的聊天記錄就是使用這個數(shù)據(jù)庫進(jìn)行存儲。SQLite也可以使用在Web端,只是不太方便。

2.4.4、使用

// 訪問第一個數(shù)據(jù)庫
@RestController
public class UserController {
    @Resource
    private UserService userService;
    @GetMapping(value = "/user_list")
    public List<User> showUserList(){
        List<User> list = userService.list();
        return list;
    }
}
// 訪問第二個數(shù)據(jù)庫
@RestController
public class AddressController {
    @Resource
    private AddressService addressService;
    @GetMapping(value = "/address_list")
    public List<Address> getAddressList(){
        List<Address> list = addressService.list();
        return list;
    }
}

使用此種方法不會存在任何代碼的冗余以及硬編碼的存在,但是需要分層明確。
唯一的不足就是添加一個數(shù)據(jù)源就需要重新寫一個類,而這個類中的代碼大部分又是相同的。

3、總結(jié)

  • 實(shí)現(xiàn)DataSource接口這種寫法是不推薦的。
  • 推薦使用Spring Boot + 自定義注解的方式與SqlSessionFactory方式。

另外,Spring AOP中各種通知的執(zhí)行順序如下圖所示:

以上就是SpringBoot配置多數(shù)據(jù)源的四種方式分享的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot配置多數(shù)據(jù)源的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaWeb簡單用戶登錄注冊實(shí)例代碼(有驗(yàn)證碼)

    JavaWeb簡單用戶登錄注冊實(shí)例代碼(有驗(yàn)證碼)

    這篇文章主要介紹了JavaWeb簡單用戶登錄注冊實(shí)例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • SpringBoot+JUnit5+MockMvc+Mockito單元測試的實(shí)現(xiàn)

    SpringBoot+JUnit5+MockMvc+Mockito單元測試的實(shí)現(xiàn)

    今天聊聊如何在 SpringBoot 中集成 Junit5、MockMvc、Mocktio。Junit5 是在 Java 棧中應(yīng)用最廣的測試框架,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • springboot+redis實(shí)現(xiàn)簡單的熱搜功能

    springboot+redis實(shí)現(xiàn)簡單的熱搜功能

    這篇文章主要介紹了springboot+redis實(shí)現(xiàn)一個簡單的熱搜功能,通過代碼介紹了過濾不雅文字的過濾器,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • SpringBoot+Redis隊(duì)列實(shí)現(xiàn)Java版秒殺的示例代碼

    SpringBoot+Redis隊(duì)列實(shí)現(xiàn)Java版秒殺的示例代碼

    本文主要介紹了SpringBoot+Redis隊(duì)列實(shí)現(xiàn)Java版秒殺的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 使用jxls自定義命令設(shè)置動態(tài)行高

    使用jxls自定義命令設(shè)置動態(tài)行高

    這篇文章主要介紹了使用jxls自定義命令設(shè)置動態(tài)行高,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java實(shí)現(xiàn)二叉堆、大頂堆和小頂堆

    Java實(shí)現(xiàn)二叉堆、大頂堆和小頂堆

    二叉堆就是完全二叉樹,或者是靠近完全二叉樹結(jié)構(gòu)的二叉樹。大頂堆要求對于一個節(jié)點(diǎn)來說,它的左右節(jié)點(diǎn)都比它??;小頂堆要求對于一個節(jié)點(diǎn)來說,它的左右節(jié)點(diǎn)都比它大。本文將用Java分別實(shí)現(xiàn)二叉堆、大頂堆和小頂堆。需要的可以參考一下
    2022-01-01
  • AutoScan Spring Boot 項(xiàng)目底座跨包掃描的終極解決方案全解析

    AutoScan Spring Boot 項(xiàng)目底座跨包掃描的終極解決方案全解析

    文章介紹了autoscan-spring-boot-starter,這是一種為解決企業(yè)級SpringBoot開發(fā)中跨包掃描問題而設(shè)計(jì)的解決方案,本文通過實(shí)例代碼給大家介紹的非常詳細(xì)感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • SpringBoot的@Value給靜態(tài)變量注入application.properties屬性值

    SpringBoot的@Value給靜態(tài)變量注入application.properties屬性值

    這篇文章主要介紹了SpringBoot的@Value給靜態(tài)變量注入application.properties屬性值,Spring是一個開源的框架,主要是用來簡化開發(fā)流程,通過IOC,依賴注入(DI)和面向接口實(shí)現(xiàn)松耦合,需要的朋友可以參考下
    2023-05-05
  • Java 泛型總結(jié)(三):通配符的使用

    Java 泛型總結(jié)(三):通配符的使用

    在泛型的使用中,還有個重要的東西叫通配符,本文介紹通配符的使用。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • Java刪除Word文檔中水印的實(shí)現(xiàn)方法

    Java刪除Word文檔中水印的實(shí)現(xiàn)方法

    在 Word 文檔中,水印常用于標(biāo)示文檔的狀態(tài),但可能會影響文檔的清晰度和專業(yè)性,本文將介紹如何使用 Java 刪除 Word 文檔中的水印,有需要的可以了解下
    2025-11-11

最新評論

安顺市| 石泉县| 石棉县| 和顺县| 喀喇| 修文县| 锦屏县| 清流县| 合水县| 洛扎县| 昌乐县| 镇沅| 雷州市| 上饶市| 剑川县| 辉县市| 北流市| 安国市| 泰顺县| 小金县| 东乌| 宁南县| 甘德县| 崇文区| 汾阳市| 武定县| 交口县| 湘潭市| 三都| 临高县| 台江县| 拉孜县| 华宁县| 黄山市| 潮州市| 县级市| 温泉县| 隆化县| 河东区| 乌苏市| 文昌市|