JSP & Servlet
Java Server Pages
JSP File
- An HTML page with some Java
- Include dynamic content from Java code
存取 .jsp & .html
- webapp
- a.html :
http://ip:port/專案路徑/a.html - b.jsp :
http://ip:port/專案路徑/b.jsp
- a.html :
JSP 本質
graph BT
HJB[Class HttpJspBase]
HS((Interface HttpServlet))
HJP((Interface HttpJspPage))
HJB --> HS
HJB -.-> HJP
- JSP是一個 Servlet 程式
- 第一次存取 .jsp頁面時,Tomcat Server會幫我們製成一個 .java,並且編譯成 .class
public final class helloworld_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports
// HttpJspBase extends HttpServlet implements HttpJspPageJSP - Syntax
page Directives 指令
<%@ directive attribute="value" %>
- language 屬性︰表示在 jsp 裡面用的是什麼語言
- contentType 屬性︰jsp 傳回的數據類型是什麼
- pageEncoding 屬性︰jsp 頁面文件本身的 Character set
- import 屬性
- autoflush 屬性︰設置 out 輸出流緩衝區滿了之後,是否自動刷新。預設 true
- buffer 屬性︰設置 out 緩衝區的大小。預設 8kb
- errorPage 屬性︰設置 jsp 報錯時,自動跳轉至 custom 404 page
- isErrorPage 屬性:設置 jsp 是否是錯誤訊息頁面,預設 false
- session 屬性︰設置當前 jsp 頁面,是否創建 HttpSession 物件,預設 true
- extends 屬性
JSP Script attributes
<%! Declare Java Code %>
<%!
private Integer id;
private String name;
private static Map
%>宣告 static
<%!
static {
map = new HashMap<String, Object>();
map.put("key1", "value1");
}
%>宣告方法
<%!
public int abc(){
return 100;
}
%>class
<%!
public static class L {
private Integer id = 10;
private String LLL = "3";
}
%>JSP Script expression
- 所有 expression script 都會被翻譯到 jspService() 中
- 由 out.print() 輸出至頁面上
- 可使用 jspService() 內的所有方法
- 結尾不可加入 ;
<%=12 %> <br>
<%=12.12 %> <br>
<%="字符串" %> <br>
<%=map %> <br>
<%=request.getParameter("username")%>JSP Code Script
<%
for(int i = 0; i < 5; i++){
%>
<tr>
<td>第 <%=i%> 行</td>
</tr>
<%
}
%>
</table>JSP Three comment
- html comment -
<!-- html -->會 out.write 輸出到 Client 端 - java comment -
// 單行 comment、/* 多行 comment */會被翻譯到 .java - jsp comment -
<%-- jsp --%>
JSP Implicit Objects
- request
- response
- pageContext
- session
- application - ServletContext 物件
- config - ServletConfig 物件
- out
- page
- exception
JSP Scope Object
- pageContext ( PageContextImpl ):當前 jsp 頁面範圍內有效
- request ( HttpServletRequest ):一次請求內有效
- session ( HttpSession ):打開 Browser Request Server,直到關閉 Browser
- application ( ServletContext ):整個 Web Project 範圍內都有效
使用優先順序
pageContext → request → session → application
out.write & response.getWriter.write 的差異
- jsp 頁面底層 Source Code 是用 out.write 輸出
- out.write() 輸出字串 ok
- out.print() 輸出任意數據都沒問題(轉換成字串後,呼叫 write 輸出)
- 結論:jsp頁面可以統一使用 out.print() 進行輸出
常用標籤
Static include
<%@include file="/include/footer.jsp" %>- 不會翻譯被包含 jsp頁面
- 把被包含的 jsp 頁面的 code 複製到包含的位置執行輸出
Dynamic include
// main.jsp
<jsp:include page="/include/footer.jsp">
<jsp:param value="root" name="username"/>
<jsp:param value="pass" name="password"/>
</jsp:include>
// footer.jsp
<%=request.getParameter("username")%>
<%=request.getParameter("password")%>- 動態包含會把 include 的 jsp 頁面也翻譯成.java
- 動態包含還可以傳遞參數
轉發
<jsp:forward page="/scope2.jsp"></jsp:forward>EL ( Expression Language ) & JSTL
- EL 代替 Script 在 jsp page 中進行數據的輸出
- EL 輸出 null 時,顯示的是空字串。JSP Expression Script 輸出 null 時,顯示為 null 字串
EL 搜尋四個 Scope 的順序
由小到大輸出顯示:pageContext > request > session > application
EL 運算
${ 12 == 12 } 或 ${ 12 eq 12 }
${ 12 != 12 } 或 ${ 12 ne 12 }
${ 12 < 12 } 或 ${ 12 lt 12 }
${ 12 > 12 } 或 ${ 12 gt 12 }
${ 12 <= 12 } 或 ${ 12 le 12 }
${ 12 >= 12 } 或 ${ 12 ge 12 }
${ 12 == 12 && 12 > 11 } 或 ${ 12 == 12 and 12 > 11 }
${ 12 == 12 || 12 > 11 } 或 ${ 12 == 12 or 12 > 11 }
${ ! true } 或 ${ not true }EL 11 implicit object
| Variable | Type | 作用 |
|---|---|---|
| pageContext | PageContextImpl | 可以取得 JSP 中的 9 個 implicit Object |
| pageScope | Map<String, Object> | 取得 pageContext 範圍中的數據 |
| requestScope | Map<String, Object> | 取得 Request 範圍中的數據 |
| sessionScope | Map<String, Object> | 取得 Session 範圍中的數據 |
| applicationScope | Map<String, Object> | 取得 ServletContext 範圍中的數據 |
| param | Map<String, String> | 取得 Request Parameter |
| paramValues | Map<String, String[]> | 取得多個值情況下的 Request Parameter |
| header | Map<String, String> | 取得 Request Header 的訊息 |
| headerValues | Map<String, String[]> | 取得多個值情況下的 Request Header 的訊息 |
| cookie | Map<String, Cookie> | 取得當前 request 的 Cookie 訊息 |
| initParam | Map<String, String> | 取得 web.xml 中配置的 <context-param> 上下文 |
JSTL 標籤 Lib
| 功能範圍 | Prefix |
|---|---|
| 核心標籤Lib | c |
| 格式化 | fmt |
| 函式 | fn |
| (不使用) | sql |
| (不使用) | x |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>Servlet
階層圖
Circle 圓形:Interface 介面 Parallelogram 平行四邊形:Abstract Class 抽象類別 Rectangle 長方形:Concrete Class 一般類別 Dotted Line 虛線:implements 實作 Solid Line 實線:extends 繼承
graph BT
O{Object}
SVL((Servlet))
HS[/HttpServlet/]
GS[/GenericsServlet/]
SC((ServletContext))
SCf((ServletConfig))
SReq((ServletRequest))
SRes((ServletResponse))
HSReq((HttpServletRequest))
HSRes((HttpServletResponse))
Custom[自定義Servlet程式]
GS -.-> SVL
GS -.-> SCf
HS --> GS --> O
Custom --> HS
HSReq --> SReq
HSRes --> SRes
- Interface Servlet:只負責定義 Servlet 程式存取規範
- abstract class GenericServlet:對 ServletConfig 的使用作一些方法
- abstract class HttpServlet:實現 service() 方法,並實現請求的分發處理
- 自定義Servlet程式:只需要根據自身業務需求去 override doGet()、doPost() 即可
Lifecycle
- Client/Browser︰The client through the browser sends HTTP requests to the web server
- Web Server︰Includes several components used to control access to files hosted on the server
- Web Container︰This is a component of the web server that interacts with Java servlets
生命週期:
- 執行 Servlet 建構子方法
- 執行 init 初始化
Step 1、2 於第一次存取的時候,創建 Servlet 會呼叫
- 執行 service 方法(每次執行都會呼叫)
- 執行 destroy 方法(在程式停止時被呼叫)
Interface ServletConfig
用於 Servlet 程式的配置訊息
三大作用:
- 獲取 Servlet 程式的別名 servlet-name 的值
- 獲取初始化參數 init-param
- 獲取 ServletContext 物件
Interface ServletContext
- Servlet 上下文物件
- 一個 Project,只有一個 ServletContext 物件實例
- ServletContext 物件是一個 Domain Object
| 舉例 | 存Data | 取Data | 刪除Data |
|---|---|---|---|
| Map | put() | get() | remove() |
| Domain Object | setAttribute() | getAttribute() | removeAttribute() |
四個作用:
- 取得 web.xml 中配置的上下文參數 context-param
- 取得當前專案路徑
- 取得專案部署後在 Server 上的絕對路徑
- 像 Map 一樣存取 Data
GET & POST 請求
GET:
<form>tag - method=get<a href="">tag : hyperlink<link>tag 嵌入 css<script>tag 嵌入 js 文件<img>tag 嵌入圖片- iframe 嵌入 html 頁面
- 於瀏覽器網址欄輸入地址後按 Enter
POST:
<form>tag - method=post
常用的 Response Status Code
- 200 - Request 成功
- 302 - Request 重定向 Redirect
- 304 - 已讀取過的圖片或網頁,由瀏覽器緩存 (cache) 中讀取
- 404 - Request Server 已經收到,但要的 Data 不存在 (Request 地址錯誤)
- 500 - Server 已經收到 Request,但是 Server 內部錯誤
MIME ( Multipurpose Internet Mail Extensions )
HTTP 協議中的 Content Type
| 文件 | MIME類型 |
|---|---|
| 超文本標記語言 | .html _ text/html |
| 普通文字 | .txt _ text/plain |
| RTF | .rtf _ application/rtf |
| GIF | .gif _ image/gif |
| JPG | .jpeg .jpg _ image/jpeg |
Interface HttpServletRequest
只要有 Request 進入 Tomcat Server, Tomcat Server 就會把 Request 過來的 HTTP 協議資訊解析好並封裝至 Request 物件中,再傳遞到 service() 方法中給我們使用。
常用方法:
| 方法 | 說明 |
|---|---|
| getRequestURI() | 取得 Request 的路徑 |
| getRequestURL() | 取得絕對路徑 |
| getRemoteHost() | 取得 Client端的 ip位址 |
| getHeader() | 取得 Request Header |
| getParameter() | 取得 Request 的參數 |
| getParameterValues() | 取得 Request 的參數(複數個值的時候使用) |
| getMethod() | 取得 Request 的方法 (GET/POST) |
| setAttribute(key, value) | 設置 Domain Data |
| getAttribute(key) | 取得 Domain Data |
| getRequestDispatcher() | 取得 Request 轉發物件 |
請求的轉發
sequenceDiagram
Client(Browser)->>+Tomcat(Servlet_1): http://ip:port/專案名稱/servlet_1
Tomcat(Servlet_1)->>Tomcat(Servlet_2): Servlet_1 到 Servlet_2 的操作叫作 請求轉發
Tomcat(Servlet_2)->>+Client(Browser):Servlet_1 & Servlet_2 可以共同完成一個完整的業務功能
請求轉發的特點:
- 瀏覽器網址欄位沒有變化
- 是「一次」請求
- 共享 Request 中的 Data
- 可以轉發至 WEB-INF 目錄底下
- 不可轉發至 Project 以外的地方
Web 路徑
- 相對路徑:
.:表示當前目錄..:表示上一層目錄檔案名稱:表示當前目錄/檔案
- 絕對路徑:
http://ip:port/專案/檔案
Web / 斜槓
- Browser 解析
/,得到的地址是:http://ip:port/ - Server 解析
/,得到的地址是:http://ip:port/專案路徑 - 例外情況:
response.sendRedirect("/"),把/發送給 Browser 解析
Interface HttpServletResponse
只要有 Request 進入, Tomcat Server 就會創建 Response 物件,傳遞給 Servlet 程式去使用。如果要回應給 Client 端的訊息,可通過 HttpServletResponse 物件來進行設置。
輸出流 OutputStream
二個輸出流,只能擇一使用,同時使用會報錯
- Byte Stream:
getOutputStream()- 常用於下載(傳送二進位元數據) - Character Stream:
getWriter()- 常用於回傳字串(常用)
請求重新導向 Redirect
sequenceDiagram
Client->>Server: Request
Server->>Client: Response 302 + Location: new_url
Client->>Server: Request to new_url
Server->>Client: Final Response
Redirect 特點:
- 瀏覽器網址欄會發生變化
- 兩次 Request
- 不共享 Request 中的數據
- 不能存取 WEB-INF 目錄底下的資料
- 可以存取專案外的資源
Filter
Listener 監聽器
三大 Component 之一:Servlet 程式、Filter 過濾器、Listener
JavaEE 規範,是介面
作用為,監聯某事物的變化,然後回呼 (Callback) 函數,反饋給客戶(或程式)去做一些相應的處理
ServletContextListener
可以監聽 ServletContext 物件的建立和銷毀
JavaEE 三層架構
flowchart LR
W[Client / Browser]
V[V / View]
S[Service 服務]
M[M / Model / DAO 持久化]
DB[(MySQL / Oracle / ...etc.)]
subgraph Database
DB
end
subgraph JaveEE
V
S
M
end
subgraph Browser
W
end
W --> V -->|Controller / Servlet| S --> M --> DB
DB --> M --> S -->|Controller / Servlet| V --> W
- Browser:HTML、CSS、JS、JQuery
- View:Servlet、Spring MVC、Struts
- Service:Spring Framework
- Model / DAO:JDBC、Hibernate
套件分類
- Web / View
- Service
- Service 介面套件
- Service 介面實現
- DAO
- DAO 介面套件
- DAO 介面實現
- Entity bean 物件
- 測試套件
- 工具 Utils