|
Standard
Syntax and Semantics
หลังจากได้เห็นตัวอย่างการทำงานของ
jsp กันแล้ว ในการศึกษาภาษาส่วนใหญ
่ เราคงเริ่มจากเรื่อง syntax กฏเกณฑ์ต่างๆ ในที่นี้เราจะทำโปรแกรมสั้นๆไปพร้อมกันด้วย
ให้เขียนไฟล์ accessCount.jsp ตามตัวอย่างข้างล่างนี้ แล้วดูผลที่ได้
<%--
This is comment --%>
<%@ page info="Access Count Sample" %>
<%@ page import="java.util.Date" %>
<HTML>
<HEAD><TITLE>Hello, JSP</TITLE></HEAD>
<BODY bgcolor="#ffffff">
<H1>Hello JSP</H1>
<BR>
<%! private int accessCount = 0; %>
<% accessCount++;
Date rightNow = new Date(); %>
Access Page: <%= accessCount %> times... at
<%= rightNow.toString() %>
</BODY>
</HTML>
จะเห็นว่ามี
script ที่อยู่ในรูปของ <% ... %> (Directives and Scripting
Elements) แตกต่างกัน 5 แบบ คือ
JSP Directives
and Scripting Elements
Directives
<%@ directive %>
Declarations
<%! declaration %>
Expressions
<%= expression %>
Code Fragment/Scriptlet
<% code fragment %>
Comments
<%-- comment --%>
Directives
JSP Directives เป็นส่วนที่เรียกว่า "message" ที่ใช้ส่งไปถึง
JSP Container
ในลักษณะของ <%@ ... %> โดย message นี้จะเป็นตัวบอกว่า Container
ควรจะทำอะไรกับ JSP Page ต่อไป ซึ่ง directives ในส่วนนี้จะไม่มีผลต่อหน้าตาที่ออกมา
ของ JSP Page เมื่อถูกแปลงออกมาในรูปของ html แล้ว Directives แบ่งออกเป็นสามส่วน
ส่วนที่เราใช้ทั่ว ๆ ไปคือ page และ include กับส่วนที่สามซึ่งเป็น
taglib
(เราจะไม่กล่าวถึงในที่นี้) ซึ่งใช้สำหรับสร้าง Tag ของเราเองใน JSP
page
directive เป็นส่วนที่ปกติเราจะเห็นอยู่บนสุดของ JSP page
ซึ่งใช้ในการกำหนดค่าต่าง ๆ ที่เกี่ยวข้องกับ JSP page นั้น ๆ หรือเกี่ยวข้องกับ
การติดต่อสื่อสารกับ JSP Container ยกตัวอย่างเช่น
ถ้าเราอยากเรียกใช้คลาสที่ชื่อ java.util.Date เราก็สามารถที่จะ import
คลาสนี้ได้โดยใช้
<%@ page import="java.util.Date" %>
หรือเวลาที่เกิดข้อผิดพลาดใน
JSP page ของเรา แล้วเราอยากให้แสดงข้อผิดพลาด
ที่เกิดขึ้น ที่ error page ที่ชื่อ errorPage.jsp เราก็ใช้
<%@ page errorPage="errorPage.jsp" %>
หรือแม้กระทั่งเวลาที่เราอยากจะเก็บ
states ของ user ในรูปของ session เราก็สามารถใช้
<%@ page session="true" %>
เพื่อบอก
container ว่า JSP Page นี้สามารถเรียกใช้ HttpSession
ในการเปลี่ยนแปลงและเก็บ states ของ user ได้ เป็นต้น
include
directive เป็นส่วนที่ช่วยให้เราสามารถนำไฟล์ JSP อื่น ๆ มาเป็นส่วนประกอบ
ของไฟล์ JSP ปัจจุบัน โดยใช้
<%@ include file="filename.jsp" %>
ประโยชน์ที่เห็นได้ชัดอย่างหนึ่งของการใช้
include directive คือ การง่ายต่อการเปลี่ยนแปลงและบำรุงรักษา ยกตัวอย่างเช่น
สมมุติว่าทุกหน้าของเราต้องการ
header หรือ footer ที่เหมือนกัน เราก็แค่ใช้ <%@ include file="header.jsp"
%> ใส่ลงไปในทุก ๆ JSP ไฟล์ หลังจากนั้น
ทุกครั้งที่เราต้องการเปลี่ยนแปลง header นี้ เราก็แค่เปลี่ยนไฟล์ที่ชื่อ
header.jsp
ซึ่งไฟล์ทุกไฟล์ที่ include ไฟล์นี้เข้าไป ก็จะเปลี่ยนไปด้วยโดยอัตโนมัติ
Declarations
Declarations ใช้ในการประกาศค่าตัวแปร (variable) หรือสร้างฟังก์ชั่นต่าง
ๆ
(method) เพื่อจะใช้ใน JSP page นั้น
โดยทั่วไป Declarations จะถูก initialize เมื่อ JSP page ถูก initialize
ซึ่งจะทำให้ตัวแปร หรือฟังก์ชั่นใน Declarations พร้อมใช้งานได้ทันที
ตัวอย่างเช่น
<%! int i = 0; %>
<%! public String f(int i) {
if (i<3) return "...";
...
}
%>
* Declarations
เป็นส่วนที่ถูกประมวลผลในช่วง Translation time
Expressions
โดยการใช้ expressions สิ่งต่าง ๆ ที่อยู่ใน <%= ... %> จะถูกประมวลผล
แล้วเปลี่ยนให้อยู่ในรูปของ String และส่วนที่ได้นี้จะถูกรวมเข้าไปอยู่ใน
output page
(html)
โดยตรง เช่น
<%= i %>
Container จะดึงค่า i ออกมา แล้วเปลี่ยนเป็นสตริงโดยใช้ Integer.toString(i)
<%=
"Hello" %>
Container จะนำค่า Hello ใส่เข้าไปใน output page
ข้อควรจำอย่างหนึ่งคือ
ห้ามทำการใส่ semicolon (;) ลงไปใน <%= ... %> ยกเว้นถ้า
semicolon นั้นเป็นส่วนหนึ่งของสตริง เช่น
<%= "Hello semicolon ;" %>
* Expressions
เป็นส่วนที่ถูกประมวลผลในช่วง Translation time
Code
Fragments/Scriptlets
เราสามารถใส่โค้ด หรือส่วนหนึ่งของโค้ดเข้าไปยัง JSP page ได้โดยใช้
<% ... %> โค้ดที่ใส่เข้าไปนี้จะไปอยู่ในส่วนของ service() ฟังก์ชั่นของ
Servlet ซึ่งจะถูกเรียกใช้เมื่อมี
request จาก client ยกตัวอย่างเช่น
<%
int userId = request.getParameter("userId");
if (userId == 9999) {
out.print("You are admin!!!");
} else {
out.print("You are who you are");
}
%>
บางทีเราอาจใส่เพียงส่วนหนึ่งของโค้ดเข้าไปในแต่ละ
<% ... %> ก็ได้ เช่น
<%
if (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.AM)
{ %>
Good morning
<% } else { %>
Good Afternoon
<% } %>
เหตุผลที่เราสามารถทำเช่นนี้ได้เพราะถ้าเราดู
code หลังจากการแปลงเป็น Servlet แล้ว
จะเป็นดังนี้
...
if (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.AM)
{ // by <% ... %>
out.print("Good Morning"); // plain html will be replaced
by out.print("...");
} else { // by <% ...%>
out.print("Good Afternoon"); // plain html
}
...
ซึ่งจะกลายเป็นโค้ดที่สมบูรณ์ขึ้นมา
* Code Fragments/Scriptlets เป็นส่วนที่ถูกประมวลผลในช่วง Client
request time
Comments
comments ใน JSP มีอยู่สองแบบคือ
1) comment ที่ปกติถูกใช้ใน html ไฟล์ ซึ่งจะไม่ถูก skip ไปโดย JSP
Container เมื่อไฟล์JSP
ถูกแปลงเป็น .class แล้ว (จะยังคงปรากฏที่ client side ในส่วนของ html
source code) ตัวอย่างเช่น
<!-- This is my comment -->
บางทีเราอาจเปลี่ยนแปลง
comment ที่อยู่ข้างใน <!-- ... --> ได้ โดยใช้ expression เช่น
<!-- <%= expression %> more comment -->
2) comments
ที่ผู้เขียน JSP ใช้สำหรับ comment ไฟล์ JSP ที่เขียนอยู่ ซึ่งจะถูก
skip
ไปโดย JSP Container ในช่วงของ Translation time ตัวอย่างเช่น
<%-- comment for server side only --%>
หลังจากที่ได้เรียนรู้เกี่ยวกับ
syntax ต่าง ๆ ของ JSP แล้ว เรากลับมาที่ไฟล์ accessCount.jsp กันอีกครั้ง
1: <%--
This is comment --%>
2: <%@ page info="Access Cont Sample" %>
3: <%@ page import="java.util.Date" %>
4: <HTML>
5: <HEAD><TITLE>Hello, JSP</TITLE></HEAD>
6: <BODY bgcolor="#ffffff">
7: <H1>Hello JSP</H1>
8: <BR>
9: <%! private int accessCount = 0; %>
10: <% accessCount++;
11: Date rightNow = new Date(); %>
12: Access Page: <%= accessCount %> times... at
<%= rightNow.toString() %>
13: </BODY>
14: </HTML>
line
1: เป็นลักษะของ JSP comment ที่จะถูก skip ไปโดย JSP Container
หลังจากที่ไฟล์ JSP ถูกแปลงเป็น Servlet แล้ว
line 2: ใช้ page directive เพื่อเซ็ตค่า "Access Count Sample"
ไปใส่ในฟังก์ชั่น Servlet.getServletInfo() ของไฟล์ Servlet ที่ได้จากการแปลงไฟล์
AccessCount.jsp
โดย JSP Container
line 3: เป็นการใช้ page directive เพื่อ import คลาส java.util.Date
ก่อนที่จะทำการเรียกใช้
line 4-8: เป็น HTML template ซึ่งจะถูกแปลงอยู่ในรูปของ out.print(HTML)
line 9: มีการประกาศตัวแปร private int accessCount โดยใส่เข้าไปใน
Declaration เพื่อใช้ในการนับจำนวนครั้งที่เพจนี้ถูกเรียกดู ซึ่ง accessCount
จะกลายเป็นส่วนหนึ่งของ
instance variable ของไฟล์ hellojsp1 ในเวอร์ชั่น Servlet
line 10: ทำการเซ็ต accessCount+1 ในทุก ๆ ครั้งที่เพจนี้ถูกเรียก
ซึ่งสามารถทำได้ในส่วนที่เป็น scriptlet (<% ... %>)
line 11: สร้าง object ใหม่ชื่อ rightNow ซึ่งมาจากคลาส java.util.Date
ที่เรา import มาก่อนหน้านี้ ใช้สำหรับเรียกดูวันเวลาปัจจุบัน
line 12: ใช้ Expression เพื่อแสดงค่าของ accessCount และพิมพ์ค่าของเวลาปัจจุบัน
ที่เก็บอยู่ใน rightNow ซึ่งทั้งสองค่าจะถูกแปลงออกมาอยู่ในรูปของ
String
ถ้าต้องการดูรายละเอียดเพิ่มขึ้น
จะพิจารณาประกอบกับซอร์ส accesscount_jsp_x.java ที่นำไปใช้สร้างคลาสดังข้างล่าง
package
myexam.jsp;
import
javax.servlet.*;
import
javax.servlet.http.*;
import
javax.servlet.jsp.*;
import
java.io.PrintWriter;
import
java.io.IOException;
import
java.io.FileInputStream;
import
java.io.ObjectInputStream;
import
java.util.Vector;
import
com.sun.jsp.runtime.*;
import
java.beans.*;
import
com.sun.jsp.JspException;
import
java.util.Date;
public
class accesscount_jsp_2 extends HttpJspBase {
static
char[][] _jspx_html_data = null;
// begin
[file="C:\\jswdk\\myexam\\jsp\\accesscount.jsp"; from=(1,0);to=(1,42)]
public
String getServletInfo() {
return
"an Access Count example";
}
// end
// begin
[file="C:\\jswdk\\myexam\\jsp\\accesscount.jsp"; from=(10,3);to=(10,33)]
private
int accessCount = 0;
// end
public
accesscount_jsp_2( ) {
}
private
static boolean _jspx_inited = false;
public
final void _jspx_init() throws JspException {
ObjectInputStream
oin = null;
int
numStrings = 0;
try
{
FileInputStream
fin = new FileInputStream
("work\\%3A8080%2Fmyexam\\ myexam.jspaccesscount.dat");
oin
= new ObjectInputStream(fin);
_jspx_html_data
= (char[][]) oin.readObject();
} catch
(Exception ex) {
throw
new JspException("Unable to open data file");
} finally
{
if (oin
!= null)
try
{ oin.close(); } catch (IOException ignore) { }
}
}
public
void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws
IOException, ServletException {
JspFactory
_jspxFactory = null;
PageContext
pageContext = null;
HttpSession
session = null;
ServletContext
application = null;
ServletConfig
config = null;
JspWriter
out = null;
Object
page = this;
String
_value = null;
try
{
if (_jspx_inited
== false) {
_jspx_init();
_jspx_inited
= true;
}
_jspxFactory
= JspFactory.getDefaultFactory();
response.setContentType("text/html");
pageContext
= _jspxFactory.getPageContext(this, request, response,
"",
true, 8192, true);
application
= pageContext.getServletContext();
config
= pageContext.getServletConfig();
session
= pageContext.getSession();
out
= pageContext.getOut();
out.print(_jspx_html_data[0]);
out.print(_jspx_html_data[1]);
out.print(_jspx_html_data[2]);
out.print(_jspx_html_data[3]);
out.print(_jspx_html_data[4]);
// begin
[file="C:\\jswdk\\myexam\\jsp\\accesscount.jsp"; from=(12,2);to=(13,32)]
accessCount++;
Date
rightNow = new Date();
// end
out.print(_jspx_html_data[5]);
// begin
[file="C:\\jswdk\\myexam\\jsp\\accesscount.jsp"; from=(15,16);to=(15,29)]
out.print(
accessCount );
// end
out.print(_jspx_html_data[6]);
// begin
[file="C:\\jswdk\\myexam\\jsp\\accesscount.jsp"; from=(15,47);to=(15,68)]
out.print(
rightNow.toString() );
// end
out.print(_jspx_html_data[7]);
} catch
(Throwable t) {
if (out.getBufferSize()
!= 0)
out.clear();
throw
new JspException("Unknown exception: ", t);
} finally
{
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
}
}
Packages
และโครงสร้างการทำงานใน JSP
|