JSP(Java Server Pages,Java 服務器頁面)是一個簡化的 Servlet 設計,它是由 Sun Microsystems 公司倡導、許多公司參與一起建立的一種動態網頁技術標準。JSP 技術類似 ASP 技術,它是在傳統的網頁 HTML(標準通用標記語言的子集)文件(.html)中插入 Java 程序段(Scriptlet)和 JSP 標記(tag),從而形成 JSP 文件,後綴名爲(*.jsp)。用 JSP 開發的 Web 應用是跨平臺的,既能在 Linux 下運行,也能在其他操作系統上運行。
JSP 其實就是 Java 爲了支持 Web 開發而推出的類前端 Servlet,可以在 JSP 中寫 Java 或者 Html 語法等,後端根據 JSP 語法渲染後返回到前端顯示,在沒有模板引擎之前 JSP 是 Java 程序員開發人員的首選,到現在仍然有很多公司使用 JSP 開發後臺管理系統。本課內容將介紹如何在 Spring Boot 項目中使用 JSP。
快速上手
項目結構
首先看一下添加 JSP 支持後的項目結構:
spring-boot-jsp
+-src
+- main
+- java
+- resources
+- webapp
+- WEB-INF
+- jsp
+- welcome.jsp
+- test
+-pom.xml
對比以前的項目結構 main 目錄下多了 webapp 目錄,用來存放目錄 jsp 文件。
配置文件
需要在配置文件中指定 jsp 的位置和後綴。
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
- spring.mvc.view.prefix 指明 jsp 文件在 webapp 下的哪個目錄
- spring.mvc.view.suffix 指明 jsp 以什麼樣的後綴結尾
引入依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
spring-boot-starter-web 包依賴了 spring-boot-starter-tomcat 不需要再單獨配置。引入 jstl 和內嵌的 tomcat,jstl 是一個 JSP 標籤集合,它封裝了 JSP 應用的通用核心功能。tomcat-embed-jasper 主要用來支持 JSP 的解析和運行。
編寫頁面
簡單寫一個頁面:
<!DOCTYPE html>
<html lang="en">
<body>
Time: ${time}
<br>
Message: ${message}
</body>
</html>
很簡單的一個頁面,展示後端傳到頁面的時間和消息。
後端程序
@Controller
public class WelcomeController {
@GetMapping("/")
public String welcome(Map<String, Object> model) {
model.put("time", new Date());
model.put("message", "hello world");
return "welcome";
}
}
time 獲取當前時間,message 賦值爲 hello world。
測試
cmd 進入項目跟路徑下:
cd ...\spring-boot-jsp
執行以下命令啓動:
mvn clean spring-boot:run
啓動完成後,在瀏覽器中訪問地址:http://localhost:8080/,返回信息如下:
Time: Sat Aug 11 13:26:35 CST 2018
Message: hello world
說明項目運行成功。
常用示例
頁面中常用的展示後端傳值、if 判斷、循環等功能,可以使用 jstl 語法處理,也可以直接寫 Java 代碼來實現這些邏輯,在 jsp 頁面中這兩種方式都支持。但不建議在 jsp 頁面中編寫大量的 Java 代碼,從而導致前端業務複雜,可讀性差等問題。下面通過一些小的示例來學習。
在 WelcomeController 類中定義一個 user() 的方法,設置一些值從後端傳遞到前端:
@GetMapping("/user")
public String user(Map<String, Object> model, HttpServletRequest request) {
model.put("username", "neo");
model.put("salary", 666);
request.getSession().setAttribute("count",6);
return "user";
}
將參數和值以鍵值對的方式存儲在 Map 中,jsp 頁面可以直接根據屬性名來獲取值,也可以通過 request 來傳遞後端屬性和值,返回值會以鍵值對的方式傳遞到 user.jsp 頁面。
在 user.jsp 文件頭部添加兩個標籤:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><html lang="en">
引入第一個標籤是爲了讓頁面支持中文展示,第二個標籤引入表示頁面使用 jstl 語法來處理頁面邏輯。
Java 代碼
可以直接在 jsp 頁面中使用 Java 代碼,如果是一行 Java 代碼使用<%= %>
的語法,如果是多行 Java 代碼則使用<% %>
的語法,示例如下:
<h3>一行 Java 代碼</h3>
<p>
今天的日期是: <%=(new java.util.Date())%>
</p>
<h3>多行 Java 代碼</h3>
<p>
你的 IP 地址是:
<%
out.println("Your IP address is " + request.getRemoteAddr()+"</br>");
out.println("一段代碼 ");
%>
</p>
For 循環是頁面最常用的功能之一,一般用在循環展示表格、列表等。
<h3>For 循環實例</h3>
<%
int count = (int)session.getAttribute("count");
for ( int fontSize = 1; fontSize <=count; fontSize++){
%>
純潔的微笑
<br />
<%}%>
根據後端傳遞的 count 值來選擇前端頁面循環次數。
jstl 語法
頁面常常會使用一些邏輯判斷,使用 jstl 語法很容易實現這些功能。
<h3>標籤 c:if</h3>
<c:if test="${username !=null}">
<p>用戶名爲:username<p>
</c:if>
使用 jstl 標籤的<c:if>
來判斷傳遞過來的 username 是否爲空,如果不爲空將 username 展示到頁面。當有多條件判斷時可以使用 <c:choose>
更方便。
<h3>標籤 c:choose</h3>
<c:choose>
<c:when test="${salary <= 0}">
太慘了。
</c:when>
<c:when test="${salary > 1000}">
不錯的薪水,還能生活。
</c:when>
<c:otherwise>
什麼都沒有。
</c:otherwise>
</c:choose>
上述代碼根據 salary 值的大小來輸出不同的內容。
jstl 語法可以支持常見的功能,這裏只是列舉最常用的兩個作爲示例。
頁面佈局
一般網站的每個頁面都擁有相同的頁眉和頁腳,這兩部分內容一般很少發生變動,這部分內容特別適合將它提取出來,讓每個頁面來重複利用。
JSP 可以通過 include 指令來實現此效果,include 指令用於在編譯階段包括一個文件,這個指令告訴容器在編譯階段,把其他外部文件的內容合併到當前 JSP 文件中,可在 JSP 頁面的任何位置使用 include 指令進行編碼。
include 有兩種用法:<%@ include file="relative url"%>
和<jsp:include page="relative url" flush=”true”/>
。前者是在翻譯階段執行,後者是在請求處理階段執行;前者叫作靜態包含,後者叫作動態包含,會在執行時檢查包含內容變化。兩者使用語法沒有太大區別,下面舉一個簡單示例。
新建一個 footer.jsp 內容如下:
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<body>
我是頁尾
</body>
</html>
在 user.jsp 頁面中引入 footer.jsp:
<h3>佈局</h3>
<%@include file="footer.jsp"%>
這樣在訪問 user.jsp 時,會將 footer.jsp 內容展示到 user.jsp 頁面引入的位置。
上述代碼都完成後,整體看一下頁面的效果,啓動項目在瀏覽器中輸入網址:http://localhost:8080/user,頁面展示效果如下:
調試和部署
在 IDEA 中運行
如果像其他項目一樣,直接在 IDEA 中通過 main 方法來啓動項目,在訪問測試的時候會出現 404 not found。
這是因爲 Spring Boot JSP 項目需要額外進行一個設置:選擇 Edit Configurations 選項,打開 Run/Debug Configurations:
設置 Working directory 的路徑爲項目根路徑:
然後重啓項目就可以正常的訪問到頁面內了。
在單獨的 Tomcat 中運行
(1)在 pom.xml 裏設置打包格式爲 war。
<packaging>war</packaging>
(2)排除內嵌的 Tomcat 依賴
打包時排除掉內嵌的 Tomcat 依賴,避免 jar 包衝突。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除內置容器,排除內置容器導出成 war 包可以讓外部容器運行spring-boot項目-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
(3)Servlet 的支持
Spring Boot 項目必須實現 SpringBootServletInitializer 接口的 configure() 方法才能讓外部容器運行 Spring Boot 項目,啓動類同目錄下創建 ServletInitializer 類:
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JspApplication.class);
}
}
(4)打包發佈,在項目根目錄執行 maven 命令:
mvn clean package
(5)將 war 包發佈到 Tomcat 即可。
總結
通過本課的學習我們掌握瞭如何在 Spring Boot 項目中集成 JSP,Spring Boot 支持使用內嵌的 Tomcat 來運行 JSP,也支持將項目打包成 War 包部署到獨立的 Tomcat 中。實際項目中推薦使用單獨的 Tomcat 來部署使用 JSP 的項目,內嵌的 Tomcat 還不是很穩定,偶爾會出現訪問遲緩的現象