JSP & Servlet

Java Server Pages

JSP File

  1. An HTML page with some Java
  2. Include dynamic content from Java code

存取 .jsp & .html

  • webapp
    • a.html : http://ip:port/專案路徑/a.html
    • b.jsp : http://ip:port/專案路徑/b.jsp

JSP 本質

  graph BT
    HJB[Class HttpJspBase]
    HS((Interface HttpServlet))
    HJP((Interface HttpJspPage))

    HJB --> HS
    HJB -.-> HJP
  1. JSP是一個 Servlet 程式
  2. 第一次存取 .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 HttpJspPage

JSP - Syntax

page Directives 指令

<%@ directive attribute="value" %>

  1. language 屬性︰表示在 jsp 裡面用的是什麼語言
  2. contentType 屬性︰jsp 傳回的數據類型是什麼
  3. pageEncoding 屬性︰jsp 頁面文件本身的 Character set
  4. import 屬性
  5. autoflush 屬性︰設置 out 輸出流緩衝區滿了之後,是否自動刷新。預設 true
  6. buffer 屬性︰設置 out 緩衝區的大小。預設 8kb
  7. errorPage 屬性︰設置 jsp 報錯時,自動跳轉至 custom 404 page
  8. isErrorPage 屬性:設置 jsp 是否是錯誤訊息頁面,預設 false
  9. session 屬性︰設置當前 jsp 頁面,是否創建 HttpSession 物件,預設 true
  10. 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

  1. 所有 expression script 都會被翻譯到 jspService() 中
  2. 由 out.print() 輸出至頁面上
  3. 可使用 jspService() 內的所有方法
  4. 結尾不可加入 ;
<%=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

  1. html comment - <!-- html --> 會 out.write 輸出到 Client 端
  2. java comment - // 單行 comment/* 多行 comment */ 會被翻譯到 .java
  3. jsp comment - <%-- jsp --%>

JSP Implicit Objects

  1. request
  2. response
  3. pageContext
  4. session
  5. application - ServletContext 物件
  6. config - ServletConfig 物件
  7. out
  8. page
  9. exception

JSP Scope Object

  1. pageContext ( PageContextImpl ):當前 jsp 頁面範圍內有效
  2. request ( HttpServletRequest ):一次請求內有效
  3. session ( HttpSession ):打開 Browser Request Server,直到關閉 Browser
  4. application ( ServletContext ):整個 Web Project 範圍內都有效

使用優先順序

pageContext → request → session → application

out.write & response.getWriter.write 的差異

  1. jsp 頁面底層 Source Code 是用 out.write 輸出
  2. out.write() 輸出字串 ok
  3. out.print() 輸出任意數據都沒問題(轉換成字串後,呼叫 write 輸出)
  4. 結論:jsp頁面可以統一使用 out.print() 進行輸出

常用標籤

Static include

<%@include file="/include/footer.jsp" %>
  1. 不會翻譯被包含 jsp頁面
  2. 把被包含的 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")%>
  1. 動態包含會把 include 的 jsp 頁面也翻譯成.java
  2. 動態包含還可以傳遞參數

轉發

<jsp:forward page="/scope2.jsp"></jsp:forward>

EL ( Expression Language ) & JSTL

  1. EL 代替 Script 在 jsp page 中進行數據的輸出
  2. 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

VariableType作用
pageContextPageContextImpl可以取得 JSP 中的 9 個 implicit Object
pageScopeMap<String, Object>取得 pageContext 範圍中的數據
requestScopeMap<String, Object>取得 Request 範圍中的數據
sessionScopeMap<String, Object>取得 Session 範圍中的數據
applicationScopeMap<String, Object>取得 ServletContext 範圍中的數據
paramMap<String, String>取得 Request Parameter
paramValuesMap<String, String[]>取得多個值情況下的 Request Parameter
headerMap<String, String>取得 Request Header 的訊息
headerValuesMap<String, String[]>取得多個值情況下的 Request Header 的訊息
cookieMap<String, Cookie>取得當前 request 的 Cookie 訊息
initParamMap<String, String>取得 web.xml 中配置的 <context-param> 上下文

JSTL 標籤 Lib

功能範圍Prefix
核心標籤Libc
格式化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
  1. Interface Servlet:只負責定義 Servlet 程式存取規範
  2. abstract class GenericServlet:對 ServletConfig 的使用作一些方法
  3. abstract class HttpServlet:實現 service() 方法,並實現請求的分發處理
  4. 自定義Servlet程式:只需要根據自身業務需求去 override doGet()、doPost() 即可

Lifecycle

  1. Client/Browser︰The client through the browser sends HTTP requests to the web server
  2. Web Server︰Includes several components used to control access to files hosted on the server
  3. Web Container︰This is a component of the web server that interacts with Java servlets

生命週期:

  1. 執行 Servlet 建構子方法
  2. 執行 init 初始化
Step 1、2 於第一次存取的時候,創建 Servlet 會呼叫
  1. 執行 service 方法(每次執行都會呼叫)
  2. 執行 destroy 方法(在程式停止時被呼叫)

Interface ServletConfig

用於 Servlet 程式的配置訊息

三大作用:

  • 獲取 Servlet 程式的別名 servlet-name 的值
  • 獲取初始化參數 init-param
  • 獲取 ServletContext 物件

Interface ServletContext

  1. Servlet 上下文物件
  2. 一個 Project,只有一個 ServletContext 物件實例
  3. ServletContext 物件是一個 Domain Object
舉例存Data取Data刪除Data
Mapput()get()remove()
Domain ObjectsetAttribute()getAttribute()removeAttribute()

四個作用:

  1. 取得 web.xml 中配置的上下文參數 context-param
  2. 取得當前專案路徑
  3. 取得專案部署後在 Server 上的絕對路徑
  4. 像 Map 一樣存取 Data

GET & POST 請求

GET

  1. <form> tag - method=get
  2. <a href=""> tag : hyperlink
  3. <link> tag 嵌入 css
  4. <script> tag 嵌入 js 文件
  5. <img> tag 嵌入圖片
  6. iframe 嵌入 html 頁面
  7. 於瀏覽器網址欄輸入地址後按 Enter

POST

  1. <form> tag - method=post

常用的 Response Status Code

  1. 200 - Request 成功
  2. 302 - Request 重定向 Redirect
  3. 304 - 已讀取過的圖片或網頁,由瀏覽器緩存 (cache) 中讀取
  4. 404 - Request Server 已經收到,但要的 Data 不存在 (Request 地址錯誤)
  5. 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 可以共同完成一個完整的業務功能

請求轉發的特點:

  1. 瀏覽器網址欄位沒有變化
  2. 是「一次」請求
  3. 共享 Request 中的 Data
  4. 可以轉發至 WEB-INF 目錄底下
  5. 不可轉發至 Project 以外的地方

Web 路徑

  • 相對路徑:
    • .:表示當前目錄
    • ..:表示上一層目錄
    • 檔案名稱:表示當前目錄/檔案
  • 絕對路徑:
    • http://ip:port/專案/檔案

Web / 斜槓

  1. Browser 解析 /,得到的地址是:http://ip:port/
  2. Server 解析 /,得到的地址是:http://ip:port/專案路徑
  3. 例外情況: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 特點:

  1. 瀏覽器網址欄會發生變化
  2. 兩次 Request
  3. 不共享 Request 中的數據
  4. 不能存取 WEB-INF 目錄底下的資料
  5. 可以存取專案外的資源

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