Spring Boot(20)---開發Web應用之JSP篇
Spring Boot(20)---開發Web應用之JSP篇
前言
上一篇介紹了Spring Boot中使用Thymeleaf模板引擎,今天來介紹一下如何使用SpringBoot官方不推薦的jsp,雖然難度有點大,但是玩起來還是蠻有意思的。
正文
先來看看整體的框架結構,跟前面介紹Thymeleaf的時候差不多,只是多了webapp這個用來存放jsp的目錄,靜態資源還是放在resources的static下面。
引入依賴
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!--WEB支援--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--jsp頁面使用jstl標籤--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!--用於編譯jsp--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> |
使用內嵌的tomcat容器來執行的話只要這3個就好了。這裡介紹下maven中scope依賴範圍的概念,因為後續涉及到這個會有問題。
依賴範圍就是用來控制依賴和三種classpath(編譯classpath,測試classpath、執行classpath)的關係,Maven有如下幾種依賴範圍:
- compile:編譯依賴範圍。如果沒有指定,就會預設使用該依賴範圍。使用此依賴範圍的Maven依賴,對於編譯、測試、執行三種classpath都有效。典型的例子是spring-code,在編譯、測試和執行的時候都需要使用該依賴。
- test: 測試依賴範圍。使用次依賴範圍的Maven依賴,只對於測試classpath有效,在編譯主程式碼或者執行專案的使用時將無法使用此依賴。典型的例子是Jnuit,它只有在編譯測試程式碼及執行測試的時候才需要。
- provided:已提供依賴範圍。使用此依賴範圍的Maven依賴,對於編譯和測試classpath有效,但在執行時候無效。典型的例子是servlet-api,編譯和測試專案的時候需要該依賴,但在執行專案的時候,由於容器以及提供,就不需要Maven重複地引入一遍。
application.properties配置
要支援jsp,需要在application.properties中配置返回檔案的路徑以及型別
1 2 |
spring.mvc.view.prefix: /WEB-INF/jsp/ spring.mvc.view.suffix: .jsp |
這裡指定了返回檔案型別為jsp,路徑是在/WEB-INF/jsp/下面。
控制類
上面步驟有了,這裡就開始寫控制類,直接上簡單的程式碼,跟正常的springMVC沒啥區別:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@Controller @RequestMapping("/learn") public class LearnResourceController { @RequestMapping("") public ModelAndView index(){ List<LearnResouce> learnList =new ArrayList<LearnResouce>(); LearnResouce bean =new LearnResouce("官方參考文件","Spring Boot Reference Guide","http://docs.spring.io/spring-boot/docs/1.5.1.RELEASE/reference/htmlsingle/#getting-started-first-application"); learnList.add(bean); bean =new LearnResouce("官方SpriongBoot例子","官方SpriongBoot例子","https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples"); learnList.add(bean); bean =new LearnResouce("龍國學院","Spring Boot 教程系列學習","http://www.roncoo.com/article/detail/125488"); learnList.add(bean); bean =new LearnResouce("嘟嘟MD獨立部落格","Spring Boot乾貨系列 ","http://tengj.top/"); learnList.add(bean); bean =new LearnResouce("後端程式設計嘟","Spring Boot教程和視訊 ","http://www.toutiao.com/m1559096720023553/"); learnList.add(bean); bean =new LearnResouce("程式猿DD","Spring Boot系列","http://www.roncoo.com/article/detail/125488"); learnList.add(bean); bean =new LearnResouce("純潔的微笑","Sping Boot系列文章","http://www.ityouknow.com/spring-boot"); learnList.add(bean); bean =new LearnResouce("CSDN——小當部落格專欄","Sping Boot學習","http://blog.csdn.net/column/details/spring-boot.html"); learnList.add(bean); bean =new LearnResouce("樑桂釗的部落格","Spring Boot 揭祕與實戰","http://blog.csdn.net/column/details/spring-boot.html"); learnList.add(bean); bean =new LearnResouce("林祥纖部落格系列","從零開始學Spring Boot ","http://412887952-qq-com.iteye.com/category/356333"); learnList.add(bean); ModelAndView modelAndView = new ModelAndView("/index"); modelAndView.addObject("learnList", learnList); return modelAndView; } } |
jsp頁面編寫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<body style="background-image: none;"> <div class="body_wrap"> <div class="container"> <div class="alert alert-success text-center" role="alert">Sptring Boot學習資源大奉送,愛我就關注嘟嘟公眾號:嘟爺java超神學堂</div> <table class="table table-striped table-bordered"> <tr> <td>作者</td> <td>教程名稱</td> <td>地址</td> </tr> <c:forEach var="learn" items="${learnList}"> <tr class="text-info"> <td th:text="${learn.author}">嘟嘟MD</td> <td th:text="${learn.title}">SPringBoot乾貨系列</td> <td><a href="#" th:href="${learn.url}" class="btn btn-search btn-green" target="_blank"><span>點我</span></a> </td> </tr> </c:forEach> </table> </div> </div> </body> |
啟動類
啟動類不變還是最簡單的
1 2 3 4 5 6 |
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } |
內嵌Tomcat容器執行專案
基本配置好了就可以啟動專案,通過http://localhost:8080/learn 訪問,我使用的SpringBoot是1.5.2版本,jdk1.8,以前介紹過,執行專案有三種方式,這裡我都做過了一次測試,發現在maven中jasper依賴有加provided和註釋掉該依賴範圍執行的效果不大一樣,具體對比如下:
有新增provided的情況:
- 右鍵執行啟動類,訪問頁面報404錯誤
- 使用spring-boot:run執行正常
- 打包成jar,通過 java -jar demo-0.0.1-SNAPSHOT.jar 執行報錯
- 打包成war,通過 java -jar demo-0.0.1-SNAPSHOT.war 執行正常
把provided 註釋掉的情況
- 右鍵執行啟動類,訪問頁面正常
- spring-boot:run執行 訪問頁面正常
- 打包成jar,通過 java -jar demo-0.0.1-SNAPSHOT.jar 執行報錯
- 打包成war,通過 java -jar demo-0.0.1-SNAPSHOT.war 執行正常
我測試了好幾次都是這樣,就是有加provided的時候,右鍵執行啟動類訪問頁面的時候,提示404錯誤。
其他3種情況都一樣, jar執行也報404,spring-boot:run以及war執行都可以。
為什麼jar包執行不行呢,我們開啟打包的jar和war分別看看區別,如下2圖所示:
從上面可以看出來,jar包執行的時候會404錯誤,因為預設jsp不會被拷貝進來,而war包裡面有包含了jsp,所以沒問題。
內嵌Tomcat屬性配置
關於Tomcat的偶有屬性都在org.springframework.boot.autoconfigure.web.ServerProperties配置類中做了定義,我們只需在application.properties配置屬性做配置即可。通用的Servlet容器配置都已”server”左右字首,而Tomcat特有配置都以”server.tomcat”作為字首。下面舉一些常用的例子。
配置Servlet容器:
1 2 3 4 5 6 |
#配置程式埠,預設為8080 server.port= 8080 #使用者繪畫session過期時間,以秒為單位 server.session.timeout= # 配置預設訪問路徑,預設為/ server.context-path= |
配置Tomcat:
1 2 3 4 |
# 配置Tomcat編碼,預設為UTF-8 server.tomcat.uri-encoding=UTF-8 # 配置最大執行緒數 server.tomcat.max-threads=1000 |
更為詳細的Servlet容器配置以及Tomcat配置,可以前往博主之前文章檢視:Spring Boot乾貨系列:常用屬性彙總
外部的Tomcat伺服器部署war包
Spring Boot專案需要部署在外部容器中的時候,Spring Boot匯出的war包如果直接在Tomcat的部署會報錯,不信你可以試試看。
需要做到下面兩點修改才可以:
- 繼承SpringBootServletInitializer
外部容器部署的話,就不能依賴於Application的main函數了,而是要以類似於web.xml檔案配置的方式來啟動Spring應用上下文,此時我們需要在啟動類中繼承SpringBootServletInitializer並實現configure方法:1 2 3 4 5 6
public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } }
這個類的作用與在web.xml中配置負責初始化Spring應用上下文的監聽器作用類似,只不過在這裡不需要編寫額外的XML檔案了。
- pom.xml修改tomcat相關的配置
如果要將最終的打包形式改為war的話,還需要對pom.xml檔案進行修改,因為spring-boot-starter-web中包含內嵌的tomcat容器,所以直接部署在外部容器會衝突報錯。這裡有兩種方法可以解決,如下
方法一:1 2 3 4 5 6 7 8 9 10
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency>
在這裡需要移除對嵌入式Tomcat的依賴,這樣打出的war包中,在lib目錄下才不會包含Tomcat相關的jar包,否則將會出現啟動錯誤。
還有一個很關鍵的關鍵點,就是tomcat-embed-jasper中scope必須是provided。
1 2 3 4 5 |
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> |
因為SpringBootServletInitializer需要依賴 javax.servlet,而tomcat-embed-jasper下面的tomcat-embed-core中就有這個javax.servlet,如果沒用provided,最終打好的war裡面會有servlet-api這個jar,這樣就會跟tomcat本身的衝突了。這個關鍵點同樣適應於下面說的第二種方法。
方法二:
直接新增如下配置即可:
1 2 3 4 5 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> |
provided的作用上面已經介紹的很透徹了,這裡就不囉嗦了,這種方式的好處是,打包的war包同時適合java -jar命令啟動以及部署到外部容器中。
如果你不喜歡預設的打包名稱,你可以通過節點裡新增內容。
1 2 3 |
<build> <finalName>springBootJsp</finalName> </bulid> |
最後啟動tomcat輸入http://localhost:8080/springBootJsp/learn 檢視效果,還是美美噠
關於使用jar部署
上面已經測試過了,正常情況下包含jsp的頁面是無法用jar的執行的,因為jsp預設是在webapp目錄下,可是打包成jar是沒有webapp這個目錄結構的。
雖然網上有介紹說通過pom.xml配置,把WEB-INF目錄複製到META-INF/resources下面。但是博主試了一整天還是訪問不了,最後放棄了。各位如何有興趣可以繼續嘗試,畢竟war也可以通過java -jar命令來啟動的不是麼。
總結
我相信全網都找不到一篇有我這篇這麼詳細的介紹Spring Boot使用jsp的文章。有很多人問我,為什麼我的很多文章這麼簡單易懂,我每次都是哭著回覆他們四個字:主題閱讀,天知道我參考了多少篇網上的文章,外加多少本相關書籍中關於這個章節的內容,反覆對比提煉,最後才產出對應的博文。說真的,我很羨慕你們在這個資訊爆炸的時代,剛好看到一篇自己要學習的技術的好文章,少走多少彎路。
說了這麼多煽情的話,哪位大兄弟帶一波節奏啊,好久沒收到打賞了d=====( ̄▽ ̄*)b
想要檢視更多Spring Boot乾貨教程,可前往:Spring Boot乾貨系列總綱
原始碼下載
( ̄︶ ̄)↗[相關示例完整程式碼]
後續補充
最近有網友按照我文章中所示跟著操作,發現就算去掉tomcat-embed-jasper
依賴中的<scope>provided</scope>
,啟動類右鍵啟動的時候訪問頁面還是404,研究下了,如果你也是用IDEA開發,那麼請檢查如下圖所示是否選擇了User classpath of module
選項:
一直覺得自己寫的不是技術,而是情懷,一篇篇文章是自己這一路走來的痕跡。靠專業技能的成功是最具可複製性的,希望我的這條路能讓你少走彎路,希望我能幫你抹去知識的蒙塵,希望我能幫你理清知識的脈絡,希望未來技術之巔上有你也有我,希望大爺你看完打賞點零花錢給我。