|
JSP Actions
JSP Actions สามารถใช้ในการควบคุมและเปลี่ยนแปลงการทำงานของไฟล์ JSP
ที่เราเขียน ซึ่งอาจจะเป็นในลักษณะของ
1) insert ไฟล์ต่าง ๆ เข้ามาเป็นส่วนหนึ่งของไฟล์ JSP ปัจจุบัน โดยใช้
<jsp:include page="exfile.jsp" .../> tag
2) ใช้สำหรับควบคุมการทำงานของ JavaBean ที่เป็นส่วนประกอบหนึ่งของไฟล์
JSP นั้น โดยใช้ <jsp:useBean .../>, <jsp:setProperty .../>,
<jsp:getProperty .../> tag
3) ใช้ในการส่งผ่าน (forward) request ของ client ไปยังไฟล์ JSP อื่น
ๆ โดยใช้ <jsp:forward .../> tag
4) ใช้ <jsp:plugin type="... /> tag เพื่อทำการสร้าง OBJECT
หรือ EMBED code ที่ใช้สำหรับเรียก(หรือโหลด) Java plugin เพื่อทำการรัน
Applet หรือ JavaBean ในตัว browser ที่กำลังเปิดไฟล์ JSP ดังกล่าวอยู่
1) jsp:include
action
action นี้ ใช้สำหรับ insert ไฟล์ต่าง ๆ เข้ามาที่ไฟล์ JSP ปัจจุบัน
โดยใช้
<jsp:include
page="relativeURL" flush="true"/>

relativeURL คือ ที่อยู่ของไฟล์ที่เราจะทำการ insert ซึ่งจะต้องอยู่ในรูปของ
relative URL กับไฟล์ JSP ปัจจุบัน
flush คือ ตัวที่บอก JSP Container ให้ทำการ flush สิ่งต่าง ๆ ที่อยู่ใน
buffer ของ page output ออกไปที่ outputStream ก่อนที่จะทำการ insert
ไฟล์นี้เข้าไป โดยใช้ค่า flush="true"
Note: ค่า flush="true" เป็นค่าบังคับสำหรับ <jsp:include
.../> เราไม่สามารถใช้ค่า flush="false" ได้ใน JSP 1.1
มีประเด็นที่น่าสนใจคือ
ข้อแตกต่างระหว่าง <%@ include file="relativeURL" %>
กับ <jsp:include page="relativeURL"/> สำหรับ <%@
include ...%> ไฟล์ relativeURL จะถูกใส่เข้าไปเป็นส่วนหนึ่งของไฟล์
JSP ที่มี include directive นี้อยู่ ในช่วงของการแปลงไฟล์ JSP ให้กลายเป็น
servlet ข้อดีก็คือจะเร็ว แต่ข้อเสียคือไฟล์ relativeURL ที่ถูก insert
เข้าไปอาจจะไม่อัพเดท ซึ่งจะเกิดขึ้นในกรณีที่ไฟล์ relativeURL ดังกล่าวถูกเปลี่ยนแปลงไป
แต่เกิดขึ้นหลังจากที่ไฟล์ JSP ที่บรรจุไฟล์ relativeURL นี้อยู่ถูกแปลงเป็น
servlet แล้ว
แต่ในลักษณะของ <jsp:include .../> ตัว JSP Container จะทำการ
insert ไฟล์ relativeURL นี้เข้าไปในไฟล์ JSP ทุก ๆ ครั้ง ที่ไฟล์
JSP ดังกล่าวถูก request โดย client ซึ่งข้อดีก็คือ เราจะได้ไฟล์ relativeURL
ที่เป็นเวอร์ชั่นอัพเดทอยู่เสมอ แต่ข้อเสียคือ จะเสียเวลาในการโหลดและ
insert ไฟล์ relativeURL นี้เข้ามาอยู่ด้วยทุกครั้ง
ประโยชน์ของ
<jsp:include .../> ที่ใช้กันโดยทั่วไป ก็เช่นการโหลดหรือซ่อนส่วนใดส่วนหนึ่งของเพจ
โดยใช้ attribute ของ user ที่ล็อกอินเข้ามาในระบบเป็นตัวตัดสิน ยกตัวอย่างเช่น
<HTML>
<HEAD>
...
<%
int userRole = userInfo.getUserRoleFromDB();
if (userRole == UserType.ADMIN) {
%>
<jsp:include page="jsp/AdminMenu.jsp" flush="true"/>
<%
} else {
%>
<jsp:include page="template/UserMenu.html" flush="true"/>
<%
}
%>
...
</BODY>
</HTML>
2) jsp:useBean
action
JavaBean
ในการเขียน JSP สำหรับระบบใหญ่ ๆ นักพัฒนาจะไม่นิยมใส่ java code ลงไปในไฟล์
JSP มากนัก สิ่งที่อยู่ในไฟล์มักจะเป็นเพียง HTML code และค่าของ variables
ต่าง ๆ ที่ได้มาจาก JavaBeans เท่านั้น. ข้อดีของการใช้ JavaBean คือการง่ายต่อการเปลี่ยนแปลงลักษณะของ
look-and-feel ของไฟล์ JSP ที่เป็นเช่นนี้เพราะ ส่วนที่เป็น data (variables)
กับส่วนที่เป็น presentation (HTML) จะอยู่ด้วยกันอย่างหลวม ๆ ดังนี้เราจึงสามารถเปลี่ยนตัว
presentation เมื่อไรก็ได้ โดยตัว JavaBean ที่ใช้เก็บค่าของ variables
ต่าง ๆ ยังคงเหมือนเดิม
สำหรับคนที่ไม่คุ้นกับ
JavaBean ให้นึกถึง JavaBean เป็นลักษณะของกล่อง โดยกล่องนี้มีส่วนที่ใช้ติดต่อกับโลกภายนอกอยู่สองส่วนหลัก
ๆ คือ
1. ส่วนที่ใช้สำหรับรับข้อมูลต่าง
ๆ โดยข้อมูลเหล่านี้จะถูกใช้เป็นตัวแปร ในการควบคุมหรือเปลี่ยนแปลงคุณสมบัติและการทำงานของกล่อง
(Setter)
2. ส่วนที่ใช้สำหรับอ่านคุณสมบัติของกล่อง (Getter) ซึ่งโดยส่วนมาก(แต่ไม่ทั้งหมด)
ก็คือค่าของตัวแปรต่าง ๆ ที่บรรจุอยู่ในกล่อง
ในการใช้งานกล่อง
(JavaBean) ดังกล่าวร่วมกับ JSP เราสามารถที่จะสร้างกล่องขึ้นมาโดยใช้
<jsp:useBean .../>, ส่งค่าเข้าไปในกล่องโดยใช้ <jsp:setProperty
.../> และอ่านค่าต่าง ๆ ที่อยู่ในกล่อง โดยใช้ <jsp:getProperty
.../> tag แต่ก่อนที่เราจะเรียนรู้ถึงการใช้ tag เหล่านี้ เรามาทำความรู้จัก
JavaBean กันก่อน
Bean
Conventions
สำหรับคนที่เคยเขียน application ที่เกี่ยวกับ JavaServlet หรือ RMI
จะพบว่า แต่ละคลาสที่เราเขียนขึ้น อาจจะต้องมีการ extend คลาสใดคลาสหนึ่งก่อน
เช่น HttpServlet (ในกรณีของการเขียน JavaServlet) หรืออาจต้องทำการ
implement interface ต่าง ๆ เช่น Serializable (ในกรณีของการเขียน
RMI) แต่สำหรับการเขียนคลาสให้กลายเป็น JavaBean แล้ว เราไม่จำเป็นต้องทำสิ่งต่าง
ๆ ที่กล่าวมาข้างต้นเลย. JavaBean จริงๆ แล้วก็คือ จาวาคลาสธรรมดา
ๆ แต่ถูกเขียนขึ้นโดยใช้ naming และ design conventions ที่อยู่ใน
JavaBean Specification เท่านั้น. Conventions หลัก ๆ ที่เราจะพูดสำหรับการเขียน
JavaBean เพื่อใช้ใน JSP มีดังต่อไปนี้คือ
1) The
Bean Constructor
ในการเขียน Bean* ให้สามารถใช้ได้กับ <jsp:useBean .../> สิ่งหนึ่งที่
Bean ของเราจะต้องมีคือ ตัว constructor ที่ไม่ต้องการ argument สำหรับการ
initialize ของ Bean ยกตัวอย่างเช่น
* JavaBean และ Bean ในที่นี้จะหมายถึงสิ่งเดียวกัน
public
class UselessBean { }
หรือ
public
class AnotherUselessBean {
public AnotherUselessBean() { }
}
หรือ
public
class TimeBean {
private int hours;
private int minutes;
public
TimeBean() {
java.util.Date rightNow = new java.util.Date();
hours = rightNow.getHours();
minutes = rightNow.getMinutes();
}
}
คลาสทั้งสาม
UselessBean, AnotherUselessBean และ TimeBean เขียนถูกต้องตาม Bean
Convention ทุกอย่าง คือมี constructor ที่ไม่ต้องการ argument สำหรับการ
initialize ดังนั้นเราสามารถเรียกคลาสทั้งสามว่า JavaBean.
เราสามารถนำคลาสเหล่านี้ไปใช้กับ
<jsp:useBean ... /> ได้ อย่างไรก็ตามคลาสทั้งสามนี้ยังไม่มีประโยชน์อะไรสำหรับไฟล์
JSP จริง ๆ ประโยชน์ที่เราจะได้จาก Bean ก็คือการส่งค่าต่าง ๆ เพื่อทำการควบคุมและเปลี่ยนแปลงคุณสมบัติของ
Bean รวมไปถึงการอ่านค่าคุณสมบัติต่าง ๆ ของ Bean ซึ่งสิ่งเหล่านี้จะเกิดขึ้นได้โดยอาศัยสิ่งหนึ่ง
ที่เรียกว่า Bean's Properties
2) Bean's
Properties
Bean's Properties คือตัวที่บอกว่า เราสามารถทำอะไรกับ JavaBean นั้นได้บ้าง
[โดยส่วนมาก(แต่ไม่ทั้งหมด) ก็คือการเปลี่ยนและอ่านค่าต่าง ๆ ของ instance
variables ที่บรรจุอยู่ข้างใน Bean นั้น ๆ] ซึ่งผลที่ได้ก็คือ การควบคุมและเปลี่ยนแปลงคุณสมบัติต่าง
ๆ ของ Bean อย่างไรก็ตามบางที properties ที่เรากำหนดขึ้น อาจจะไม่ได้ทำอะไรที่เกี่ยวข้องกับ
instance variables ที่อยู่ข้างใน Bean นั้นเลย
JSP
Container จะสามารถทราบว่า JavaBean ของเรามี properties อะไรบ้าง
ได้จากวิธีการที่เรียกว่า introspection หลักการก็คือ JSP Container
จะทำการวิเคราะห์ฟังก์ชั่นที่เป็น public ของ Bean นั้น ซึ่งจะต้องเขียนขึ้นอย่างถูกต้อง
ตามหลักของ JavaBean API โดยจะถือว่า property ใด ๆ ก็ตามจะเกิดขึ้นได้ก็ต่อเมื่อ
Bean คลาสนั้นมี
1. public
ฟังก์ชั่นที่ใช้สำหรับควบคุมหรือเปลี่ยนแปลงค่าของ property นั้น (Setter)
หรือ
2. public ฟังก์ชั่นที่ใช้สำหรับอ่านค่าของ property นั้น (Getter)
หรือ
3. มีทั้งสองฟังก์ชั่นข้างต้น
สรุปง่าย
ๆ ก็คือ ในการกำหนด property ขึ้นมาอันหนึ่ง เราจะต้องสร้าง public
ฟังก์ชั่นที่ขึ้นต้นด้วยคำว่า set (Setter) ซึ่งใช้สำหรับควบคุมหรือเปลี่ยนแปลงค่าของ
property นั้น และหรือ public ฟังก์ชั่นที่ขึ้นต้นด้วยคำว่า get (Getter)
ซึ่งใช้สำหรับอ่านค่าของ property นั้น โดยรูปแบบโดยทั่วไปก็คือ
public
void setPropertyName(PropertyType value);
public PropertyType getPropertyName();
ยกตัวอย่างเช่น
ถ้าเราต้องการกำหนด property ที่ชื่อ hours ซึ่งมีค่าเป็นแบบ int โดยที่เราสามารถเปลี่ยนค่าและอ่านค่าของ
hours ได้ ฟังก์ชั่นที่เราจะต้องสร้างขึ้นเพื่อบอกให้ Container ทราบว่ามี
property นี้อยู่ใน Bean ก็คือ
public
void setHours(int hour);
public int getHours();
หรือ
ถ้าเราต้องการกำหนด property ที่ชื่อ firstName ซึ่งมีค่าเป็นค่าแบบ
String เราก็สามารถบอก Container ให้ทราบว่ามี property นี้อยู่ใน
JavaBean ได้โดยใช้
public
void setFirstName(String firstName);
public String getFirstName();
ย้อนกลับมาที่
TimeBean โดยเพิ่มส่วนที่เป็น Setter และ Getter เข้าไป เราจะได้
public
class TimeBean {
private int hours;
private int minutes;
public
TimeBean() {
java.util.Date rightNow = new java.util.Date();
hours = rightNow.getHours();
minutes = rightNow.getMinutes();
}
public
int getHours() {
return hours;
}
public
void setHours(int hours) {
this.hours = hours;
}
public
int getMinutes() {
return minutes;
}
}
จะสังเกตว่า
property ที่ชื่อ minutes จะไม่มี Setter แต่อย่างที่กล่าวมาข้างต้นก็คือ
เราสามารถบอก Container ให้ทราบว่า JavaBean ของเรามี properties อะไรบ้างโดยการสร้าง
public ฟังก์ชั่นที่เป็น Setter หรือ Getter หรือ สร้างทั้ง Setter
และ Getter ก็ได้ ใน JSP ไฟล์ เราสามารถเรียกใช้ TimeBean ได้ดังตัวอย่างข้างล่าง
(จะกล่าวถึงรายละเอียดต่อไป)
<jsp:useBean
id="time" class="TimeBean" scope="request"/>
<HTML>
<BODY>
Time is <jsp:getProperty name="time" property="hours"/>
with minutes = <jsp:getProperty name="time" property="minutes"/>
...
ในการเขียน
JavaBean เพื่อกำหนด properties ต่าง ๆ หลายคนมักเข้าใจผิดคิดว่า properties
ก็คือ instance variables. ในตัวอย่างของ TimeBean จะเห็นว่า property
ที่ชื่อ hours และ minutes จะเกี่ยวข้องกับ instance variable ที่ชื่อ
hours และ minutes แต่อย่างไรก็ตาม เราสามารถกำหนด properties ต่าง
ๆ ขึ้นมา โดยไม่เกี่ยวข้องกับ instance variable ใด ๆ เลยก็ได้ ยกตัวอย่างเช่น
public
class RandomBean {
private java.util.Radom rand;
public
RandomBean() {
rand = new Random();
}
public
int getRandomNumber() {
// return a number between 0-10
return rand.nextInt(10);
}
public
int getRandomDice() {
// return a number bewteen 1-6
return rand.nextInt(6) +1;
}
}
จากตัวอย่าง
จะเห็นว่า property ที่ชื่อ randomNumber และ randomDice ไม่ได้เกี่ยวข้องกับ
instance variables ใด ๆ ทั้งสิ้น ค่าต่าง ๆ ของ properties เหล่านี้ถูกสร้างขึ้นโดยใช้คลาส
java.util.Random.
สำหรับการใช้ RandomBean ในไฟล์ JSP ก็อาจเป็นดังตัวอย่างข้างล่าง
<jsp:useBean
id="random" class="RandomBean" scope="session"/>
<HTML>
<BODY>
Our random number is <jsp:getProperty name="random"
property="ramdomNumber"/>
Random number by dice is <jsp:getProperty name="random"
property="randomDice"/>
...
Property
Name Conventions
โดยทั่วไป การเขียนชื่อของ properties ต่าง ๆ จะเป็นในลักษณะของลูกผสมคือ
มีทั้งตัวใหญ่และตัวเล็ก ซึ่งจะขึ้นต้นด้วยตัวเล็กในคำแรกและจะตามด้วยตัวใหญ่ในคำถัด
ๆ มา ยกตัวอย่างเช่น firstName, lastName, randomNumber, timeInHour
เป็นต้น สำหรับตัว setter และ getter ของ properties ดังกล่าวก็จะเป็น
setFirstName, setLastName, setRandomNumber, setTimeInHour และ getFirstName,
getLastName, getRandomNumber, getTimeInHour ตามลำดับ.
เราจะสังเกตเห็นว่า ชื่อของ properties และตัว setter, getter ของ
properties เหล่านั้นจะต่างกันที่ตัวแรก หลังจากคำว่า set หรือ get
เท่านั้น ในการตีความ setter, getter เพื่อหา properties ต่าง ๆ ของ
JavaBean โดย JSP Container, JSP Container จะทำการแปลง case ต่าง
ๆ ให้สอดคล้องกับชื่อของ properties ที่อยู่ใน <jsp:getProperties
.../>, <jsp:setProperty .../> โดยอัตโนมัติ
Loading
a Bean - <jsp:useBean>
ก่อนที่เราจะสามารถใช้ JavaBean ใน JSP ได้ สิ่งแรกที่เราต้องทำคือ
การโหลด instance ของ Bean
เราสามารถโหลด instance ของ Bean เข้ามาในระบบได้โดยใช้ <jsp:useBean
.../> โดยเราจะต้อง
1. กำหนดชื่อที่จะใช้ในการอ้างถึง
instance ของ Bean นี้ (id)
2. กำหนดคลาสของ Bean ที่จะโหลด (class)
3. ทำการเซ็ต scope (หรือช่วงชีวิต) ของ Bean ว่าจะยาวนานแค่ไหน (scope)
ดังรูปแบบข้างล่าง
<jsp:useBean
id="myBeanInstance" class="com.myPackage.BeanClass"
scope="page|request|session|application">
...body...
</jsp:useBean>
เพราะว่า
<jsp:useBean> เขียนในรูปแบบของ XML ดังนั้นจึงต้องมีตัวปิด
tag </jsp:useBean>
จากตัวอย่างจะเห็นว่าใน <jsp:useBean> จะมีส่วนที่เป็น ...body...
อยู่ โดยส่วนนี้จะถูกเรียกเพียงครั้งเดียวในช่วงที่ instance ของ Bean
ถูกโหลด ในกรณีที่ไม่มี ...body... เราสามารถเขียน <jsp:useBean>
ให้อยู่ในรูปของ Empty tag ได้ โดยใช้
<jsp:useBean
id="myBeanInstance" class="com.myPackage.BeanClass"
scope="page|request|session|application"/>
สมมุติว่า
TimeBean อยู่ใน package ที่ชื่อ net.energythai.TimeBean โดยเราต้องการอ้างถึง
Bean นี้โดยใช้ instance ที่ชื่อ time และกำหนดช่วงชีวิตให้อยู่แค่ในแต่ละ
request ของ client เราสามารถโหลด TimeBean นี้ได้โดยใช้
<jsp:useBean
id="time" class="net.energythai.TimeBean" scope="request">
...body...
</jsp:useBean>
หรือ
<jsp:useBean
id="time" class="net.energythai.TimeBean" scope="request"/>
บางครั้ง
<jsp:useBean> อาจจะไม่ทำการโหลด new instance ของ Bean ขึ้นมา
ถ้าหากว่า instance ดังกล่าวถูกโหลดขึ้นมาก่อนแล้ว โดยบรรทัดฐานของการโหลด
Bean จะขึ้นอยู่กับ scope ที่เซ็ตไว้ให้กับ instance ของ Bean นั้น
Initializing
a Bean - <jsp:setProperty>
ใน Bean Conventions เรากล่าวถึง Bean Constructor ที่ไม่ต้องการ arguments
ซึ่งถูกใช้สำหรับ <jsp:useBean> อย่างไรก็ตามบางครั้ง Bean ที่เราใช้อาจต้องการค่าเริ่มต้นในการ
initialize ซึ่งเราสามารถทำการเซ็ตค่าต่าง ๆ ให้ Bean ได้โดยใช้ <jsp:setProperty
.../>
ค่าที่เราจะเซ็ตให้ Bean บางครั้งอาจมาจากค่าที่เรากำหนดขึ้น หรืออาจจะเป็นค่าที่ได้จาก
request ของ client ซึ่งมาจาก element ต่าง ๆ ใน <FORM> tag
ของ html ดังนั้นการเซ็ตค่า Bean จึงถูกแบ่งออกเป็นสองแบบคือ
1. การเซ็ตค่าให้
Bean โดยใช้ค่าที่เรากำหนดขึ้น เช่น
<jsp:useBean
id="myBeanInstance" class="com.myPackage.BeanClass"
scope="request">
<jsp:setProperty name="myBeanInstance" property="myProperty"
value="definedValue"/>
</jsp:useBean>
name
คือ ชื่อของ Bean instance ที่เราต้องการอ้างถึง
property คือ ชื่อของ property ที่เราต้องการเซ็ตค่า
value คือ ค่าที่เราจะใส่เข้าไปให้ property นั้น
2. การเซ็ตค่าให้
Bean โดยใช้ค่าที่ได้จาก element ต่าง ๆ ของ <FORM> tag เช่น
<jsp:useBean
id="myBeanInstance" class="com.myPackage.BeanClass"
scope="request">
<jsp:setProperty name="myBeanInstance" property="myProperty"
param="myFormElementName"/>
</jsp:useBean>
param
คือ ชื่อของ element ที่อยู่ใน <FORM> tag ที่ส่ง request มาที่ไฟล์
JSP ที่มี <jsp:useBean> นี้อยู่
ให้สังเกตุว่า
เราไม่สามารถใช้ value และ param พร้อมกันได้ เพราะ JSP Container
จะไม่ทราบว่าเราจะใช้ค่าไหนในการเซ็ตให้ Bean
ในกรณีที่ค่าทุกค่าใน Bean ขึ้นอยู่กับ ค่าของ element ต่าง ๆ ใน <FORM
> tag เราสามารถบอกให้ JSP Container แมปค่าของ element เข้ากับ
ค่า property ต่าง ๆ ของ Bean ได้โดยอัตโนมัติ โดยการใช้ property="*"
ดังตัวอย่างข้างล่าง
<jsp:useBean
id="myBeanInstance" class="com.myPackage.BeanClass"
scope="request">
<jsp:setProperty name="myBeanInstance" property="*"/>
</jsp:useBean>
เพิ่มเติมอีกนิดหนึ่งคือ
<jsp:setProperty> ไม่จำเป็นจะต้องอยู่ใน <jsp:useBean>...
</jsp:useBean> เสมอไป เราสามารถเรียกใช้ tag นี้เมื่อไรก็ได้
ที่เราต้องการเปลี่ยนหรือเซ็ตค่าของ property ของ Bean
Displaying
Dynamic Content - <jsp:getProperty>
หลังจากที่เราทำการโหลด และเซ็ตค่าของ property ต่าง ๆ ใน Bean แล้ว
เราสามารถดูผลที่เกิดขึ้นได้ โดยใช้
<jsp:getProperty
name="myBeanInstance" property="myProperty"/>
ค่าที่ได้จาก
<jsp:getProperty> อาจจะเป็นค่าของ instance variables ของ Bean
ที่เปลี่ยนไปหลังจากที่เราใช้ <jsp:setProperty> หรือบางครั้ง
อาจจะเป็นลิสท์ของตารางรายชื่อ ในกรณีที่ค่า property ที่เราเซ็ตผ่าน
<jsp:setProperty> เป็นตัว trigger ให้ Bean ส่ง query ไปที่ฐานข้อมูล
เป็นต้น
The
scope Attribute
โดยทั่วไปในการสร้าง instance ของ Bean แต่ละตัว เราจะต้องกำหนดว่าช่วงชีวิตของ
instance นั้นจะยาวนานแค่ไหน. scope เป็นตัวที่ถูกใช้ในการกำหนดช่วงชีวิตของ
instance เหล่านั้น โดยเราสามารถเซ็ต scope ได้เป็นสี่แบบคือ
Scope
in JSP
page
Object is accessible only by a single client from the page on which
it is created.
request
Object is accessible by a single client for the lifetime of a single
client request.
session
Object is accessible by a client from anywhere in the application
for the lifetime of an entire user session.
application
Object is accessible by any client from any page within the application
for the lifetime of the application.
Instance
ของ Bean ที่ถูกเซ็ต scope="page" จะมีช่วงชีวิตอยู่ตั้งแต่
JSP page ที่มี instance ดังกล่าวอยู่ทำการประมวลผล ไปจนถึงระยะเวลาที่เพจดังกล่าวเสร็จสิ้นการประมวลผลแล้ว.
ถ้า scope ถูกเซ็ตเท่ากับ request, instance ของ Bean จะมีช่วงชีวิตอยู่ตั้งแต่
request ของ client ถูกส่งมาถึง JSP Container จนถึงช่วงที่ client
ได้รับ page output ทั้งหมดกลับไปแล้ว (ซึ่งส่งกลับไปโดย ServletResponse).
ข้อแตกต่างระหว่างสอง scope นี้คือ ในหนึ่ง HttpRequest อาจจะมีการเกี่ยวข้องกับ
JSP page หลาย ๆ เพจ ยกตัวอย่างเช่น การใช้ include directive เพื่อประกอบ
JSP page หลาย ๆ เพจเข้าด้วยกัน หรือแม้กระทั่งการใช้ <jsp:forward>
ซึ่งจะทำการส่ง ServletRequest จาก JSP page หนึ่งไปยังอีกเพจหนึ่ง
ดังนั้นเราอาจพูดได้ว่า ในหนึ่ง scope ของ request(ServletRequest)
จะประกอบด้วยหลาย ๆ scope ที่เป็น page(javax.servlet.jsp.PageContext)
ในกรณีของ
scope="session", instance ของ Bean จะมีช่วงชีวิตยาวนานเท่ากับ
HttpSession ของ client นั้น ๆ ซึ่งก็คือ ตั้งแต่ client เริ่มทำการติดต่อกับ
server ที่มี JSP เพจดังกล่าวอยู่ จนถึงเวลาที่ client นั้นหายไป ซึ่งอาจเกิดขึ้นจากการปิด
browser หรือการขาดการติดต่อกับ server เป็นเวลานาน ๆ (timeout). scope
แบบสุดท้ายก็คือ application (ServletContext) ซึ่งจะยาวนานตั้งแต่
instance ของ Bean นั้นถูกสร้างขึ้นจนถึงระยะเวลาที่ server ที่มี
Bean นั้นอยู่ถูก shutdown หรือ restart.
ในส่วนของ
<jsp:useBean> แล้ว scope จะเป็นตัวกำหนดว่า JSP Container จะต้องทำการโหลด
instance ของ Bean ขึ้นมาใหม่หรือไม่ ยกตัวอย่างเช่น ถ้า instance
ของ Bean ถูกเซ็ต scope ให้เป็น request, JSP Container จะทำการสร้าง
Bean instance ขึ้นมาใหม่ ในทุกครั้งที่มี request ใหม่ถูกส่งมาจาก
client โดยหลังจากที่ request ดังกล่าวเสร็จสิ้นลง Bean instance ที่ถูกสร้างขึ้นโดย
request นั้นจะถูกทำลาย โดย JSP Container จะทำการสร้างขึ้นมาใหม่อีกครั้ง
สำหรับ request อันถัดไป
ในกรณีของ Bean instance ที่ถูกเซ็ต scope ให้เป็น session, JSP Container
จะทำการสร้าง instance ดังกล่าวขึ้นในครั้งแรกที่ instance นั้นถูกเรียกใช้เท่านั้น
ถ้า instance นี้ถูกเรียกใช้อีกในอนาตค, JSP Container จะไม่ทำการสร้าง
Bean instance ขึ้นมาอีก แต่จะทำการโหลด instance ที่สร้างขึ้นไว้แล้วมาใช้แทน
application อันหนึ่งที่ใช้ประโยชนจาก Bean instance ที่มี scope="session"
ก็คือ shopping cart ซึ่ง Bean instace นี้จะถูกใช้เป็นตัวเก็บรายชื่อสินค้าที่
client ทำการเลือกไว้
3) jsp:forward
action
Action นี้อนุญาติให้เราส่งผ่าน (forward) ตัว request ของ client
จาก JSP page ปัจจุบันไปยังเพจอื่น ๆ ซึ่งอาจจะเป็น JSP หรือ Servlet
(ที่อยู่ใน ServletContext) เดียวกันก็ได้ ซึ่งตัว <jsp:forward>
จะทำลาย content คือ halt การ process ของเพจปัจจุบันที่จะส่งให้กับ
client โดยจะแทนด้วย content ของเพจที่ถูก forward ไปแทน ลักษณะการใช้ก็คือ
<jsp:forward
page="urlSpec" />
urlSpec
คือ relative URL ของเพจที่เราส่งผ่าน request ไปให้
ตัวอย่างที่ใช้กัน ก็อาจจะเป็น
<jsp:forward page="/utils/errorPage.jsp" />
<jsp:forward page="<%= whereTo %>" />
จะสังเกตเห็นว่า
ในส่วนของ page attribute เราสามารถใส่ค่าที่เป็น dynamic ก็ได้
เพจที่ถูกเรียกสามารถส่ง
resource bean parameters ปลายทาง โดยแทนที่ เข้าไปใน request ดังแสดงในรูป

นอกจากนี้เรายังสามารถใช้ jsp:param เป็น subelements เพื่อเตรียมค่าสำหรับบาง
elements ใน request ที่ใช้ในการทำ forwarding ดังตัวอย่าง
<jsp:forward
page="<%= somePage %>" >
<jsp:param name="name1" value="value1" />
<jsp:param name="name2" value="value2" />
</jsp:forward>
4) jsp:plugin action
ปกติ HTML code ที่ใช้ในการโหลด Java Plugin ไว้สำหรับรัน Applet จะต้องเขียนอย่างน้อย
2 เวอร์ชันไว้สำหรับสนันสนุน Netscape และ IE ยกตัวอย่างเช่น ถ้าเราต้องการรัน
Applet โดยใช้ Java Plugin, HTML code ที่เราจะต้องเขียนสำหรับ Netscape
และ IE ก็จะเป็นอย่างข้างล่าง
<APPLET>
tag ที่ใช้สำหรับโหลดและรัน Applet โดยไม่ใช้ Java plugin
<APPLET code="XYZApp.class" codebase="html/"
align="baseline"
width="200" height="200">
<PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
No Java 2 SDK, Standard Edition v 1.3 support for APPLET!!
</APPLET>
EMBED
Tag เพื่อบอก Netscape ให้ใช้ Java Plugin (หรือโหลด ถ้ายังไม่มี)
สำหรับ <APPLET> tag ข้างต้น
<EMBED type="application/x-java-applet;version=1.3"
width="200"
height="200" align="baseline" code="XYZApp.class"
codebase="html/" model="models/HyaluronicAcid.xyz"
pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html">
<NOEMBED>
No Java 2 SDK, Standard Edition v 1.3 support for APPLET!!
</NOEMBED>
</EMBED>
Object Tag เพื่อบอก IE ให้ใช้ Java Plugin (หรือโหลด ถ้ายังไม่มี)
สำหรับ <APPLET> tag ข้างต้น
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
width="200" height="200" align="baseline"
codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0">
<PARAM NAME="code" VALUE="XYZApp.class">
<PARAM NAME="codebase" VALUE="html/">
<PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
<PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
<PARAM NAME="scriptable" VALUE="true">
No Java 2 SDK, Standard Edition v 1.3 support for APPLET!!
</OBJECT>
จะเห็นว่าโค้ดแต่ละแบบค่อนข้างจะซับซ้อนและใช้เวลาในการเขียน
ซึ่งทาง SUN ก็เห็นใจนักพัฒนาสำหรับเรื่องนี้ จึงมีโปรแกรมที่ชื่อ
HTMLConverter ไว้สำหรับเปลี่ยน <Applet> code แบบที่ไม่ใช้
Plugin ให้กลายเป็นเวอร์ชันที่ใช้ Plugin สำหรับ Netscape และ IE โดยเฉพาะ
แต่สำหรับ JSP แล้ว เราไม่จำเป็นต้องเขียนโค้ดดังกล่าว โดยเราสามารถใช้
<jsp:plugin> ซึ่งจะทำการตรวจชนิดของ browser และทำการสร้างโค๊ด
<EMBED> หรือ <OBJECT> ใส่เข้าไปแทนโดยอัตโนมัติ แต่เราอาจจะต้องใส่ค่า
parameter ต่าง ๆ ที่จำเป็นสำหรับ <APPLET> เข้าไปใน <jsp:plugin>
ด้วย ยกตัวอย่างเช่น
<jsp:plugin
type="applet" code="Molecule.class" codebase="/html">
<jsp:params>
<jsp:param name="molecule" value="molecules/benzene.mol"/>
</jsp:params>
<jsp:fallback>
<p> unable to start plugin </p>
</jsp:fallback>
</jsp:plugin>
<jsp:param>
เป็นตัวบ่งบอกถึง parameter ต่าง ๆ ที่ใช้สำหรับ Applet
<jsp:fallback> เป็นตัวที่ใช้ใส่ข้อความเพื่อบอกว่าเกิดอะไรขึ้น
ในกรณีที่ Java Plugin ไม่สามารถ start หรือเกิดข้อผิดพลาดบางอย่างขึ้น
ตัวอย่างการเขียน
JSP โดยใช้ Bean และ Actions ต่างๆ
|