當前位置:
首頁 > 知識 > Spring Boot 2.0 版的開源項目雲升級所帶來的新內容

Spring Boot 2.0 版的開源項目雲升級所帶來的新內容

先給大家曬一下雲收藏的幾個數據,作為一個 Spring Boot 的開源項目(https://github.com/cloudfavorites/favorites-web)目前在 Github 上面已經有1600多個 Star,如果按照 SpringBoot 標籤進行篩選的話也可以排到第五位。

當雲收藏1.0開發完成之後,同步將雲收藏部署到了伺服器上,申請了一個域名www.favorites.ren方便大家使用,到目前為止:網站的註冊用戶4000多人,共計收藏文章100000多條,在百度上搜索:雲收藏,排在第一的就是雲收藏的官網。2年多的時間這個數據其實也並不是很耀眼,但是作為一個學習 Spring Boot 的開源軟體來講,已經不錯了。

雲收藏的部署之路也挺曲折,剛開始的時候部署在我以前公司的伺服器上,後來離職的時候在阿里雲買了個1核1G的雲伺服器,因為安裝了 Mysql、Redis、還有其它小軟體導致伺服器非常卡,那段時間訪問雲收藏的時候需要等待2-3秒才會有響應。

終於有一天自己也不能忍了,花錢把伺服器升級到2核2G,訪問速度雖有所提升但還是很不理想,那段時間工作很忙也沒時間優化。網站的 Bug 也是一片,有時候還會突然中斷服務幾個小時,流失了一大批用戶,甚至有人在 Github 上面留言說:看來微笑哥已經放棄雲收藏了,我看了之後只能苦笑。

到了今年 Spring Boot 2.0 發布的時候,我就計劃著把雲收藏全面升級到2.0,順便做一些優化讓訪問速度快一點。但一拖就是2個月,終於在前幾個周末抽出了一點時間,將雲收藏升級到了 Spring Boot 2.0 同時修復了一批顯而易見的 Bug ,使用 Nginx 將靜態圖片等資源做了代理,當這些工作完全做完的時候,雲收藏的訪問速度明顯得到了提升,大家可以訪問www.favorites.ren體驗一下。

將雲收藏從 Spring Boot 1.0 升級到 2.0 的時候也遇到了一些問題,在修改的過程中記錄下來,今天整理一下分享出來,方便後續升級的朋友少踩一些坑。

1、第一個問題:啟動類報錯

Spring Boot 部署到 Tomcat 中去啟動時需要在啟動類添加 SpringBootServletInitializer,2.0 和 1.0 有區別。

  1. // 1.0
  2. import org.springframework.boot.web.support.SpringBootServletInitializer;
  3. // 2.0
  4. import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
  5. @SpringBootApplication
  6. public class UserManageApplication extends SpringBootServletInitializer {
  7. @Override
  8. protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
  9. return application.sources(UserManageApplication.class);
  10. }
  11. public static void main(String[] args) throws Exception {
  12. SpringApplication.run(UserManageApplication.class, args);
  13. }
  14. }

這個問題好解決只需要重新導包就行。

2、日誌類報錯:Spring Boot 2.0 默認不包含 log4j,建議使用 slf4j 。

  1. import org.apache.log4j.Logger;
  2. protected Logger logger = Logger.getLogger(this.getClass());

改為:

  1. import org.slf4j.Logger;
  2. import org.slf4j.LoggerFactory;
  3. protected Logger logger = LoggerFactory.getLogger(this.getClass());

這個也比較好改動,就是需要替換的文件比較多。

3、Spring Boot 2.0 去掉了 findOne()方法。

以前的 findOne()方法其實就是根據傳入的 Id 來查找對象,所以在 Spring Boot 2.0 的 Repository 中我們可以添加 findById(longid)來替換使用。

例如:

  1. User user=userRepository.findOne(Long id)

改為手動在 userRepository手動添加 findById(longid)方法,使用時將 findOne()調用改為 findById(longid)

  1. User user=userRepository.findById(long id)

delete()方法和 findOne()類似也被去掉了,可以使用 deleteById(Longid)來替換,還有一個不同點是 deleteById(Longid)默認實現返回值為 void。

  1. Long deleteById(Long id);

改為

  1. //delete 改為 void 類型
  2. void deleteById(Long id);

當然我們還有一種方案可以解決上述的兩種變化,就是自定義 Sql,但是沒有上述方案簡單不建議使用。

  1. @Query("select t from Tag t where t.tagId = :tagId")
  2. Tag getByTagId(@Param("tagId") long tagId);

4、雲收藏升級到 2.0 之後,插入數據會報錯,錯誤信息如下:

  1. org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
  2. ....
  3. Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
  4. ...
  5. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry "299" for key "PRIMARY"

這個問題稍稍花費了一點時間,報錯提示的是主鍵衝突,跟蹤資料庫的數據發現並沒有主鍵衝突,最後才發現是 Spring Boot 2.0 需要指定主鍵的自增策略,這個和 Spring Boot 1.0 有所區別,1.0 會使用默認的策略。

  1. @Id
  2. @GeneratedValue(strategy= GenerationType.IDENTITY)
  3. private long id;

改動也比較簡單,需要在所有的主鍵上面顯示的指明自增策略。

5、Thymeleaf 3.0 默認不包含布局模塊。

這個問題比較尷尬,當我將 Pom 包升級到 2.0 之後,訪問首頁的時候一片空白什麼都沒有,查看後台也沒有任何的報錯信息,首先嘗試著跟蹤了 http 請求,對比了一下也沒有發現什麼異常,在查詢 Thymeleaf 3.0 變化時才發現:Spring Boot 2.0 中 spring-boot-starter-thymeleaf 包默認並不包含布局模塊,需要使用的時候單獨添加,添加布局模塊如下:

  1. <dependency>
  2. <groupId>nz.net.ultraq.thymeleaf</groupId>
  3. <artifactId>thymeleaf-layout-dialect</artifactId>
  4. </dependency>

改完之後再訪問首頁,一切正常,但是回頭查看日誌信息發現有一個告警信息:

  1. 2018-05-10 10:47:00.029 WARN 1536 --- [nio-8080-exec-2] n.n.u.t.decorators.DecoratorProcessor : The layout:decorator/data-layout-decorator processor has been deprecated and will be removed in the next major version of the layout dialect. Please use layout:decorate/data-layout-decorate instead to future-proof your code. See https://github.com/ultraq/thymeleaf-layout-dialect/issues/95 for more information.
  2. 2018-05-10 10:47:00.154 WARN 1536 --- [nio-8080-exec-2] n.n.u.t.expressions.ExpressionProcessor : Fragment expression "layout" is being wrapped as a Thymeleaf 3 fragment expression (~{...}) for backwards compatibility purposes. This wrapping will be dropped in the next major version of the expression processor, so please rewrite as a Thymeleaf 3 fragment expression to future-proof your code. See https://github.com/thymeleaf/thymeleaf/issues/451 for more information.

跟蹤地址看了一下,大概的意思是以前布局的標籤已經過期了,推薦使用新的標籤來進行頁面布局,解決方式也比較簡單,修改以前的布局標籤 layout:decorator 為 layout:decorate即可。

6、分頁組件 PageRequest變化。

在 Spring Boot 2.0 中 ,方法 newPageRequest(page,size,sort) 已經過期不再推薦使用,推薦使用以下方式來構建分頁信息:

  1. Pageable pageable =PageRequest.of(page, size, Sort.by(Sort.Direction.ASC,"id"));

跟蹤了一下源碼發現 PageRequest.of()方法,內部還是使用的 newPageRequest(page,size,sort),只是最新的寫法更簡潔一些。

  1. public static PageRequest of(int page, int size, Sort sort) {
  2. return new PageRequest(page, size, sort);
  3. }

7、關聯查詢時候組合返回對象的默認值有變化。

在使用 Spring Boot 1.0 時,使用 Jpa 關聯查詢時我們會構建一個介面對象來接收結果集,類似如下:

  1. public interface CollectView{
  2. Long getId();
  3. Long getUserId();
  4. String getProfilePicture();
  5. String getTitle();
  6. }

在使用 Spring Boot 1.0 時,如果沒有查詢到對應的欄位會返回空,在 Spring Boot 2.0 中會直接報空指針異常,對結果集的檢查會更加嚴格一些。

8、其它優化

前段時間在學習 Docker ,給雲收藏添加了 Docker 、Docker Compose 支持讓部署的時候更簡單一些;同時修復了一些 bug,對於明顯很消耗資源的功能進行了改進,部分功能添加了容錯性;本次部署的時候使用了 Nginx 作為反向代理,因為使用了 WebJars 暫時不能使用 Nginx 代理 Js,所以將除過 Js 以外的其它資源都配置了緩存,;資料庫由 Mysql 換成了 Mariadb。

以上就是雲收藏從 Spring Boot 1.0 到 2.0 所做的一些小改進,做完這些工作之後驚喜的發現雲收藏的訪問速度比以前快了很多,雖然還有很大的優化空間,但日常使用基本上不會體驗到太大的延遲。Spring Boot 2.0 中 Thymeleaf 默認使用了 3.0 ,資料庫連接池默認使用了 Hikari ,這兩個組件在性能上有很大的提升,同時也是提升雲收藏訪問速度的因素之一。

Spring Boot 2.0 版的開源項目雲升級所帶來的新內容

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

W3C的簡介
RSS 的簡介

TAG:程序員小新人學習 |