<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ## 版本更新說明 * SpringBlade 4.0 版本已適配 Spring Boot 3 和 JDK 17,并從 Swagger 2 遷移到 OpenAPI 3。此次更新包含重大更改,屬于破壞性更新。 * **若從SpringBlade 4.0版本開始使用,本章節可以直接跳過** * 若之前版本的工程已處于生產階段或接近開發完成,請在升級前仔細權衡。 * 接下來,我們將詳細列出工程升級的步驟及注意事項。 ## 項目編譯級別升級為JDK17 ### 下載安裝jdk17 1. 下載openjdk17,前往下載地址找到符合自己機器的版本并安裝配置環境變量,三種推薦版本選其一或公司選型的Jdk均可 2. 下載地址(Azul Zulu):[https://www.azul.com/downloads/?version=java-17-lts&package=jdk#zulu](https://www.azul.com/downloads/?version=java-17-lts&package=jdk#zulu) 3. 下載地址(Eclipse Temurin?):[https://adoptium.net/zh-CN/temurin/releases/?version=17](https://adoptium.net/zh-CN/temurin/releases/?version=17) 4. 下載地址(Amazon Corretto):[https://aws.amazon.com/cn/corretto/?filtered-posts.sort-by=item.additionalFields.createdDate&filtered-posts.sort-order=desc](https://aws.amazon.com/cn/corretto/?filtered-posts.sort-by=item.additionalFields.createdDate&filtered-posts.sort-order=desc) #### 配置工程編譯級別為jdk17 1. 打開工程后選擇 `Project Structure` ![](https://img.kancloud.cn/9a/b8/9ab85f1f200efe2b17201b02ee0eac3f_790x1142.png) 2. 依次配置版本為JDK17 ![](https://img.kancloud.cn/7e/9c/7e9c047abba0643fd6675eb573990e06_1886x3158.png) 3. 打開設置找到Java Compiler設置為17 ![](https://img.kancloud.cn/a3/86/a38666eeb964d8dbc473a9c27c09ef49_1994x1424.png) 4. 打開設置找到Maven Runner設置為17 ![](https://img.kancloud.cn/80/0e/800e80444c73ccaa97fff09038cdd545_1994x1424.png) ## API升級 1. Spring Boot 3 與 JDK17開始,由 Java EE 升級為 Jakarta EE,我們需要對工程源碼進行全局替換。 ~~~ javax.validation ? ? → ? ? jakarta.validation javax.servlet ? ? ? ?→ ? ? jakarta.servlet javax.annotation ? ? → ? ? jakarta.annotation javax.transaction ? ?→ ? ? jakarta.transaction javax.persistence ? ?→ ? ? jakarta.persistence ~~~ 2. 由于部分api已經過期刪除但業務代碼用到相關api,我們需要重新引入 (Tool工程已經處理,業務代碼若需要則加上對應依賴) ~~~ <!-- jakarta --> <dependency> ? ?<groupId>jakarta.servlet</groupId> ? ?<artifactId>jakarta.servlet-api</artifactId> </dependency> <!-- javax --> <dependency> ? ?<groupId>javax.xml.bind</groupId> ? ?<artifactId>jaxb-api</artifactId> </dependency> <dependency> ? ?<groupId>com.sun.xml.bind</groupId> ? ?<artifactId>jaxb-core</artifactId> </dependency> <dependency> ? ?<groupId>com.sun.xml.bind</groupId> ? ?<artifactId>jaxb-impl</artifactId> </dependency> <dependency> ? ?<groupId>javax.activation</groupId> ? ?<artifactId>activation</artifactId> </dependency> ~~~ 3. 原 `spring.redis` 配置升級為 `spring.data.redis` ,以下為最新版本配置 ~~~ spring: data: ? redis: ? ? host: 127.0.0.1 ? ? port: 6379 ? ? password: ? ? database: 0 ? ? ssl: ? ? ? enabled: false ~~~ 4. 針對反射工具類進行全局替換 ~~~ BeanUtil.copy ? ?→ ? ? BeanUtil.copyProperties ~~~ ![](https://img.kancloud.cn/9a/ff/9aff6dc699bfd22ef016b089bfb26b66_1708x1066.png) 5. 工程pom.xml版本升級 ~~~ <revision>3.4.0.RELEASE</revision> ? <java.version>1.8</java.version> <maven.plugin.version>3.8.1</maven.plugin.version> <maven.flatten.version>1.2.2</maven.flatten.version> ~~~ 【替換為】 ~~~ <revision>4.0.0.RELEASE</revision> ? <java.version>17</java.version> <maven.plugin.version>3.11.0</maven.plugin.version> <maven.flatten.version>1.3.0</maven.flatten.version> ~~~ 6. 序列化加上注解 `@Serial` ~~~ package org.springblade.system.entity; ? import java.io.Serial; import java.io.Serializable; ? public class Entity implements Serializable { ? @Serial private static final long serialVersionUID = 1L; } ~~~ ## Swagger升級 1. 由原本的Swagger2 改用 OpenAPI3。Knife4J采用支持OpenAPI3的版本,我們需要對依賴、注解、引用進行全局替換 2. Knife4j前端ui依賴 ~~~ <dependency> ? ?<groupId>com.github.xiaoymin</groupId> ? ?<artifactId>knife4j-openapi2-ui</artifactId> </dependency> ~~~ 【替換為】 ~~~ <dependency> ? ?<groupId>com.github.xiaoymin</groupId> ? ?<artifactId>knife4j-openapi3-ui</artifactId> </dependency> ~~~ 3. Knife4j核心依賴 ~~~ <dependency> ? ?<groupId>com.github.xiaoymin</groupId> ? ?<artifactId>knife4j-openapi2-spring-boot-starter</artifactId> </dependency> ~~~ 【替換為】 ~~~ <dependency> ? ?<groupId>com.github.xiaoymin</groupId> ? ?<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> </dependency> ~~~ 4. SpringFox移除改為新版依賴 ~~~ <dependency> ? ?<groupId>io.springfox</groupId> ? ?<artifactId>springfox-swagger2</artifactId> ? ?<exclusions> ? ? ? ?<exclusion> ? ? ? ? ? ?<groupId>io.swagger</groupId> ? ? ? ? ? ?<artifactId>swagger-models</artifactId> ? ? ? ?</exclusion> ? ?</exclusions> </dependency> <dependency> ? ?<groupId>io.swagger</groupId> ? ?<artifactId>swagger-models</artifactId> </dependency> ~~~ 【替換為】 ~~~ <dependency> ? ?<groupId>io.swagger.core.v3</groupId> ? ?<artifactId>swagger-annotations</artifactId> </dependency> ~~~ 5. Swagger2注解全局替換為OpenAPI3(Swagger3)注解 * 全局替換如下注解(箭頭前為swagger2注解需要被全局替換為箭頭后的openapi3注解) * 具體參數使用對比如下(快捷替換可以將`@Api(value`全局替換為`@Tag(name`,其他的以此類推) ~~~ @Api(value = "xx", tags = "xxx") → @Tag(name = "xx", description = "xxx") ? @ApiIgnore → @Hidden (若是在方法入參則將@Hidden改為@Parameter(hidden = true)替換) ? @ApiModel(value = "xx", description = "xx") → @Schema(description = "xx") ? @ApiModelProperty(hidden = true) → @Schema(accessMode = READ_ONLY) @ApiModelProperty(value = "xx") → @Schema(description = "xx") ? @ApiImplicitParams → @Parameters ? @ApiImplicitParam → @Parameter ? @ApiOperation(value = "xx", notes = "xx") → @Operation(summary = "xx", description = "xx") ? @ApiParam("xx") → @Parameter(name = "xx") @ApiParam(value = "xx") → @Parameter(name = "xx") ? @ApiResponse(code = 404, message = "msg") → @ApiResponse(responseCode = "404", description = "msg") ~~~ * 較為復雜的組合式注解前后對比如下 ~~~ @ApiImplicitParams({ ?@ApiImplicitParam(name = "category", value = "公告類型", paramType = "query", dataType = "integer"), ?@ApiImplicitParam(name = "title", value = "公告標題", paramType = "query", dataType = "string") ? }) @ApiOperation(value = "分頁", notes = "傳入notice") ~~~ ? ? ~~~ @Parameters({ ?@Parameter(name = "category", description = "公告類型", in = ParameterIn.QUERY, schema = @Schema(type = "integer")), ?@Parameter(name = "title", description = "公告標題", in = ParameterIn.QUERY, schema = @Schema(type = "string")) ? }) @Operation(summary = "分頁", description = "傳入notice") ~~~ * 剩余無法全局替換的再手動處理 * 比如我們可以先全局替換`@ApiImplicitParam`為`@Parameter` * 接著全局替換`paramType = "query", dataType = "integer"`為`in = ParameterIn.QUERY, schema = @Schema(type = "integer")` * 經過兩波替換,剩下一個`, value = "`再全局替換為`, description = "` * 前面帶一個逗號可以避免將 `@ApiOperation(value`的value值替換為`description`,因為`@ApiOperation`對應的是`summary` 6. 包路徑全局替換 ~~~ import springfox.documentation.annotations.ApiIgnore; → import io.swagger.v3.oas.annotations.Hidden; ? import io.swagger.annotations.ApiModelProperty; → import io.swagger.v3.oas.annotations.media.Schema; ? import io.swagger.annotations.ApiModel; → import io.swagger.v3.oas.annotations.media.Schema; ? import io.swagger.annotations.ApiImplicitParams; → import io.swagger.v3.oas.annotations.Parameters; ? import io.swagger.annotations.ApiImplicitParam; → import io.swagger.v3.oas.annotations.Parameter; ? import io.swagger.annotations.ApiOperation; → import io.swagger.v3.oas.annotations.Operation; ? import io.swagger.annotations.ApiParam; → import io.swagger.v3.oas.annotations.Parameter; ? import io.swagger.annotations.Api; → import io.swagger.v3.oas.annotations.tags.Tag; ? import io.swagger.annotations.ApiResponse; → import io.swagger.v3.oas.annotations.responses.ApiResponse; ? import io.swagger.annotations.*; ?→ import io.swagger.v3.oas.annotations.*; ~~~ 7. Swagger2配置類升級為OpenAPI3寫法 * 原寫法如下 ~~~ public class SwaggerConfiguration { ? @Bean public Docket authDocket() { return docket("授權模塊", Collections.singletonList(AppConstant.BASE_PACKAGES + ".modules.auth")); } ? @Bean public Docket sysDocket() { return docket("系統模塊", Arrays.asList(AppConstant.BASE_PACKAGES + ".modules.system", AppConstant.BASE_PACKAGES + ".modules.resource")); } ? @Bean public Docket flowDocket() { return docket("工作流模塊", Collections.singletonList(AppConstant.BASE_PACKAGES + ".flow")); } ? } ~~~ * 新寫法如下 ~~~ public class SwaggerConfiguration { ? @Bean public GroupedOpenApi authApi() { return GroupedOpenApi.builder() .group("授權模塊") .packagesToScan(AppConstant.BASE_PACKAGES + ".modules.auth") .build(); } ? @Bean public GroupedOpenApi sysApi() { return GroupedOpenApi.builder() .group("系統模塊") .packagesToScan(AppConstant.BASE_PACKAGES + ".modules.system", AppConstant.BASE_PACKAGES + ".modules.resource") .build(); } ? @Bean public GroupedOpenApi flowApi() { // 創建并返回GroupedOpenApi對象 return GroupedOpenApi.builder() .group("工作流模塊") .packagesToScan(AppConstant.BASE_PACKAGES + ".flow") .build(); } ? } ~~~ 8. Swagger文檔訪問地址,springcloud與springboot地址通用 * 文檔地址:[http://localhost/doc.html](http://localhost/doc.html) 9. 由于需要同時生效兩套swagger的ui,我們刪除了blade-swagger服務,重新改為springcloud聚合文檔的實現方式。文檔默認使用knife4j的ui,地址:[http://localhost/doc.html](http://localhost/doc.html),若需要使用swagger-ui,在blade-gateway的pom.xml加入如下配置,然后訪問[http://localhost/swagger-ui.html](http://localhost/swagger-ui.html) 便可 ~~~ <dependency> ? ?<groupId>org.springdoc</groupId> ? ?<artifactId>springdoc-openapi-starter-webflux-ui</artifactId> </dependency> ~~~ 10. springboot無需操作,直接訪問 [http://localhost/swagger-ui.html](http://localhost/swagger-ui.html) 便可 ### Mybatis-Plus升級 1. mybatis-plus啟動依賴 ~~~ <dependency> ? ?<groupId>com.baomidou</groupId> ? ?<artifactId>mybatis-plus-boot-starter</artifactId> ? ?<version>${mybatis.plus.version}</version> </dependency> ~~~ 【替換為】 ~~~ <dependency> ? ?<groupId>com.baomidou</groupId> ? ?<artifactId>mybatis-plus-spring-boot3-starter</artifactId> ? ?<version>${mybatis.plus.version}</version> </dependency> ~~~ 2. dynamic-datasource啟動依賴 ~~~ <dependency> ? ?<groupId>com.baomidou</groupId> ? ?<artifactId>dynamic-datasource-spring-boot-starter</artifactId> ? ?<version>${mybatis.plus.dynamic.version}</version> </dependency> ~~~ 【替換為】 ~~~ <dependency> ? ?<groupId>com.baomidou</groupId> ? ?<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> ? ?<version>${mybatis.plus.dynamic.version}</version> </dependency> ~~~ 3. 由于mybatis-plus依賴的mybatis-spring版本會導致工程無法啟動,需要將mybatis-plus指定適配版本 ~~~ <dependency> ? ?<groupId>org.mybatis</groupId> ? ?<artifactId>mybatis-spring</artifactId> ? ?<version>3.0.3</version> </dependency> ~~~ 4. 以上升級均在tool工程處理完畢,大家業務工程無需處理,若有自定義二開tool工程的情況請知悉 ### Druid升級 1. druid啟動依賴 ~~~ <dependency> ? ?<groupId>com.alibaba</groupId> ? ?<artifactId>druid-spring-boot-starter</artifactId> </dependency> ~~~ 【替換為】 ~~~ <dependency> ? ?<groupId>com.alibaba</groupId> ? ?<artifactId>druid-spring-boot-3-starter</artifactId> </dependency> ~~~ 2. 以上升級均在tool工程處理完畢,大家業務工程無需處理,若有自定義二開tool工程的情況請知悉 ### Ureport升級 1. 由于ureport還未支持springboot3與jdk17,bladex官方對其進行了升級適配,直接升級tool工程便可以無縫使用 2. 具體源碼請看:https://gitee.com/smallc/blade-tool/tree/master/blade-core-report ## 反射 1. 升級到Java17后,如果未進行模塊化命名,使用反射則會報如下錯誤:`module java.base does not "opens java.lang" to unnamed module)` 2. 從Java 9開始引入的模塊系統增加了對JVM內部API的封裝,以促進Java平臺的封裝性和安全性。默認情況下,Java核心庫中的很多內部API和類都不再對外公開,除非顯式地使用`--add-opens`選項來開放它們。 3. 為了解決老版本源碼使用反射但未模塊化到問題,可以通過在Java命令行中添加`--add-opens`參數來實現,格式如下: ~~~ java --add-opens java.base/java.lang=ALL-UNNAMED -jar your-application.jar ~~~ ## JDK17+ZGC JDK 17引入了很多重要的特性,其中之一是Z Garbage Collector (ZGC) 的正式支持。ZGC是一種可伸縮的垃圾收集器,旨在減少應用程序停頓時間,無論是在小型還是大型堆上。它最初在JDK 11中作為實驗性特性引入,但到了JDK 17,ZGC成為了正式支持的特性。 #### 1\. ZGC的主要特點包括: * **低延遲**:ZGC的設計目標是將停頓時間限制在幾毫秒內,甚至在大堆上也是如此。 * **可伸縮性**:ZGC旨在處理從幾百兆字節到幾個太字節大小的堆,而不會顯著增加停頓時間。 * **無內存抖動**:ZGC幾乎不產生內存抖動,這對于需要穩定和可預測性能的應用程序來說非常重要。 #### 2\. 使用ZGC 在JDK 17中使用ZGC非常簡單。只需要在啟動Java應用程序時通過命令行參數指定使用ZGC即可。以下是一個示例命令行,它啟動了一個使用ZGC的Java應用程序: ~~~ java -XX:+UseZGC -jar your-application.jar ~~~ 這個命令告訴JVM使用ZGC作為垃圾收集器。請注意,使用ZGC可能需要您根據應用程序的具體情況調整其他JVM參數,以獲得最佳性能。 #### 3.示例 假設有一個簡單的Java應用程序,它在運行過程中不斷創建新對象,模擬了一個典型的業務應用負載。在使用ZGC的情況下,可以觀察到即使在高負載下,應用程序的停頓時間也保持在很低的水平。 ~~~ public class ZGCDemo { ? ?public static void main(String[] args) { ? ? ? ?List<Object> list = new ArrayList<>(); ? ? ? ?while (true) { ? ? ? ? ? ?list.add(new Object()); ? ? ? ? ? ?if (list.size() > 10000) { ? ? ? ? ? ? ? ?list.clear(); ? ? ? ? ? } ? ? ? } ? } } ~~~ 在這個示例中,我們不斷地創建并清理對象,以模擬一個持續的負載。使用ZGC時,即使這種類型的工作負載可能導致大量的垃圾收集活動,應用程序的停頓時間也可以保持在極低的水平。 請注意,雖然ZGC能夠顯著減少停頓時間,但選擇合適的垃圾收集器還需考慮應用程序的具體需求和工作負載特性。在某些情況下,其他垃圾收集器(如G1 GC)可能更適合您的應用程序。 #### 4\. 推薦使用的ZGC配置 ~~~ # 垃圾收集器 # 使用ZGC垃圾收集器 JAVA_OPTS="-XX:+UseZGC" # 解鎖診斷VM選項 JAVA_OPTS="-XX:+UnlockDiagnosticVMOptions" # 設置ZGC統計信息的記錄間隔(秒) JAVA_OPTS="-XX:ZStatisticsInterval=10" ? # 內存 # 設置JVM最小堆大小為512m JAVA_OPTS="-Xms512m" # 設置JVM最大堆大小為1024m JAVA_OPTS="-Xmx1024m" # 允許未命名模塊訪問java.base模塊中java.lang包的所有成員 JAVA_OPTS="--add-opens=java.base/java.lang=ALL-UNNAMED" # 允許未命名模塊訪問java.base模塊中java.util包的所有成員 JAVA_OPTS="--add-opens=java.base/java.util=ALL-UNNAMED" # 將java.base模塊中sun.security.ssl包的所有成員導出給所有未命名模塊 JAVA_OPTS="--add-exports=java.base/sun.security.ssl=ALL-UNNAMED" # 允許未命名模塊訪問java.base模塊中sun.security.ssl.internal.ssl包的所有成員 JAVA_OPTS="--add-opens=java.base/sun.security.ssl.internal.ssl=ALL-UNNAMED" ? # 日志 # 打印出JVM啟動時接收的命令行標志 JAVA_OPTS="-XX:+PrintCommandLineFlags" # 配置垃圾收集日志,包括日志文件的位置、名稱、記錄的信息(時間、運行時間)、日志文件的數量和大小限制 JAVA_OPTS="-Xlog:gc*:file=${LOG_DIR}/${PROJ_NAME}-gc-%p.log:time,uptime:filecount=10,filesize=50M" # 在內存溢出時生成堆轉儲 JAVA_OPTS="-XX:+HeapDumpOnOutOfMemoryError" # 指定堆轉儲文件的路徑和名稱 JAVA_OPTS="-XX:HeapDumpPath=${LOG_DIR}/${PROJ_NAME}-`date +%s`-pid$$.hprof" # 指定JVM崩潰日志(如JVM錯誤日志)的路徑和名稱 JAVA_OPTS="-XX:ErrorFile=${LOG_DIR}/${PROJ_NAME}-`date +%s`-pid%p.log" ~~~ ## 工程啟動準備 1. 由于升級了JDK17,Java 模塊化系統(Java Module System)的安全限制導致的針對反射等場景有可能會出現如下錯誤: ~~~ Cause: java.lang.reflect.InaccessibleObjectException: Unable to make field protected java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.h accessible: module java.base does not "opens java.lang.reflect" to unnamed module @223aa2f7 ~~~ 2. 這種情況,我們需要在啟動時增加對應配置: ~~~ --add-opens java.base/java.lang.reflect=ALL-UNNAMED ~~~ 3. 具體完整命令,格式如下: ~~~shell java --add-opens java.base/java.lang.reflect=ALL-UNNAMED -jar your-application.jar ~~~ 4. 若依舊報錯可以增加第二個參數`--add-opens java.base/java.lang=ALL-UNNAMED`,格式如下 ~~~shell java --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED -jar your-application.jar ~~~ 5. 若出現如下錯誤:`module java.base does not "opens java.io" to unnamed module`,則額外增加如下配置 ~~~shell -–add-opens java.base/java.io=ALL-UNNAMED ~~~ 6. 若出現如下錯誤:`module java.base does not "opens java.util" to unnamed module`,則額外增加如下配置 ~~~shell -–add-opens java.base/java.util=ALL-UNNAMED ~~~ 7. 其他更多錯誤則可以通過搜索工具,搜索具體報錯來查詢具體對應的配置,配置較多本文檔便不再一一列舉 8. 具體操作如下 ![](https://img.kancloud.cn/61/1c/611c6b5c67966bdaaf5dfd338cb7e149_2326x1354.png) 9. jar包啟動時也需要加入此配置,具體命令如下(增加的命令以最終可運行為準) ~~~ java --add-opens java.base/java.lang.reflect=ALL-UNNAMED -jar your-application.jar ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看