主頁 > 後端開發 > 企業級spring-boot案例-自定義Spring Boot Starter

企業級spring-boot案例-自定義Spring Boot Starter

2022-01-04 09:45:47 後端開發

文章目錄

    • 1. 未使用Spring Boot Starter前的情況
    • 2. Spring Boot Starter簡介
      • 2.1 什么是Spring Boot Starter(啟動器)
      • 2.2 Starter 模塊整體結構
      • 2.3 Spring 官方提供的 Starter 和 Starter 命名規范
    • 3. 自定義Spring Boot Starter
      • 3.1 根據 starter 命名規范創建一個 spring boot 專案
      • 3.2 在 pom.xml 檔案中引入依賴
      • 3.3 撰寫`ConfigInfo.java`、`ConfigService.java`、 `ConfigServiceImpl.java`
      • 3.4 撰寫ConfigProperties.java
      • 3.5 撰寫ConfigAutoConfiguration.java
      • 3.6 撰寫spring.factories
      • 3.7 發布自定義 starter
      • 3.8 測驗自定義 starter
        • 3.8.1 添加config-spring-boot-starter依賴
        • 3.8.2 配置application.yml
        • 3.8.3 撰寫 ConfigInfoController.java
        • 3.8.4 啟動測驗
    • 4. Spring Boot Starter原理
      • 4.1 自動配置原理
        • 4.1.1 自動配置類的獲取與注入
        • 4.1.2 自動配置的程序
      • 4.2 Spring Boot自動配置使用總結

企業級spring-boot案例系列文章上線了,涵蓋了大部分企業級的spring-boot使用場景,會不定期進行更新,企業級spring-boot案例原始碼地址:https://gitee.com/JourWon/spring-boot-example,歡迎各位大佬一起學習和指正

1. 未使用Spring Boot Starter前的情況

在沒有 starter 之前,假如我想要在 Spring 中使用 jpa,那我可能需要做以下操作:

  1. 在 Maven 中引入使用的資料庫的依賴(即 JDBC 的 jar)
  2. 引入 jpa 的依賴
  3. 在 xxx.xml 中配置一些屬性資訊
  4. 反復的除錯直到可以正常運行

需要注意的是,上面的操作在我們每次新建一個需要用到 jpa 的專案的時候都需要重復的做一次

但在 Spring Boot 中,一切因為 Starter 變得簡單

  1. pom 檔案中引入 spring-boot-starter-data-jpa
  2. .properties 檔案中配置引數

通過上面兩個步驟,配置自動生效,具體生效的 beanJpaRepositoriesAutoConfiguration,自動配置類的名字都有一個特點,叫做 xxxAutoConfiguration

這就是使用 Spring 框架開發專案帶來的一些的問題:

  • 依賴匯入問題: 每個專案都需要來單獨維護自己所依賴的jar包,在專案中使用到什么功能就需要引入什么樣的依賴,手動匯入依賴容易出錯,且無法統一集中管理
  • 配置繁瑣: 在引入依賴之后需要做繁雜的配置,并且這些配置是每個專案來說都是必要的,例如web.xml配置(Listener配置、Filter配置、Servlet配置)、log4j配置、資料庫連接池配置等等,這些配置重復且繁雜,在不同的專案中需要進行多次重復開發,這在很大程度上降低了我們的開發效率

而在 Spring Boot 出現之后,它為我們提供了一個強大的功能來解決上述的兩個痛點,這就是 Spring Boot 的 starters(啟動器),

2. Spring Boot Starter簡介

2.1 什么是Spring Boot Starter(啟動器)

Spring Boot 通過將我們常用的功能抽取出來,做成的一系列啟動器,這些啟動器幫我們匯入了實作各個功能所需要依賴的全部組件,我們只需要在專案中引入這些 starters,需要的依賴就會全部被匯入進來,并且我們通過【約定大于配置】的方式,拋棄繁雜的配置,僅需要通過組態檔來進行少量的配置就可以使用相應的功能,

starter 的實作:雖然不同的 starter 實作起來各有差異,但是他們基本上都會使用到兩個相同的內容:ConfigurationProperties 和 AutoConfiguration,因為 Spring Boot 堅信 “約定大于配置” 這一理念,所以我們使用 ConfigurationProperties 來保存我們的配置,并且這些配置都可以有一個默認值,即在我們沒有主動覆寫原始配置的情況下,默認值就會生效,這在很多情況下是非常有用的,除此之外,starter 的 ConfigurationProperties 還使得所有的配置屬性被聚集到一個檔案中(一般在 resources 目錄下的 application.properties),這樣我們就告別了 Spring 專案中眾多的 XML 配置,

2.2 Starter 模塊整體結構

starter的整體實作邏輯主要由兩個基本部分組成:

xxxAutoConfiguration:自動配置類,對某個場景下需要使用到的一些組件進行自動注入,并利用xxxProperties類來進行組件相關配置

xxxProperties:某個場景下所有可配置屬性的集成,在組態檔中配置可以進行屬性值的覆寫,按照SpringBoot官方的定義,Starer的作用就是依賴聚合,因此直接在starter內部去進行代碼實作是不符合規定的,starter應該只起到依賴匯入的作用,而具體的代碼實作應該交給其他模塊來實作,然后在starter中去參考該模塊即可,因此整體的starter的構成應該如下圖所示:

可見starter模塊依賴了兩部分,一部分是一些常用依賴,另一部分就是對自動配置模塊的依賴,而xxxAutoConfigurationxxxProperties的具體實作,都封裝在自動配置模塊中,starter實際是通過該模塊來對外提供相應的功能,

2.3 Spring 官方提供的 Starter 和 Starter 命名規范

SpringBoot 提供了非常多的 Starter,下面列出常用的幾個:

序號名稱功能
1spring-boot-starter-web支持 Web 開發,包括 Tomcat 和 spring-webmvc
2spring-boot-starter-redis支持 Redis 鍵值存盤資料庫,包括 spring-redis
3spring-boot-starter-test支持常規的測驗依賴,包括 JUnit、Hamcrest、Mockito 以及 spring-test 模塊
4spring-boot-starter-aop支持面向切面的編程即 AOP,包括 spring-aop 和 AspectJ
5spring-boot-starter-data-elasticsearch支持 ElasticSearch 搜索和分析引擎,包括 spring-data-elasticsearch
6spring-boot-starter-jdbc支持JDBC資料庫
7spring-boot-starter-data-jpa支持 JPA ,包括 spring-data-jpa、spring-orm、Hibernate

可以看到這些 Starter 的名稱都是以 spring-boot-starter 為開頭,后面跟著具體的模塊名,所有官方的 Starter 遵循相似的命名模式,

根據約定,Spring Boot官方的starter命名要定義為spring-boot-starter-*,自定義或者說第三方的要命名為thirdpartyproject-spring-boot-starter

  • 官方命名空間
    • 前綴:spring-boot-starter-
    • 模式:spring-boot-starter-模塊名
    • 舉例:spring-boot-starter-web、spring-boot-starter-actuator、spring-boot-starter-jdbc
  • 自定義命名空間
    • 后綴:-spring-boot-starter
    • 模式:模塊-spring-boot-starter
    • 舉例:mybatis-spring-boot-starter

3. 自定義Spring Boot Starter

如果你想要自己創建一個 starter,那么基本上包含以下幾步

3.1 根據 starter 命名規范創建一個 spring boot 專案

創建一個名為config-spring-boot-starter的 spring boot 專案

3.2 在 pom.xml 檔案中引入依賴

<!-- 自動配置依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

<!-- 將被@ConfigurationProperties注解的類的屬性注入到元資料 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

<!-- starter非必須依賴,使用到了可以添加 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

3.3 撰寫ConfigInfo.javaConfigService.javaConfigServiceImpl.java

ConfigInfo 配置資訊類,用于封裝配置資訊,

@Data
@Builder
public class ConfigInfo implements Serializable {

    private static final long serialVersionUID = -2878523532668902073L;

    /**
     * ID
     */
    private String id;

    /**
     * IP地址
     */
    private String ip;

}

ConfigService 示例業務介面,這里我們定義了一個configInfo介面,用于獲取配置資訊,

public interface ConfigService {

    /**
     * 獲取配置資訊
     *
     * @return {@link ConfigInfo}
     */
    ConfigInfo configInfo();

}

ConfigServiceImpl 業務邏輯實作類,用于實作功能,

public class ConfigServiceImpl implements ConfigService {

    /**
     * ID
     */
    private String id;
    /**
     * ip
     */
    private String ip;

    /**
     * 建構式
     *
     * @param id ID
     * @param ip IP
     */
    public ConfigServiceImpl(String id, String ip) {
        this.id = id;
        this.ip = ip;
    }

    /**
     * 獲取配置資訊
     *
     * @return {@link ConfigInfo}
     */
    @Override
    public ConfigInfo configInfo() {
        return ConfigInfo.builder().id(this.id).ip(this.ip).build();
    }

}

3.4 撰寫ConfigProperties.java

創建一個組態檔讀取類 ConfigurationProperties 用于保存配置資訊(如果你的專案不使用配置資訊則可以跳過這一步,不過這種情況非常少見)

@ConfigurationProperties注解使開發人員可以輕松地將整個檔案.propertiesyml檔案映射到一個物件中,撰寫Properties,應使用唯一的名稱空間,不要使用Spring Boot的名稱空間(如server,management,spring等),所以應在所有配置鍵前面加上自己的名稱空間,如我們這里使用的是com.jourwon.config作為配置名稱空間,

@Data
@ConfigurationProperties(value = "com.jourwon.config")
public class ConfigProperties {

    /**
     * ID標識
     */
    private String id;

    /**
     * IP地址
     */
    private String ip;

}

3.5 撰寫ConfigAutoConfiguration.java

創建一個 AutoConfiguration,撰寫帶有@Configuration的配置類,并添加@EnableConfigurationProperties注解,@EnableConfigurationProperties作用是為了使@ConfigurationProperties注解的類生效,

@Slf4j
@Configuration
@EnableConfigurationProperties(value = ConfigProperties.class)
public class ConfigAutoConfiguration {

    @Resource
    private ConfigProperties properties;

    /**
     * 配置ExampleService
     *
     * @return {@link ConfigService}
     */
    @Bean
    @ConditionalOnMissingBean
    public ConfigService configService() {
        log.info("Config ConfigService Start...");
        ConfigService service = new ConfigServiceImpl(properties.getId(), properties.getIp());
        log.info("Config ConfigService End.");
        return service;
    }

}

3.6 撰寫spring.factories

resources/META-INF/下創建spring.factories檔案,并且把上一步創建的AutoConfiguration類加入 spring.factories 組態檔中

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jourwon.spring.boot.config.ConfigAutoConfiguration

3.7 發布自定義 starter

在自定義 starter 專案根目錄執行 mvn install 進行打包安裝

3.8 測驗自定義 starter

3.8.1 添加config-spring-boot-starter依賴

<properties>
    <config-spring-boot-starter.version>1.0.0</config-spring-boot-starter.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.jourwon.spring.boot</groupId>
        <artifactId>config-spring-boot-starter</artifactId>
        <version>${config-spring-boot-starter.version}</version>
    </dependency>

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

    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>
</dependencies>

3.8.2 配置application.yml

IDE 提示

在使用官方starter的時候,我們可以發現IDE可以進行提示

在這里插入圖片描述

application.yml組態檔添加如下配置

# 自定義starter相關配置
com:
  jourwon:
    config:
      id: 23145fdb-7427-42d1-ae29-a67f5be30d02
      ip: 127.0.0.1

3.8.3 撰寫 ConfigInfoController.java

@RestController
public class ConfigInfoController {

    @Resource
    private ConfigService configService;

    @GetMapping("/configInfo")
    public String configInfo() {
        return JSON.toJSONString(configService.configInfo());
    }

}

3.8.4 啟動測驗

打開瀏覽器,輸入 http://127.0.0.1:8080/configInfo ,你將會看到我們配置的內容,

在這里插入圖片描述

4. Spring Boot Starter原理

首先說說原理,我們知道使用一個公用的starter的時候,只需要將相應的依賴添加的Maven的組態檔當中即可,免去了自己需要參考很多依賴類,并且SpringBoot會自動進行類的自動配置,

在匯入的starter之后,SpringBoot主要幫我們完成了兩件事情:

  • 相關組件的自動匯入
  • 相關組件的自動配置

這兩件事情統一稱為SpringBoot的自動配置

那么 SpringBoot 是如何知道要實體化哪些類,并進行自動配置的呢? 下面簡單說一下,

首先,SpringBoot 在啟動時會去依賴的starter包中尋找 resources/META-INF/spring.factories檔案,然后根據檔案中配置的Jar包去掃描專案所依賴的Jar包,這類似于 Java 的 SPI 機制,

第二步,根據 spring.factories配置加載AutoConfigure類,

最后,根據 @Conditional注解的條件,進行自動配置并將Bean注入Spring Context 背景關系當中,

我們也可以使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自動配置哪些類,

4.1 自動配置原理

4.1.1 自動配置類的獲取與注入

我們從主程式入口來探索一下整個程序的原理:

//標注這個類是一個springboot的應用
@SpringBootApplication
public class CommunityApplication {
    public static void main(String[] args) {
        //將springboot應用啟動
        SpringApplication.run(CommunityApplication.class, args);
    }
}

@SpringBootApplication注解內部結構如下圖所示:

AutoConfigurationImportSelector :重點看該類中重寫的selectImports方法,看下它回傳的字串陣列是如何得來的:

圖片

我們可以去到上邊提到的spring.factories檔案中去看一下,找到spring官方提供的spring-boot-autoconfigure包,在其下去找一下該檔案:

圖片

可以看到這個就是SpringBoot官方為我們提供的所有自動配置類的候選串列,我們可以在其中找到一個我們比較熟悉的自動配置類去看一下它內部的實作:

可以看到這些一個個的都是JavaConfig配置類,而且都通過@Bean注解向容器中注入了一些Bean

圖片

結論:

  • SpringBoot在啟動的時候從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的所有自動配置類的全限定類名
  • 將這些自動配置類匯入容器,自動配置類就生效,幫我們進行自動配置作業;
  • 整個J2EE的整體解決方案和自動配置都在spring-boot-autoconfigure的jar包中;
  • 它會給容器中匯入非常多的自動配置類 (xxxAutoConfiguration), 就是給容器中匯入這個場景需要的所有組件,并配置好這些組件 ;
  • 有了自動配置類,免去了我們手動撰寫配置注入功能組件等的作業;

4.1.2 自動配置的程序

自動配置類被注入到容器當中后,會幫我們進行組件的自動配置和自動注入的作業,我們以HttpEncodingAutoConfiguration(Http編碼自動配置)為例解釋這個程序:

首先我們先看下SpringBoot中組態檔與POJO類之間映射的方法,這是進行自動配置的基礎,

配置集中化管理:SpringBoot中所有可配置項都集中在一個檔案中(application.yml),這個檔案中的配置通過@ConfigurationProperties注解來與我們程式內部定義的POJO類來產生關聯,這些POJO類統一命名為xxxProperties,并且這些xxxProperties類中各個屬性欄位都有自己的默認值,這也是SpringBoot約定大于配置理念的體現,盡可能減少用戶做選擇的次數,但同時又不失靈活性,只要我們想,組態檔中的配置隨時可以覆寫默認值,

在這里插入圖片描述

之后,通過配合@EnableConfigurationProperties注解,就可以自動將與組態檔系結好的這個類注入到容器中供我們使用,

自動配置類的作業流程:

  • 根據限定的條件向容器中注入組件
  • 使用xxxProperties對注入的組件的相關屬性進行配置
//表示這是一個配置類,和以前撰寫的組態檔一樣,也可以給容器中添加組件;
@Configuration

//將與組態檔系結好的某個類注入到容器中,使其生效
//進入這個HttpProperties查看,將組態檔中對應的值和HttpProperties系結起來;
//并把HttpProperties加入到ioc容器中
@EnableConfigurationProperties(HttpProperties.class)

//Spring底層@Conditional注解
//根據不同的條件判斷,如果滿足指定的條件,整個配置類里面的配置就會生效;
//這里的意思就是判斷當前應用是否是web應用,如果是,當前配置類生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)

//判斷系統中有沒有CharacterEncodingFilter這個類,如果有配置類才生效
@ConditionalOnClass(CharacterEncodingFilter.class)

//判斷組態檔中是否存在某個配置:spring.http.encoding.enabled;
//matchIfMissing = true表明即使我們組態檔中不配置spring.http.encoding.enabled=true,該配置類也是默認生效的;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    //該類已經與組態檔系結了
    private final HttpProperties.Encoding properties;

    //構建該自動配置類時將與組態檔系結的配置類作為入參傳遞進去
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }

    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        //注入bean時使用配置類中屬性的值進行初始化,相當于將組態檔中的值映射到了組件的某些屬性上
        filter.setEncoding(this.properties.getCharset().name()); 
        filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
        //注入配置好的bean
        return filter; 
    }
}

一句話總結下自動配置類的作業程序 :

  • 首先容器會根據當前不同的條件判斷,決定這個配置類是否生效!
  • 一但這個配置類生效;這個配置類就會給容器中添加相應組件;
  • 這些組件的屬性是從對應的properties類中獲取的,這些類里面的每一個屬性又是和組態檔系結的;
  • 所有在組態檔中能配置的屬性都是在xxxxProperties類中封裝著,組態檔可以配置什么內容,可以參照該前綴對應的屬性類中的屬性欄位
//從組態檔中獲取指定的值和bean的屬性進行系結
@ConfigurationProperties(prefix = "spring.http") 
public class HttpProperties {
    // .....
}

4.2 Spring Boot自動配置使用總結

  • SpringBoot啟動會加載大量的自動配置類

  • 我們首先可以看我們需要的功能有沒有在SpringBoot默認寫好的自動配置類當中;

  • 我們再來看這個自動配置類中到底配置了哪些組件;(只要我們要用的組件存在在其中,我們就不需要再手動配置了)

  • 給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性,我們只需要在組態檔中指定這些屬性的值即可;

    • xxxxAutoConfigurartion:自動配置類;給容器中添加組件
    • xxxxProperties:封裝組態檔中相關屬性;

了解完自動裝配的原理后,我們來關注一個細節問題,自動配置類必須在一定的條件下才能生效;@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必須是@Conditional指定的條件成立,才給容器中添加組件,配置里面的所有內容才生效;

序號@Conditional擴展注解作用(判斷是否滿足當前條件)
1@ConditionalOnWebApplication當前專案是Web專案的條件下
2@ConditionalOnNotWebApplication當前專案不是Web專案的條件下
3@ConditionalOnResource類路徑下是否有指定的資源
4@ConditionalOnExpression基于SpEL運算式作為判斷條件
5@ConditionalOnMissingBean當容器中沒有指定Bean的情況下
6@ConditionalOnBean當容器中有指定的Bean的條件下
7@ConditionalOnSingleCandidate當指定的Bean在容器中只有一個,或者在有多個Bean的情況下,用來指定首選的Bean
8@ConditionalOnJava基于JVM版本作為判斷條件
9@ConditionalOnMissingClass當類路徑下沒有指定的類的條件下
10@ConditionalOnClass當類路徑下有指定的類的條件下
11@ConditionalOnProperty指定的屬性是否有指定的值

那么多的自動配置類,必須在一定的條件下才能生效;也就是說,我們加載了這么多的配置類,但不是所有的都生效了,

我們怎么知道哪些自動配置類生效?

我們可以通過啟用 debug=true屬性;來讓控制臺列印自動配置報告,這樣我們就可以很方便的知道哪些自動配置類生效;

#在組態檔中開啟springboot的除錯類
debug=true

Positive matches:(自動配置類啟用的:正匹配)

Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'org.springframework.context.annotation.EnableAspectJAutoProxy', 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice', 'org.aspectj.weaver.AnnotatedElement' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.CglibAutoProxyConfiguration matched:
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)

   AuditAutoConfiguration#auditListener matched:
      - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.audit.listener.AbstractAuditListener; SearchStrategy: all) did not find any beans (OnBeanCondition)

   AuditAutoConfiguration#authenticationAuditListener matched:
      - @ConditionalOnClass found required class 'org.springframework.security.authentication.event.AbstractAuthenticationEvent' (OnClassCondition)
      - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener; SearchStrategy: all) did not find any beans (OnBeanCondition)

Negative matches:(沒有啟動,沒有匹配成功的自動配置類:負匹配)

Negative matches:
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

   AopAutoConfiguration.JdkDynamicAutoProxyConfiguration:
      Did not match:
         - @ConditionalOnProperty (spring.aop.proxy-target-class=false) did not find property 'proxy-target-class' (OnPropertyCondition)

   AppOpticsMetricsExportAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'io.micrometer.appoptics.AppOpticsMeterRegistry' (OnClassCondition)

   ArtemisAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

Exclusions、Unconditional classes(排除的、沒有限定條件的自動配置類):

Exclusions:
-----------

    org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration


Unconditional classes:
----------------------

    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

    org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration

    org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration

    org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/402719.html

標籤:java

上一篇:【JavaSE基礎】基本資料型別族譜及易錯點代碼分析

下一篇:【Java資料結構】搜索二叉樹——對節點的插入、查找、洗掉 操作(注釋很詳細我奶奶都能看懂)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more