XML Syntax
ในปัจจุบันนี้ XML (Extensible Markup Language) ได้กลายเป็นส่วนหนึ่งของมาตรฐานที่ใช้กันอย่างกว้างขวางในวงการ*
web application เพื่อทำหน้าที่เป็นเอกสารที่ใช้ในการสื่อสารระหว่างจุดหนึ่งไปยังอีกจุดหนึ่ง
รวมไปถึงประโยชน์ทั่ว ๆ ในการเป็นตัวกลางในการเก็บข้อมูล ก่อนที่ข้อมูลเหล่านั้นจะถูกเปลี่ยนแปลงไป
โดย appliction ที่ทำการประมวลผลข้อมูลเหล่านั้น
เพื่อที่จะสนันสนุนและสามารถทำงานร่วมกับระบบที่มี XML เข้ามาเกี่ยวข้องได้อย่างมีประสิทธิภาพ,
Syntax ต่าง ๆ ใน JSP จึงถูกออกแบบ ให้สามารถเขียนอยู่ในรูปของ XML format
ได้ โดยเฉพาะอย่างยิ่งในส่วนของ JSP Actions
* XML ถูกนำไปใช้ประโยชน์ในหลาย ๆ วงการ แต่เรากล่าวถึงเฉพาะที่ใช้สำหรับ
web application เท่านั้น
โดยทั่วไป Tag ต่าง ๆ ที่อยู่ในรูปของ XML syntax
จะต้องมีลักษณะของการเปิดและปิดของ Tag ยกตัวอย่างเช่น
<mytag attr1="attribute value" ...>
body
</mytag>
ถ้าเป็น Tag ที่ไม่มี body, ตัวของ Tag จะต้องถูกปิดโดยตัวของมันเอง
โดยใช้ชื่อของ Tag นั้น ๆ ปิด หรือใส่ /
ไว้ที่ท้ายสุดของตัว Tag ยกตัวอย่างเช่น
<mytag attr1="attribute value"></mytag>
<mytag attr1="attribute value" .../>
จะสังเกตเห็นว่า การเขียน Tag ต่าง ๆ ในรูปแบบของ XML จะต้องการระเบียบแบบแผนมากกว่าการเขียน
Tag เดียวกันในรูปแบบของ HTML ยกตัวอย่างเช่น
HTML:
<img src="http://www.jarticles.com/images/jar.gif"> ไม่ต้องมี
</img>
ปิดท้าย แต่
XML:
<img src="http://www.jarticles.com/images/jar.gif"></img>
หรือ
<img src="http://www.jarticles.com/images/jar.gif"/>
case sensitive ก็เป็นส่วนหนึ่งของข้อบังคับในการเขียน XML
ยกตัวอย่างเช่น
HTML:
<head><title>My messy html code</TITLE><Head>
ไม่สนใจว่า case จะเป็นอย่างไร
XML:
<head><title>My clean xml code<title><head>
<HEAD><TITLE>My clean xml code<TITLE><HEAD>
<head><TITLE>My
clean xml code<TITLE><head>
<HEAD><title>My
clean xml code<title><HEAD>
จะเขียนอย่างไรก็ได้ แต่ Tag แต่ละตัว จะต้องมี case ที่เหมือนกัน
ยังมีรายละเอียดอีกหลายอย่างที่ควรรู้สำหรับผู้ที่สนใจการเขียน XML แต่ส่วนที่กล่าวถึงข้างต้นก็เพียงพอสำหรับที่เราจะใช้ในการเขียน
JSP Actions แล้ว (สำหรับผู้ที่สนใจเกี่ยวกับ XML ผู้เขียนอยากให้เริ่มเรียนรู้จาก
http://www.webmonkey.com)
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
ดังกล่าวอยู่
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" %> (Part II)
กับ <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>
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;
}
}
Note: จะสังเกตว่า 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
.../> โดยอัตโนมัติ
(สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ JavaBean สามารถหาอ่านได้จาก http://java.sun.com/beans/)
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 ที่ชื่อ com.jarticles.utils.TimeBean
โดยเราต้องการอ้างถึง Bean นี้โดยใช้ instance ที่ชื่อ time และกำหนดช่วงชีวิตให้อยู่แค่ในแต่ละ
request ของ client เราสามารถโหลด TimeBean นี้ได้โดยใช้
<jsp:useBean id="time" class="com.jarticles.utils.TimeBean" scope="request">
...body...
</jsp:useBean>
หรือ
<jsp:useBean id="time" class="com.jarticles.utils.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> นี้อยู่
Note: เราไม่สามารถใช้ 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 ทำการเลือกไว้
<jsp:forward> Action
Action นี้อนุญาติให้เราส่งผ่าน (forward) ตัว request ของ client จาก
JSP page ปัจจุบันไปยังเพจอื่น ๆ ซึ่งอาจจะเป็น JSP หรือ Servlet (ที่อยู่ใน
ServletContext) เดียวกันก็ได้ ซึ่งตัว <jsp:forward> จะทำลาย content
ของเพจปัจจุบันที่จะส่งให้กับ client โดยจะแทนด้วย content ของเพจที่ถูก forward
ไปแทน ลักษณะการใช้ก็คือ
<jsp:forward page="urlSpec" />
urlSpec คือ relative URL ของเพจที่เราส่งผ่าน request ไปให้
ตัวอย่างที่ใช้กัน ก็อาจจะเป็น
<jsp:forward page="/utils/errorPage.jsp" />
<jsp:forward page="<%= whereTo %>" />
จะสังเกตเห็นว่า ในส่วนของ page attribute เราสามารถใส่ค่าที่เป็น
dynamic ก็ได้
<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 หรือเกิดข้อผิดพลาดบางอย่างขึ้น
Next >>
Copyright (C)
2000 www.jarticles.com.
|