SCWCD Study Guide

Author: swanky(swanky.hsiao@gmail.com)
Reviser: yoshi(yoshijava@hotmail.com)
Last Updated: 2004-08-30
Version: 1.36

本文發表於 JavaWorld@TW,如欲轉載或轉錄內容,請註明來源及作者

強力建議使用 Mozilla 系列瀏覽
若有任何錯誤,請 mail 通知我們

Objectives 1.1~1.6 (約 7 題)

1.1

處理不同類型的 HTTP request(GET、POST、 PUT)

HttpServlet class:
void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, java.io.IOException
void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, java.io.IOException
void doPut(HttpServletRequest req, HttpServletResponse res) throws ServletException, java.io.IOException
比較 ServletContextServletConfig
ServletContext 的內容屬於整個 WebApp,而 ServletConfig 的內容只屬於單一 servlet 實體

1.2

Triggers for GET request

註:HTML FORM 預設使用 HTTP GET request

Triggers for POST request

Tiggers for HEAD request

HTTP GET

把資料附加在 URL 後面(query string),可以 bookmark 起來,大小不限,但有些 browser 可輸入的 URL 有長度限制(255 chars),只傳送文字資料(text)

HTTP POST

把資料存在 request 裡面(常用在傳送 ID/password、資料量大的檔案),大小不限,可傳送任何資料(text 與 binary)

1.3

取得 request 的參數(parameter)

ServletRequest interface:
String getParameter(String paramName)
String[] getParameterValues(String param)
Enumeration getParameterNames()

取得 servlet 的初始參數(deployment descriptor 內 <servlet><init-param> ) (2.2)

ServletConfig interface:
String getInitParameter(String paramName)
Enumeration getInitParameterNames()

取得 HTTP request header 的資訊

HttpServletRequest interface:
String getHeader(String headerName)
Enumeration getHeaders(String name)
Enumeration getHeaderNames()

設定 HTTP response header

HttpServletResponse interface:
void setHeader(String headerName, String value)
void addHeader(String headerName, String value)

設定 response 的 Content-Type

ServletResponse interface:
void setContentType(String type)

取得 response 的 text stream 傳送字元資料

ServletResponse interface:
PrintWriter getWriter() 註:java.io.Writer
java.io.PrintWriterjavax.servlet.http.JspWriter (8.6、12.7)

取得 response 的 binary stream 傳送任何資料

ServletResponse interface:
ServletOutputStream getOutputStream()
註:java.io.OutputStream
javax.servlet.ServletOutputStream
註:若在 JSP 中呼叫 response.getOutputStream(),會有 IllegalStateException

將 HTTP request 重新導向別的 URL (5.3 URL-rewriting)

HttpServletResponse interface:
void sendRedirect(String newURL)

1.4

Servlet scopes:Request(ServletRequest)、Session(HttpSession)、Context(ServletContext) (10.2 JSP scopes)

ServletRequestHttpSessionServletContext 取得、設定、清除 attribute (5.1 session attribute)

Object getAttribute(String name)
void setAttribute(String name, Object value)
Enumeration getAttributeNames()
void removeAttribute(String name)

獨立存取資源

ServletContext interface:
java.net.URL getResource(String path)
java.io.InputStream getResourceAsStream(String path)
註:可存放資料的地方
Servlet Context (on server) 同一 WebApp、不同 user、不同 session,網頁間可共享的 memory
Session (on server) 同一 WebApp、同一 user、同一 session,網頁間可共享的 memory
Request 同一 request
Cookies (on client) 同一 WebApp、同一 user、不同 session,網頁間可共享的 file

1.5

Servlet life-cycle (8.5 JSP life-cycle)

Servlet interface:
void init(ServletConfig config) throws ServletException:每個 servlet object 只呼叫一次
void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException
void destroy():只呼叫一次,但若是 servlet container 當掉,可能不會呼叫到
註:同一 servlet class 可有多個 servlet object:Single-Threaded 或在 deployment descriptor 設定不同的初始值

1.6

取得 RequestDispatcher 物件

  1. ServletRequest interface:
    RequestDispatcher getRequestDispatcher(String path):path 可以是相對路徑絕對路徑(以"/"開頭的路徑)
  2. ServletContext interface:
    RequestDispatcher getRequestDispatcher(String path):path 只能是絕對路徑(以 "/"開頭的路徑)
    RequestDispatcher getNamedDispatcher(String name):name只能是 Servlet 的資源名稱

使用 RequestDispatcher 來 include、forward 到另一個 web resource (4.2 forward 到錯誤網頁)

RequestDispatcher interface:
void forward(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException
void include(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException

比較 RequestDispatcher.forwardHttpServletResponse.sendRedirect (1.3、5.3)

RequestDispatcher.forward:transparent to the browser,request 是同一個
HttpServletResponse.sendRedirect:新的 request

Objectives 2.1~2.2 (約 4 題)

2.1

網站目錄結構

WebAppName
├ 所有 html, jsp, 圖片等等檔案
WEB-INF
web.xml(WebApp deployment descriptor)
classes(WebApp 類別檔案)
lib(其他 JAR 檔案)

WAR檔案(WebAppName.war)

2.2

<!ELEMENT web-app (icon?, display-name?, description?, distributable?, context-param*, filter*, filter-mapping*, listener*, servlet*, servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?, error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*, login-config?, security-role*, env-entry*, ejb-ref*, ejb-local-ref*)>

deployment descriptor 內 servlet 的設定

Servlet 實體:<servlet> (設定在 <web-app> )
Servlet 名稱:<servlet-name> (設定在 <servlet><servlet-mapping> )
Servlet 類別:<servlet-class> (設定在 <servlet> )

<!ELEMENT servlet (icon?, servlet-name, display-name?, description?, (servlet-class|jsp-file), init-param*, load-on-startup?, run-as?, security-role-ref*)>

設定個別 servlet object 初始參數(設定在 <servlet> ) (1.3)

<!ELEMENT init-param (param-name, param-value, description?)>
註:可設定同一 <servlet-class>, 用不同的 <servlet-name> 來提供不同的初始值

設定 WebApp (Servlet Context) 初始參數(設定在 <web-app>) (3.1)

<!ELEMENT context-param (param-name, param-value, description?)>

設定 URL 與 servlet 的對應關係(mapping)(設定在 <web-app> )

<!ELEMENT servlet-mapping (servlet-name, url-pattern)>

Objectives 3.1~3.3 (約 5 題)

3.1

取得 Servlet Context 初始參數(deployment descriptor 內的 <context-param> ) (2.2)>

ServletContext interface:
String getInitParameter(String paramName)
Enumeration getInitParameterNames()

Servlet context listener

ServletContextListener interface:
void contextInitialized(ServletContextEvent e)
void contextDestroyed(ServletContextEvent e)

ServletContextEvent class:
ServletContext getServletContext()

Servlet context attribute linstener

ServletContextAttributeListener interface:
void attributeAdded(ServletContextAttributeEvent e)
void attributeRemoved(ServletContextAttributeEvent e)
void attributeReplaced(ServletContextAttributeEvent e)

ServletContextAttributeEvent class(extends ServletContextEvent):
ServletContext getServletContext()
String getName()
Object getValue()
Return the name and value of the attribute that was added, removed, or replaced.

Session attribute listener

HttpSessionAttributeListener interface:
void attributeAdded(HttpSessionBindingEvent e)
void attributeRemoved(HttpSessionBindingEvent e)
void attributeReplaced(HttpSessionBindingEvent e)

HttpSessionEvent class:
HttpSession getSession()

HttpSessionBindingEvent class(extends HttpSessionEvent):
HttpSession getSession()
String getName()
Object getValue()

參考:Linstener 請參考 3.3 的表格
註:javax.servlet.GenericServlet implements the javax.servlet.ServletConfig interface.

3.2

設定 WebApp (Servlet Context) 初始參數(設定在 <web-app> ) (2.2)

<!ELEMENT context-param (param-name, param-value, description?)>

Listener 的設定(設定在 <web-app> )

<!ELEMENT listener (listener-class)>
<listener> 要設定在 <servlet> 之前,<context-param> 之後
註:可寫不同的 listener class 實作不同的 Listener interface,也可只寫一個 listener class 實作所有需要的 Listener interface
參考:Linstener 請參考 3.3 的表格

3.3

分散式環境

各種 Lintener 的比較
javax.servlet.ServletContextListener void contextInitialized(ServletContextEvent sce)
void contextDestroyed(ServletContextEvent sce)
javax.servlet.ServletContextAttrubuteListener void attributeAdded(ServletContextAttributeEvent scae)
void attributeRemoved(ServletContextAttributeEvent scae)
void attributeReplaced(ServletContextAttributeEvent scae)
javax.servlet.http.HttpSessionListener void sessionCreated(HttpSessionEvent se)
void sessionDestroyed(HttpSessionEvent se)
javax.servlet.http.HttpSessionAttributeListener void attributeAdded(HttpSessionBindingEvent se)
void attributeRemoved(HttpSessionBindingEvent se)
void attributeReplaced(HttpSessionBindingEvent se)
javax.sevlet.http.HttpSessionActivationListener void sessionDidActivate(HttpSessionEvent se)
void sessionWillPassivate(HttpSessionEvent se)
javax.servlet.http.HttpSessionBindingListener void valueBound(HttpSessionBindingEvent event)
void valueUnbound(HttpSessionBindingEvent event)

補充

SRV.7.7.2 Distributed Environments
Within an application marked as distributable, all requests that are part of a session must handled by one virtual machine at a time. The container must be able to handle all objects placed into instances of the HttpSession class using the setAttribute or putValue methods appropriately. The following restrictions are imposed to meet these conditions:

Objectives 4.1~4.3 (約 3 題)

4.1

使用 setStatus method 設定 status code

HttpServletResponse interface:
void setStatus(int statusCode) 補充 by fishinwater:
This method is used to set the return status code when there is no error (for example, for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, and the caller wishes to invoke an defined in the web applicaion, the sendError method should be used instead.

使用 sendError method 回傳 HTTP 錯誤

HttpServletResponse interface:
void sendError(int statusCode)
void sendError(int statusCode, String message)

4.2

自訂錯誤網頁:

方法一:

在 deployment descriptor 設定處理錯誤的錯誤網頁(設定在 <web-app> )

<!ELEMENT error-page ((error-code|exception-type), location)>
補充 by ziyu:
雖然 Java 語法的限制,使得你只能丟出 IOExceptoin, ServletException, RuntimeException, 但在 JSP 中,可以任意丟出 Exception,會自動以 ServletException 將之包住。故 <exception-type> 並無限制為此三類。
<error-page> 的判斷有2步,第一步是以instanceof來判斷,第二回是以 ServletException.getRootCause() 取出被自動包起來的 Exception object,因此若 <exception-type> 若是 ServletException, 會使得所有非以上三類的 Exception 全被其截住,而產生意料外的 <error-page> 對映。
方法二:

取得 RequestDispatcher 物件 (1.6)

  1. ServletRequest interface:
    RequestDispatcher getRequestDispatcher(String path) path 可以是相對路徑絕對路徑(以"/"開頭的路徑)
  2. ServletContext interface:
    RequestDispatcher getRequestDispatcher(String path) path 只能是絕對路徑(以 "/"開頭的路徑)
    RequestDispatcher getNamedDispatcher(String name) name 只能是Servlet 的資源名稱

使用 RequestDispatcher 把 request 轉送到錯誤網頁(1.6)

void forward(ServletRequest req, ServletResponse res)

註:
Use RequestDispatcher.forward() to forward a request to an error-handler page. In case of an exception, set javax.servlet.error.exception_type, javax.servlet.error.request_uri, and javax.servlet.error.servlet_name in the request, and in case of an error condition, set javax.servlet.error.error_code, javax.servlet.error.request_uri, and javax.servlet.error.servlet_name in the request before forwarding the request.

Rules for exceptions thrown by an included or forwarded resource using the RequestDispatcher interface:
  1. If the exception thrown by the included or forwarded resource is a RuntimeException, a ServletException, or an IOException, it is thrown as is by the include() or forward() method.
  2. Otherwise, the exception is wrapped in a ServletException as the rootCause, and the ServletException is thrown by the include() or forward() method.

4.3

寫 log 的方法

ServletContext interface 與 GenericServlet class:
void log(String message)
void log(String message, Throwable t)
註:

Objectives 5.1~5.3 (約 4 題)

5.1

取得 session 物件(multiple requests、同一或不同 servlet、同一 WebApp)

HttpServletRequest interface:
HttpSession getSession() : the same with getSession(true)
HttpSession getSession(boolean createFlag)

在 session 物件取得、設定、清除 object attribute

HttpSession interface:
Object getAttribute(String name)
void setAttribute(String name, Object value)
Enumeration getAttributeNames()
void removeAttribute(String name)

參考:attribute 請參考 1.4

處理 session 建立、摧毀的事件 (要在 deployment descriptor 設定,不適用分散式環境)

HttpSessionListener interface:
void sessionCreated(HttpSessionEvent e)
void sessionDestroyed(HttpSessionEvent e)

處理 session 內 attribute 增加、清除的事件 (不用在 deployment descriptor 設定,attribute 需實作此介面,適用分散式環境)

HttpSessionBindingListener interface:
void valueBound(HttpSessionBindingEvent e)
void valueUnbound(HttpSessionBindingEvent e)

參考:Linstener 請參考 3.3 的表格

使 session 無效

HttpSession interface:
void invalidate()

5.2

設定 session 的自動 timeout 時間
1. HttpSession.setMaxInactiveInterval(int seconds):單位,當值 < 0 時表示不會自動 timeout,只對呼叫此 method 的 session 作用
2.在 deployment descriptor 設定 (設定在 <web-app><session-config> 裡)
<!ELEMENT session-config (session-timeout?)>:單位分鐘, 當值 <= 0 時表示不會自動 timeout,對所有 session 作用
HttpSession.setMaxInactiveInterval(int seconds) 比在 deployment descriptor 設定 <session-timeout> 來得優先
• 要使 session 無效,除非 session 自動 timeout 或呼叫 session.invalidate()

5.3

要使用 URL-rewriting
HttpServletResponse interface:
String encodeURL(String originalUrl)
• 無法使用 session 時,在 URL 後加上 session ID;可使用 session 時,則不變更 URL

要使用 URL-rewriting 來重新導向別的網頁HttpServletResponse.sendRedriect(String url) (1.3)
HttpServletResponse interface:
String encodeRedirectURL(String originalUrl)

註:要把靜態 HTML 改成 servlet 或 JSP,裡面的 URL 才能使用 URL-rewriting

補充 by fishinwater:
All URLs sent to the HttpServletResponse.sendRedirect method should be run through this method. Otherwise, URL rewriting cannot be used with browsers which do not support cookies.

Objectives 6.1~6.3 (約 4 題)

6.1

Authentication
Authentication is the mechanism by which parties identify themselves to each other and prove that they have the rights to access a system. Authentication indicates who you are (or who you represent).
詢問 username 與 password 來驗證使用者身份

Authorization
Authorization ensures that data and resources are only made available to parties that are authorized to use them.
控制使用者的存取權

Authentication 與 Authorization的比較
Authentication只是讓你登入用的,存取權是由 Authorization 來控制

Data integrity
Data integrity means that the data has not been modified on its route from the client to the server(or vice versa).
確認傳輸的資料沒有被變更(常使用加密)

Confidentiality
Making sure that unintended parties cannot make use of the data. (常使用加密)

Auditing
Auditing means keeping a log of who does what within an application.
使用 log 來記錄動作

Malicious code
Code aimed at breaking the security rules of a web application.
惡意程式,可使用數位簽章(signed code)來避免

Web site attacks
A web site attack is the name given to any attack against a web site. Examples of this could include Denial of Service attacks or just plain password hacking.
大量 request(denial-of-service) 佔據系統資源,可使用 monitoring access patterns 來避免

6.2

在 deployment descriptor 設定安全限制(設 定在 <web-app> )
<!ELEMENT security-constraint (display-name?, web-resource-collection+, auth-constraint?, user-data-constraint?)>

需要安全限制的 Web resource(設定在 <security-constraint> )
<!ELEMENT web-resource-collection (web-resource-name, description?, url-pattern*, http-method*)>
<http-method> 的值:GETPOST 等,限制只能使用該 HTTP METHOD 來存取被保護的 web resource,沒設表示所有 HTTP METHOD 都被保護

使用者限制(設定在 <security-constraint> )
<!ELEMENT auth-constraint (description?, role-name*)>
<role-name> 的值:* 或是有設定在 <security-role> 裡的 <role-name>

資料傳輸限制(設定在 <security-constraint> )
<!ELEMENT user-data-constraint (description?, transport-guarantee)>
<transport-guarantee> 的值: NONE implies HTTP;CONFIDENTIAL, INTEGRAL imply HTTPS

Authentication mechanism:The login configuration(設定在 <web-app> )
<!ELEMENT login-config (auth-method?, realm-name?, form-login-config?)>
<auth-method> 的值:BASICFORMDIGESTCLIENT-CERT

設定 form based login 的 login and error pages(設定在 <login-config> )
<!ELEMENT form-login-config (form-login-page, form-error-page)>
註:If form based authentication is not used, these elements are ignored.

A security role(設定在 <web-app> )
<!ELEMENT security-role (description?, role-name)>

註:Programmatic security requires role names that are hard-coded in the servlet to be specified in the security-role-ref element(設定在 <servlet> )
<!ELEMENT security-role-ref (description?, role-name, role-link?)>
Manager will be hard-coded in the servlet while supervisor is the actual role name in the deployment environment.
請參考 Manning SCWCD Exam Study Kit
API:HttpServletRequest interface:
String getRemoteUser()
java.security.Principal getUserPrincipal()
boolean isUserInRole(String role)

6.3

BASIC
With BASIC authentication, passwords and usernames are sent to the server in plaintext (this is unencrypted).
Username and password information is gathered by popping up a box on the client.
Performed by sending the username and password in Base64 encoding.

DIGEST
With DIGEST authentication, passwords are encrypted using a simple hashing algorithm.
The username is still sent as plaintext. Username and password information is gathered by popping up a box on the client.
Performed by sending a digest of the password in an encrypted form.

FORM
FORM-based authentication allows the user to enter their username and password using a custom-built form.
This allows the login functionality to be customized for the application.
Performed by sending username and password in Base64 encoding. The username and password are captured using a customized HTML FORM.

CLIENT-CERT
End-user authentication using HTTPS (HTTP over SSL) is a strong authentication mechanism. This mechanism requires the user to possess a Public Key Certificate (PKC). Currently, PKCs are useful in e-commerce applications and also for a single sign-in from within the browser. Servlet containers that are not J2EE-compliant are not required to support the HTTPS protocol.

Authentication type
Advantages
Disadvantages
BASIC

• Very easy to set up
• Supported by all browsers               
• It is not secure, since the username and password are not encrypted.
• You cannot customize the look and feel of the dialog box.
DIGEST

• Secure
• Not supported by all browsers
FORM

• Easy to set up
• Supported by all browsers
• Custiomiezd look and feel
• It is not secure, since the username and password are not encrypted unless HTTPS is used.
CLIENT-CERT
• Very secure
• Supported by all browsers
• Costly to implement
• The Http specification only defines BASIC and DIGEST authentication mechanisms.

Objectives 7.1~7.3 (約 3 題)

7.1

Variable/Attribute scope
Thread Safe in Multi-Threaded Model
Thread Safe in Single-Threaded Model
Local Variables
Yes
Yes
Instance Variables
No
Yes
Class Variables
No
No
Request Attributes
Yes
Yes
Session Attributes
No
No
Context Attributes
No
No
註:
Instance Variables 只在 Single-Threaded Model thread-safe,原因在於 Multi-Threaded Model 讓每個 request 在同一 servlet 實體叫起一個 service() thread 同時跑,而 Single-Threaded Model 是叫起不同的 servlet 實體來跑

Class Variables 一定不是 thread-safe,因為在 Single-Threaded Model,雖然是叫起不同的 servlet 實體,但是更改的還是同一個值,所以會有 concurrency 問題

Request Attribute 一定是 Thread Safe,因為他的 scope 就是在那 method 裡,不可能在中間被別的 method 裡被更動

Session 一定不是 Thread Safe,原因在於使用者可能另開視窗,造成多個視窗同一 session 的問題(同browser)

Context Attributes 一定不是 Thread Safe,因為它就是那個 Web App 的一個共同記憶體,都可能會被更改

7.2

Multi-Threaded Model
• Only one instance of the servlet class is created.
Multiple threads can execute the service() method sumultaneously.
• Requests are serviced in parallel by a single instance.

Single-Threaded Model
Multiple instances of the servlet class may be created.
• Only one thread executes the service() method of one instance.
• Mulitple requests may be serviced concurrently by multiple instances.
• One instance services only one request at a time.

7.3

Implements javax.servlet.SingleThreadModel interface ensures that only one thread executes the service() method at a time.
盡量不要實作 javax.servlet.SingleThreadModel 介面
實作 javax.servlet.SingleThreadModel 只保證 Instance Variables 能夠 thread safe

Objectives 8.1~8.7 (約 8 題)

8.1、8.3


JSP tag
XML-based tag
Directive
<%@ directive {attribute="value"}* %>
Example:
<%@ page attribute list %>
<%@ include file="relativeURL" %>
<%@ taglib prefix="prefix" uri="uri" %>
<jsp:directive.page isErrorPage="true" />
<jsp:directive.include file="relativeURL" />
Declaration
<%! declaration; %>
Example:
<%! int count; %>
<%!
int getCount(){
return count;
}
%>
<jsp:declaration>
 int j = 0;
</jsp:declaration>
Scriptlet
<% seriptlet; %>
<jsp:scriptlet>
 if(x > 10){
</jsp:scriptlet>
Expression
<%= expression %>
Example:
<%= request.getParameter("paramName") %>
<jsp:expression>
 new java.util.Date()
</jsp:expression>
Action
<jsp:action {attribute="value"}* />
<jsp:action {attribute="value"}* ></jsp:action>
• All XML-based pages should have a root tag ramed <jsp:root>. Thus, the page ends with </jsp:root>.
• Unknown attributes or invalid values result in errors and are caught during the translation phase.
• The standard JSP tags and XML-based tags cannot be mixed within a single JSP page.
• A page written in one syntax format can, however, include or forward to a page in the other syntax format by using either directive or action.
<jsp:directive.include file="./header.jsp" /><jsp:include page="page.jsp" /> 是不同的
一個是 include directive 另一個是 include action (9.1)

DirectiveActionXML syntax format
• Tag names, their attributes, and their values are case sensitive.
• The value must be enclosed within a pair of single or double quotes.
• A pair of single quotes is equivalent to a pair of double quotes.
• There must be no space between the equals sign (=) and the value.

補充 by lazymeg:
Request-Time Expression 的兩種不同形式
JSP tag XML-based tag
<jsp:param name="name" value="<%= RTExpr %>" /> <jsp:param name="name" value="%= RTExpr %" />

8.2

Directive
Specifies translation time instructions to the JSP engine.
Provide global info across the page independent of any request.
Three types of directives: page, taglib and include
page directives can be placed anywhere in a page but apply to the entire translation unit.
註:taglib 沒有對應的 XML-based tag, Taglibs are specified in <jsp:root> (參考11.2)

Declaration
在 _jspService()外宣告 class/instance variable (7.1)、 class/instance method

Scriptlet
Used for writing free-form Java code.
• 若有宣告 variable,該變數會是_jspService()的 local variable
• 不能宣告 method

Expression
Used as a shortcut to print values in the generated page.
• Expressions must not end with a semicolon.

Action
Provides request time instructions to the JSP engine.
Action 有:<jsp:fallback><jsp:forward>(9.1)<jsp:getProperty>(10.1)<jsp:include>(9.1)<jsp:param><jsp:params><jsp:plugin><jsp:setProperty>(10.1)<jsp:useBean>(10.1)

補充:
<jsp:fallback> 只能用在 <jsp:plugin> 內,沒有 attribute

<jsp:param name="name" value="value" /> 可用在 <jsp:forward><jsp:include><jsp:params> 內,value 可以是 request-time value

<jsp:params> 只能用在 <jsp:plugin> 內,沒有 attribute

<jsp:plugin type="applet" code="Applet.class" codebase="applet" jreversion="1.2" width="160" heifht="150" >
  <jsp:params>
    <jsp:param name="bgcolor" value="ccddff" />
  </jsp:params>
  <jsp:fallback>
    Plugin tag OBJECT or EMBED not supported by browser.
  </jsp:fallback>
</jsp:plugin>
● mandatory attribute:codecodebasetype
● optional attribute:alignarchiveheighthspaceiepluginurljreversionnamenspluginurltitlevspacewidth

Comment
Used to comment out parts of JSP code.
補充:可見到註解的地方:

<%-- JSP註解 --%>
<% //JAVA註解 %>
<!-- HTML註解 -->
JSP檔案
Yes
Yes
Yes
轉譯後的 JAVA檔
No
Yes
Yes
回傳給 client 的 HTML檔
No
No
Yes

8.4

page directive attributeimportsessionerrorPageisErrorPage

Import a Java class into the JSP page
<%@ page import="java.util.Date" %>
• "java.lang.*,javax.servlet.*,javax.servlet.http.*,javax.servlet.jsp.*" 會被自動 import

Declare that a JSP page exists within a session
<%@ page session="true" %>:預設為 true

Declare that a JSP page uses an error page
<%@ page errorPage="./errorPage.jsp" %>:預設為 null

Declare that a JSP page is an error page
<%@ page isErrorPage="true" %>: 預設為 false

註:page directive 中,只有 import 可以宣告多次

8.5

JSP page life-cycle (1.5 Servlet life-cycle)
1. Page translation
2. Page compilation
3. Load class
4. Create instance
5. Call void jspInit(): call only once
6. Call void _jspService(HttpServletRequest req, HttpServletResponce res) throws ServletException, IOException
called multiple times, once for every request for this page
7. Call void jspDestroy():call only once

jspInit() and jspDestroy() are defined in the javax.servlet.jsp.JspPage interface.
_jspService() is defined in the javax.servlet.jsp.HttpJspPage interface.
• JSP declarations are used to declare(override) jspInit() and jspDestroy().
• We never declare(override) _jspService() explicitly. The JSP engine automatically declares it.

8.6

Implicit objects
Type
Purpose, Function, or Uses
request
javax.servlet.http.HttpServletRequest
Passed in as a parameter to _jspService().
Used for getting HTTP header information, cookies, parameters, etc.
Also used for getting and setting attributes into the request scope.
response
javax.servlet.http.HttpServletResponse
Passed in as a parameter to _jspService().
Used to send a response to the client.
Used for setting HTTP header information, cookies, etc.
out
javax.servlet.jsp.JspWriter
Used for writing data to the output stream.
session
javax.servlet.http.HttpSession
Used for storing and retrieving session related information and sharing objects across multiple requests and pages within the same HTTP session.
config
javax.servlet.ServletConfig
Used to retrieve initialization parameters for a JSP page.
application
javax.servlet.ServletContext
Used for storing and retrieving application related infotmation and sharing objects across multiple sessions, requests, and pages within the same web application.
page
java.lang.Object
Refers to the generated Servlet class.
Not used much because it is declared as type java.lang.Object. (使用前要 cast)
pageContext
javax.servlet.jsp.PageContext
Used for storing and retrieving page-related information and sharing objects within the same translation unit and same request.
Also used as a convenience class that maintains a table of all the other implicit objects.
exception
java.lang.Throwable
Only available in pages that have the page directive isErrorPage set to true.
參考:用 PageContext 取得 implict variable 請參考 12.7

8.7

conditional statement
<% if(someCondition){ %>
  regular HTML/JSP code
<% }else{ %>
  regular HTML/JSP code
<% } %>

iteration statement
<% for(int i = 0; i < 10; i++){ %>
  regular HTML/JSP code
<% } %>

Objectives 9.1 (約 1 題)

9.1

include directive: 靜態 include
<%@ include file="relativeURL" %>
<jsp:directive.include file="
relativeURL" />
relativeURL 不能指向 servlet
● 不可加參數 (query string),只可使用原 request 內的參數

include action: 動態 include
<jsp:include page="relativeURL" flush="true|false" />
relativeURL 要是 page(HTML, JSP 等),不可是 url 或 file,可以指向 servlet,接受 request-time value
flush is optional,預設 false
<jsp:include> actions are translated and evaluated on their own
● 可傳參數,且參數可以是動態產生的,也可使用原 request 內的參數
Example: (8.2)
<jsp:include page="somePage.jsp">
   <jsp:param name="name1" value="<%= someExpr1 %>"/>
   <jsp:param name="name2" value="<%= someExpr2 %>"/>
</jsp:include>
● Three equivalent constructs:
Construct 1
<%
  RequestDispatcher rd = request.getRequestDispatcher("other.jsp");
  rd.include(request, response);
%>
Construct 2
<%
  pageContext.include("other.jsp");
%>
Construct 3
<jsp:include page="other.jsp" flush="true" />

forward action: 動態 forward
<jsp:forward page="relativeURL" />
relativeURL 要是 page(HTML, JSP 等),不可是 url 或 file,可以指向 servlet,接受 request-time value
● 可傳參數,且參數可以是動態產生的,也可使用原 request 內的參數
● Three equivalent constructs:
Construct 1
<%
  RequestDispatcher rd = request.getRequestDispatcher("other.jsp");
  rd.forward(request, response);
%>
Construct 2
<%
  pageContext.forward("other.jsp");
%>
Construct 3
<jsp:forward page="other.jsp" />

註:
include directiveinclude actionforward action:都是使用相對路徑
include directive 不能指向 servlet;include actionforward action可以指向 servlet

API:PageContext class:
abstract void forward(String relativeUrlPath) throws ServletException, java.io.IOException
abstract void include(String relativeUrlPath) throws ServletException, java.io.IOException

Objectives 10.1~10.3 (約 5 題)

10.1

<jsp:useBean id="name" scope="page|request|session|application" typeSpec />
typeSpec::= class="className" |
            class="className" type="typeName" |
            beanName="beanName" type="typeName" |
            type="typeName"
● mandatory attribute:id; optional attribute:scope(預設 page); 至少要提供 classtypebeanName 可以是 request-time value
● The body of the <jsp:useBean> action can be used to initialize its properties.
Example:
<jsp:useBean id="address" scope="session" class="AddressBean">
   <jsp:setProperty name="address" property="street" value="123 Main" />
</jsp:useBean>
● The beanName attribute can also be a JSP expression.
beanName can be used to instantiate a class or a serialized object whereas class is only for a class.
class uses the new keyword to instantiate a class and beanName uses java.beans.Beans.instantiate()
● Using beanName and class together is illegal.

<jsp:setProperty name="beanName" prop-expr />
prop-expr::= property="*" |
             property="propertyName" |
             property="propertyName" param="parameterName" |
             property="propertyName" value="propertyValue" |
● mandatory attribute:nameproperty; Using param and value together is illegalpropertyValue 可以是 request-time value
● The name attribute must refer to a bean that is already declared using a useBean action.
● Examples:
Sets all the properties for which there is a matching parameter in the request
<jsp:setProperty name="aName" property="*" />

Sets aProp using the parameter of the same name in the request
<jsp:setProperty name="aName" property="aProp" />

Sets aProp using the parameter named aParam in the request
<jsp:setProperty name="aName" property="aProp" param="aParam" />

Sets aProp to the value aValue
<jsp:setProperty name="aName" property="aProp" value="aValue" />

Sets aProp to the value returned by the expression
<jsp:setProperty name="aName" property="aProp" value="<%= JSPExpression %>" />

<jsp:getProperty name="name" property="propertyName" />
● mandatory attribute:nameproperty
<jsp:getProperty> prints out the value.

10.2

JSP scopespage(PageContext)、request(HttpServletRequest)、session(HttpSession)、application(ServletContext) (1.4 Servlet scopes)

10.3

可以存取 JavaBean 的方式

JSP scriptlet
JSP expression
JSP standard action (<jsp:uesBean> 等)
custom action 或 custom tag

註:Once the use of a JavaBean is declared using a <jsp:useBean> action, a variable by the given name is automatically declared in the servlet code.Therefore, besides the setProperty and getProperty actions, the bean can alse be accessed through this variable in the scription elements.
Example:
<jsp:useBean id="user" class="UserBean" scope="session" />
<%
//The bean is used in a scriptlet here. You can call methods on the object referred to by the user variable.
user.initialize();
out.println(user.getName());
%>

Objectives 11.1~11.3 (約 3 題)

11.1

在 deployment descriptor 設定 tag library(設 定在 <web-app> )
<!ELEMENT taglib (taglib-uri, taglib-location)>
Example:
<web-app>
  <taglib>
    <taglib-uri>/myTag</taglib-uri>
    <taglib-location>
      /WEB-INF/tld/mytag.tld
    </taglib-location>
  </taglib>
</web-app>
● Each taglib element maps one URI to one location.
● The value of <taglib-uri> can be an absolute URI, a root-relative URI or a non-root-relative URI.
● The value of <taglib-location> can be a root-relative URI or a non-root-relative URI. It cannot be an absolute URI.
● The value of <taglib-uri> must be unique in the deployment descriptor.
● The value of <taglib-location> must point to a valid TLD resource path. It can be either a TLD file or a JAR file containing the TLD file at location META-INF/taglib.tld.

11.2

taglib directive

<%@ taglib uri="/taglibURI" prefix="prefix" %>
註:prefix不可使用 jspjspxjavaservletsunsunw
uri 的值要與 <!ELEMENT taglib (taglib-uri, taglib-location)> 中的 <taglib-uri> 相同

補充 by Michael Deng:
When the JSP engine parses a JSP file and encounters a taglib directive, it checks its taglib map to see if a mapping exists for the uri attribute of the taglib directive:

● In XML syntax, a tag library is introduced in the <jsp:root> element:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
          xmlns:prefix="uri" version="1.2" >

...JSP PAGE...
</jsp:root>

補充 by fishinwater:xmlnsversion 都是mandatory的,xmlns<%@ taglib %> 一樣可以多個

11.3

An empty custom tag

<prefix:tagName/><prefix:tagName></prefix:tagName>

A custom tag with attributes

<prefix:tagName attribute="value"/><prefix:tagName attribute="value"></prefix:tagName>

A custom tag that surrounds other JSP code

<prefix:tagName attribute="value">
  <% //JSP code %>
</prefix:tagName>

Nested custom tags

<prefix:tagName1 attribute="value">
  <prefix:tagName2/>
</prefix:tagName1>
● You cannot nest a custom tag in the attribute list of another custom tag like this:
<test:tag1 name="<test:tag2 />" />
In this case, the JSP engine may assume "<test:tag2 />" as a String value passed to the name attribute. It will not execute tag2.

Objectives 12.1~12.8 (約 8 題)

Tag Library Descriptor element names

12.1

<!ELEMENT taglib (tlib-version, jsp-version, short-name, uri?, display-name?, small-icon?, large-icon?, description?, validator?, listener*, tag+) >

<tag> 設定在 tag library descriptor (TLD,taglib.tld) <taglib>
<!ELEMENT tag (name, tag-class, tei-class?, body-content?, display-name?, small-icon?, large-icon?, description?, variable*, attribute*, example?) >
The name of the tag:<name>
The class of the tag use:<tag-class>
The type of content that the tag accepts<body-content> (值可以是 emptyJSPtagdependent)
Any attributes of the tag:<attribute>

12.2

<attribute> 設定在 tag library descriptor (TLD,taglib.tld) <tag>
<!ELEMENT attribute (name, required? , rtexprvalue?, type?, description?) >
The name of a tag attribute:<name>
Whether a tag attribute is required:<required>, 預設 false
Whether or not the attribute's value can be dynamically specified:<rtexprvalue>, 預設 false
● For each attribute, the container calls the setXXX() method.

12.3

<body-content> 設定在 tag library descriptor (TLD,taglib.tld) <tag>
Empty tag:<body-content>empty</body-content>
Custom tag that surrounds other JSP code:<body-content>JSP</body-content> (預設)
Custom tag that surrounds content that is used only by the tag handler:<body-content>tagdependent</body-content>
● If <body-content> is specified as empty, the actual tag usage cannot have a body.

12.4

int doStartTag() throws JspException
Tag.doStartTag() is called after the JSP engine completely parses the opening tag. Before calling doStartTag(), the JSP engines calls the following methods:
1. setPageContext()
2. setParent()
3. setter methods for attributes

int doAfterBody() throws JspException
IterationTag.doAfterBody() is called after the JSP engine completely evaluates the entire body of the tag.
This happens the first time only if:
1. The tag implements IterationTag and doStartTag() returns EVAL_BODY_INCLUDE.
2. The tag implements BodyTag and doStartTag() returns EVAL_BODY_INCLUDE.
3. The tag implements BodyTag and doStartTag() returns EVAL_BODY_BUFFERED.
doAfterBody() is not called for tags that implement only the Tag interface.

The body of the tag is evaluated again(repeatedly), that is, the doAfterBody() is called repeatedly, only if:
1. The tag implements IterationTag and the previous call to doAfterBody() returns EVAL_BODY_AGAIN.
2. The tag implements BodyTag and the previous call to doAfterBody() returns EVAL_BODY_AGAIN.
3. The tag implements BodyTag and the previous call to doAfterBody() returns EVAL_BODY_BUFFERED.

int doEndTag() throws JspException
Tag.doEndTag() is always called at the end of processing a tag.

12.5

Method Return Value/Type
Tag.doStartTag() SKIP_BODYEVAL_BODY_INCLUDE, (EVAL_BODY_BUFFERED, implements BodyTag)
IterationTag.doAfterBody() SKIP_BODYEVAL_BODY_AGAIN, (EVAL_BODY_BUFFERED, implements BodyTag)
Tag.doEndTag() SKIP_PAGEEVAL_PAGE
PageContext.getOut() javax.servlet.jsp.JspWriter
doEndTag() is always called at the end of processing a tag regardless of the interfaces implemented and regardless if the return values from doStartTag() and doAfterBody().
● At request time, if the doStartTag() returns EVAL_BODY_BUFFEREDPageContext.getOut() returns an object of type BodyContent (which extends JspWriter) when it is called from within the body of the tag.

12.6

SKIP_BODY:This skips body evaluation and is a valid return value for doStartTag() and doAfterBody().
EVAL_BODY_INCLUDE:This evaluates the body of the tag and is a valid return value for doStartTag().
SKIP_PAGE:This skips the rest of the page and is a valid return value for doEndTag().
EVAL_PAGE:This continues evaluating the page and is a valid return value for doEndTag().
EVAL_BODY_AGAIN:This indicates that we require re-evaluation of the tag's body.This can be returned from doAfterBody().
EVAL_BODY_BUFFERED:This requests the creation of new buffer - a BodyContent object - in which we evaluate the body of this tag. This can be returned from doStartTag() when it implements the BodyTag interface. This is an illegal return value for doStartTag() when the class does not implement BodyTag.

Constants Tag.doStartTag() IterationTag.doAfterBody() Tag.doEndTag()
EVAL_BODY_INCLUDE Includes the body of the tag for the first time.


EVAL_BODY_AGAIN
Includes the body of the tag for the second and further times in a loop.

EVAL_BODY_BUFFERED Allow processing of the tag body for the first time. Uses buffering.
Valid only for tags implementing the BodyTag interface.
Allows processing of the tag body repratedly in a loop.
Valid only for tags implementing the BodyTag interface.

SKIP_BODY Does not include or process the body of the tag even for the first time.
Does not include or process the body of the tag the next  time.
EVAL_PAGE

Continue processing the rest of the page.
SKIP_PAGE

Do not process the rest of the page.
Skip everything from the end of this tag to the end of the page.

12.7

PageContext class 取得 implicit variable

Implicit variable Using convenience methods Using constants Return Type
application
getServletContext() getAttribute(PageContext.APPLICATION) javax.servlet.ServletContext
session
getSession() getAttribute(PageContext.SESSION) javax.servlet.http.HttpSession
request
getRequest() getAttribute(PageContext.REQUEST) javax.servlet.ServletRequest
response
getResponse() getAttribute(PageContext.RESPONSE) javax.servlet.ServletResponse
out
getOut() getAttribute(PageContext.OUT) javax.servlet.jsp.JspWriter
config
getServletConfig() getAttribute(PageContext.CONFIG) javax.servlet.ServletConfig
page
getPage() getAttribute(PageContext.PAGE) java.lang.Object
pageContext
  getAttribute(PageContext.PAGECONTEXT) javax.servlet.jsp.PageContext
exception
getException() getAttribute(PageContext.EXCEPTION) java.lang.Exception
註:這些 method 都為 abstract

取得、設定、清除 JSP page's attributes

PageContext class:
Object getAttribute(String name)
Object getAttribute(String name, int scope)
void setAttribute(String name, Object attribute)
void setAttribute(String name, Object attribute, int scope)
void removeAttribute(String name)
void removeAttribute(String name, int scope)
Object findAttribute(String name)
: Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null.
int getAttributesScope(String name)
Enumeration getAttributeNamesInScope(int scope)
參考:attribute 請參考 1.4

12.8

Get the direct parent

Tag interface:
Tag getParent()

Get any parent tag

TagSupport class(implements IterationTag, java.io.Serializable, Tag):
Tag getParent()
static Tag findAncestorWithClass(Tag from, java.lang.Class klass)
註:TagTagSupportvoid setParent(Tag parentTag)

Objectives 13.1~13.2 (約 4 題)

13.1、13.2

Value Objects(VO)

Value Objects can be used best in scenarios where clients need to exchange data with Enterprise JavaBeans. Applications need to transfer data across tiers.

Model-View-Controller(MVC)

MVC is typically used in scenarios where an application needs to support many diverse client types that use the same back-end system.
The pattern also reduces coupling between presentation logic and business logic.

Data-Access Objects(DAO)

They are used in cases where the method of data access varies due to data being persisted in various different forms. For example, XML, relational databases, comma separated files, legacy systems, and so on.
Furthermore, accessing data using the same mechanism can vary due to vendor-specific implementations.

Business Delegate

The client communicates across a network and thus is expected to cope with the complexity of remote method invocations. An example of this complexity is the necessity to catch RemoteExceptions that might be thrown from EJB. This pattern allows the client to ignore the fact that calls are remote by handling the complexities of remote communication.
Issues Pattern
  • Small object
  • Grouped information
  • Read-only data
  • Reduce network traffic
  • Improve response time
  • Transfer data across networked tiers
Value Object
  • Flexible design
  • Provide services to different clients: web client, WAP client, etc.
  • Multiple views, such as HTML or WML
  • Single controller
Model-View-Controller(MVC)
  • Uniform access to the database
  • Transparent access to the database
  • Centralized access to the database
  • Reduce dependency on the type of database
  • Reduce dependency on the database access mechanism
  • Reduce coupling between the enterprise beans and the database
  • Reduce coupling between the business objects and the database
  • Easier migration of data from one database to another
  • Multiple data sources, such as database systems in the intranet, database systems
Data Access Object(DAO)
  • Reduce coupling between presentation and business tiers
  • Proxy for the client
  • Client-side facade
  • Cache business service references for presentation-tier components
  • Cache business service results for presentation-tier components
  • Encapsulate business service lookup
  • Encapsulate business service access
  • Decouple clients from business service API
Business Delegate
  • Dispatch requests
  • Manage workflow of a web application
  • Manage the sequence of steps
  • Manage use cases
Front Controller

Pattern/Important concepts Potential benfits
A Value Object is a small-sized serializable Java object that is used for transferring data over the network in a distributed application.
  • Less communication overhead
  • Fewer number of  remote calls
  • Reduction in network traffic
  • Increased response time
The Model-View-Controller design pattern is applicable in situations where the same data(Model) is to be presented in different formats(Views), but is to be managed centrally by a single controlling entity(Controller).
  • Flexible design
  • Centrally managed data
  • Multiple ways of presentation
A Data Access Object provides other application components with a clean, simple, and common interface to access the data from various multiple data stores.
DAO talks to the actual underlying database and takes care of the different types of data access mechanism.
  • Reduced dependency of other components on the datails of using the database
  • Access to database unified, centralized, and made transparent to the business-tier components
  • Reduced dependency on type of database
  • Reduced dependency on database access mechanism
  • Reduced coupling between the enterprise beans and the database
  • Reduced coupling between the business objects and the database
  • Migration of data from one database to another made easier
A Business Delegate is an object that communicates with the business service components on behalf of the client components.
The client-side components delegate the work of accessing the business services to the Business Delegate object.
  • Reduced coupling between presentation and business tiers
  • Cached business service results for presentation-tier components
  • Business service lookup encapsulated
  • Business service access encapsulated
  • Decoupled clients from business serviceAPI

補充:J2EE Patterns Catalog

記:與 header (1.3)redirect (1.3)HTTP status code (4.1)session (5.1) 有關的,均使用以 Http 開頭的 interface (HttpServletRequestHttpServletResponseHttpSession) 其他都使用不以 Http 開頭的 interface (ServletRequestServletResponseServletConfig)

//by JSwanky 2003-08-24