Servlet 與 JSP 是一體的兩面,JSP 會轉換為 Servlet,Servlet 作的到的也可以用 JSP 作的到,通常 JSP 會來作爲畫面顯示之用,在這邊,將用一個顯示畫面的 Servlet,將之轉換為 JSP,從中了解各元素的對照。
假設原本有個 Servlet 負責畫面顯示如下:
package cc.openhome.view;
import cc.openhome.model.Bookmark;
import cc.openhome.model.BookmarkService;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ListBookmark extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println(
"<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset=\"UTF-8\">");
out.println("<title>觀看線上書籤</title>");
out.println("</head>");
out.println("<body>");
out.println("<table style=\"text-align: left; width: 100%;\" border=\"0\" >");
out.println(" <tbody>");
out.println(" <tr>");
out.println(" <td style=\"background-color: rgb(51, 255, 255);\">網頁</td>");
out.println(" <td style=\"background-color: rgb(51, 255, 255);\">分類</td>");
out.println(" </tr>");
BookmarkService bookmarkService =
(BookmarkService) getServletContext().getAttribute("bookmarkService");
bookmarkService.getBookmarks()
.forEach(bookmark -> {
out.println(" <tr>");
out.println(" <td><a href=\"http://" +
bookmark.getUrl() + "\">" +
bookmark.getTitle() + "</a></td>");
out.println(" <td>" +
bookmark.getCategory() + "</td>");
out.println(" </tr>");
});
out.println(" </tbody>");
out.println("</table>");
out.println("</body>");
out.println("</html>");
}
}
你可以建立一個檔案,副檔名為 .jsp,首先把 doGet()
中所有的程式碼貼上去,接著看到第一行:
response.setContentType("text/html;charset=UTF-8");
這可以使用 JSP 的指示(Directive)元素在 JSP 頁面的第一行寫下:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
這告訴容器在將 JSP 轉換為 Servlet 時,使用 UTF-8 將 JSP 轉譯為 .java,然後編譯時也用 UTF-8,並設定內容型態為 text/html
。接著這行可以直接刪除:
PrintWriter out = response.getWriter();
這是因為 JSP 中有隱含物件(Implicit object),out
這個名稱就是一個隱含物件名稱。接著 out.println()
的部份可以寫成:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>觀看線上書籤</title>
</head>
<body>
<table style="text-align: left; width: 100%;" border="0">
<tbody>
<tr>
<td style="background-color: rgb(51, 255, 255);">網頁</td>
<td style="background-color: rgb(51, 255, 255);">分類</td>
</tr>
這是你為什麼要用 JSP 處理畫面的原因,因為你不必用 ""
包括字串來作那些 HTML 的輸出了。接下來這個部份:
BookmarkService bookmarkService =
(BookmarkService) getServletContext().getAttribute("bookmarkService");
bookmarkService.getBookmarks()
.forEach(bookmark -> {
可以直接用 Scriptlet 元素,也就是用 <%
與 %>
包括起來,在 JSP 中要撰寫 Java 程式碼,就是這麼作的:
<%
BookmarkService bookmarkService =
(BookmarkService) application.getAttribute("bookmarkService");
bookmarkService.getBookmarks()
.forEach(bookmark -> {
%>
在上面可以看到,ServletContext
的取得,在 JSP 中是透過 application
隱含物件,而 BookmarkService
與 Bookmark
,其完整名稱其實必須包括 cc.openhome.model
套件名稱,在 JSP 中,若要作到與 Servlet 中 import
同樣的目的,可以使用指示元素,告訴容器轉譯時,必須包括的 import
語句,也就是在 JSP 的開頭寫下:
<%@page import="cc.openhome.model.*, java.util.*" %>
再來的這邊:
out.println(" <tr>");
out.println(" <td><a href=\"http://" +
bookmark.getUrl() + "\">" +
bookmark.getTitle() + "</a></td>");
out.println(" <td>" +
bookmark.getCategory() + "</td>");
out.println(" </tr>");
這當中夾雜了 HTML 與 Java 物件取值的動作,這可以轉換為以下:
<tr>
<td><a href="http://<%= bookmark.getUrl()%>">
<%= bookmark.getTitle()%></a></td>
<td><%= bookmark.getCategory()%></td>
</tr>
HTML 的部份直接撰寫即可,至於 Java 物件取值的動作,可以透過運算(Expression)元素,也就是 <%=
與 %>
來包括。接著注意到,之前用 <%
與 %>
包括的部份,forEach
方法的區塊語法並沒有完成,因為還少了個 },所以必須再補上:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>觀看線上書籤</title>
</head>
<body>
<table style="text-align: left; width: 100%;" border="0">
<tbody>
<tr>
<td style="background-color: rgb(51, 255, 255);">網頁</td>
<td style="background-color: rgb(51, 255, 255);">分類</td>
</tr>
<%
});
%>
最後:
out.println(" </tbody>");
out.println("</table>");
out.println("</body>");
out.println("</html>");
可以在JSP中直接寫下:
</tbody>
</table>
</body>
</html>
所完成的JSP頁面完整結果如下:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="cc.openhome.model.*, java.util.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>觀看線上書籤</title>
</head>
<body>
<table style="text-align: left; width: 100%;" border="0">
<tbody>
<tr>
<td style="background-color: rgb(51, 255, 255);">網頁</td>
<td style="background-color: rgb(51, 255, 255);">分類</td>
</tr>
<%
BookmarkService bookmarkService =
(BookmarkService) application.getAttribute("bookmarkService");
bookmarkService.getBookmarks()
.forEach(bookmark -> {
%>
<tr>
<td><a href="http://<%= bookmark.getUrl()%>">
<%= bookmark.getTitle()%></a></td>
<td><%= bookmark.getCategory()%></td>
</tr>
<%
});
%>
</tbody>
</table>
</body>
</html>
雖然 HTML 與 Java 程式碼夾雜的情況仍在,但至少 HTML 撰寫的部份輕鬆多了,如果你想要進一步消除 Java 程式碼,則可以嘗試使用 JSTL 之類的自訂標籤,這在之後還會說明。
最主要的是了解,每個 JSP 中的元素,都可以對照至 Servlet 中某個元素或程式碼,所以要了解 JSP,必先了解 Servlet,你也可以嘗試看看這個 JSP 轉譯後的 Servlet 程式碼,就更能了解兩者之間的關係。