By Scott Ferguson Blueski編譯
目錄如下: 1 引論 2 范例的框架: Hello, World 3 Servlet 評(píng)論 4 展示留言本 5 留言本的模式 6 作為應(yīng)用屬性的留言本 7 留言本的邏輯 8 結(jié)論
1 引論
JSP的強(qiáng)大優(yōu)勢在于把一種應(yīng)用的商務(wù)邏輯和它的介紹分離開來。用 Smalltalk的面向?qū)ο蟮男g(shù)語來說, JSP鼓勵(lì)MVC(model-view-controller)的web應(yīng)用。JSP的classes 或 beans 是模型, JSP 是這個(gè)視圖, 而Servlet是控制器。
這個(gè)例子是一個(gè)簡單的留言本,包括用戶登錄和留言。它被作為Resin平臺(tái)的示范: --執(zhí)行角色 --模型 A 留言本 --用于新用戶的login.jsp --用于已注冊(cè)用戶的add.jsp --控制器 GuestJsp, 一個(gè)用來管理狀態(tài)的servlet
2 樣板的框架: Hello, World
GuestJsp servlet的框架把 "Hello, World" 這個(gè)字符串傳給login.jsp頁面。這個(gè)框架為留言本設(shè)立結(jié)構(gòu)。具體細(xì)節(jié)將在下面補(bǔ)充。
這個(gè)例子被編譯后可以瀏覽到:
http://localhost:8080/servlet/jsp.GuestJsp
你可以看到頁面上有這樣的顯示: Hello, world
JSP模板是以Servlet的處理開始然后把處理結(jié)果傳給JSP頁進(jìn)行格式化。
以下使用了一個(gè)Servlet2.1 ServletContext的特性 getRequestDispatcher()。 請(qǐng)求的調(diào)度器在服務(wù)器上讓servlets直接向前傳送并包括了任何可能的子請(qǐng)求。對(duì)SSI包含來說這是一個(gè)更靈活的取代做法。 在servlet文件中請(qǐng)求的調(diào)度器可以包含任何頁面,servlet,或JSP的結(jié)果。 GuestJsp將使用dispatcher.forward()來將控制傳給JSP頁進(jìn)行格式化。
GuestJsp.java: Skeleton package jsp.GuestJsp;
import java.io.*; import java.util.*;
import javax.servlet.*; import javax.servlet.http.*;
/** * GuestJsp is a servlet controlling user * interaction with the guest book. */ public class GuestJsp extends HttpServlet { /** * doGet handles GET requests */ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Save the message in the request for login.jsp req.setAttribute("message", "Hello, world");
// get the application object ServletContext app = getServletContext();
// select login.jsp as the template RequestDispatcher disp; disp = app.getRequestDispatcher("login.jsp");
// forward the request to the template disp.forward(req, res); } }
servlet和jsp頁使用HttpRequest對(duì)象中的屬性進(jìn)行通信。skeleton在"message"屬性中保存了"Hello, World"。 當(dāng)login.jsp啟動(dòng)時(shí),它將捕捉到該字符串并將其打印出來。
由于Resin的JavaScript能夠讀取擴(kuò)充的Bean模型,它可以將request.getAttribute("message")轉(zhuǎn)換成為 JavaScript的對(duì)應(yīng)物 request.attribute.message。
login.jsp: Skeleton <%@ page language=javascript %>
<head> <title><%= request.attribute.message %></title> </head>
<body bgcolor='white'> <h1><%= request.attribute.message %></h1> </body>
3 Servlet的復(fù)習(xí)
對(duì)于來自于ASP或CGI背景并轉(zhuǎn)向jsp的人來說, Servlets代替CGI腳本體現(xiàn)了Java在動(dòng)態(tài)類加載方面的優(yōu)勢。servlet就是一個(gè)Java類, 它對(duì)Servlet或HttpServlet進(jìn)行了擴(kuò)展并放置到適當(dāng)?shù)穆窂街小esin將自動(dòng)加載servlet并執(zhí)行它。
url /servlet/classname將request提交給Servlet請(qǐng)求器。請(qǐng)求器會(huì)從doc/WEB-INF/classes自動(dòng)加載Java類的類名 并試圖執(zhí)行Servlet的service方法。
Resin將定期檢查類文件以判斷是否被修改過。如果被修改過,則將用新的servlet取代舊的。
4 顯示留言本
在基本框架已經(jīng)運(yùn)行后, 下一步是創(chuàng)建model。
5 留言本模型
留言本是很直接的,這里知識(shí)包含了一下API。它遵從Bean模型以簡化JavaScript。 同樣的API可以工作于HashMap, 基于文件,以及數(shù)據(jù)庫應(yīng)用。
JSP文件只能存取public方法。所以JSP文件無法創(chuàng)建一個(gè)新的留言本或者增加一個(gè)新用戶。 這是GuestJsp servlet的責(zé)任。
jsp.Guest.java API package jsp;
public class Guest { Guest(); public String getName(); public String getComment(); }
Resin的JavaScript能讀取Bean模型。所以使用JavaScript的JSP頁面可以存取getName()和getComment() 作為屬性。例如,你可以簡化使用guest.name和guest.comment。
jsp.GuestBook.java API package jsp;
public class GuestBook { GuestBook(); void addGuest(String name, String comment); public Iterator iterator(); }
Resin的JavaScript同樣可以讀取iterator()調(diào)用,所以你可以使用JavaScript用于 ... 任何一個(gè)來取得用戶:
for (var guest in guestBook) { ... }
GuestBook作為application屬性 為了使得例子保持簡單,GuestJsp在application (ServletContext)中存取GuestBook。作為例子, 在application中保存數(shù)據(jù)是可以接受的,但對(duì)于完全成熟的應(yīng)用,最好僅使用application將數(shù)據(jù)放到其它地方。
jsp.GuestJsp.java // get the application object ServletContext app = getServletContext();
GuestBook guestBook;
// The guestBook is stored in the application synchronized (app) { guestBook = (GuestBook) app.getAttribute("guest_book");
// If it doesn't exist, create it. if (guestBook == null) { guestBook = new GuestBook(); guestBook.addGuest("Harry Potter", "Griffindor rules"); guestBook.addGuest("Draco Malfoy", "Slytherin rules"); app.setAttribute("guest_book", guestBook); } }
RequestDispatcher disp; disp = app.getRequestDispatcher("login.jsp");
// synchronize the Application so the JSP file // doesn't need to worry about threading synchronized (app) { disp.forward(req, res); }
JSP文件本身是簡單的。它從application獲取留言本并在表中顯示內(nèi)容。通常, application對(duì)象需要同步,因?yàn)橐恍┛蛻舳丝赡芡瑫r(shí)瀏同一頁面。 GuestJsp在jsp文件被調(diào)用之前小心處理了同步情況。
login.jsp: Display Guest Book <%@ page language=javascript %>
<head> <title>Hogwarts Guest Book</title> </head>
<body bgcolor='white'>
<h1>Hogwarts Guest Book</h1> <table> <tr><td width='25%'><em>Name</em><td><em>Comment</em> <% var guestBook = application.attribute.guest_book
for (var guest in guestBook) { out.writeln("<tr><td>" + guest.name + "<td>" + guest.comment); } %>
</body>
Hogwarts Guest Book Name Comment Harry Potter Griffindor Rules Draco Malfoy Slytherin Rules
6 留言本的規(guī)則(logic)--作為應(yīng)用屬性的留言本
留言本的規(guī)則是很簡單的。如果用戶沒有登錄,他會(huì)看到一個(gè)提示和登錄表。 登錄后他會(huì)看到提示并在一個(gè)表中加入留言。 login.jsp給出了登錄的頁面,add.jsp給出了 增加流言的頁面。
GuestJsp在session變量中保存了規(guī)則信息。
執(zhí)行'login'來登錄或 'add'來增加留言。 其中 name: 用戶名 password: 口令 comment:留言
7 留言本規(guī)則 ...
// name from the session String sessionName = session.getValue("name");
// action from the forms String action = request.getParameter("action");
// name from the login.jsp form String userName = request.getParameter("name");
// password from the login.jsp form String password = request.getParameter("password");
// comment from the add.jsp form String comment = request.getParameter("comment");
// login stores the user in the session if (action != null && action.equals("login") && userName != null && password != null && password.equals("quidditch")) { session.putValue("name", userName); }
// adds a new guest if (action != null && action.equals("add") && sessionName != null && comment != null) { guestBook.addGuest(sessionName, comment); }
String template; // if not logged in, use login.jsp if (session.getValue("name") == null) template = "login.jsp"; // if logged in, use add.jsp else template = "add.jsp";
RequestDispatcher disp; disp = app.getRequestDispatcher(template);
...
login.jsp和add.jsp僅加上了不同forms在前一個(gè)section中顯示代碼。
login.jsp <%@ page language=javascript %> <head> <title>Hogwarts Guest Book: Login</title> </head> <body bgcolor='white'>
<h1>Hogwarts Guest Book</h1> <table> <tr><td width='25%'><em>Name</em><td><em>Comment</em> <% var guestBook = application.attribute.guest_book
for (var guest in guestBook) { out.writeln("<tr><td>" + guest.name + "<td>" + guest.comment); } %>
<hr>
<form action='GuestJsp' method='post'> <input type=hidden name='action' value='login'> <table> <tr><td>Name:<td><input name='Name'> <tr><td>Password:<td><input name='Password' type='password'> <tr><td><input type=submit value='Login'>
</form> </body>
8 結(jié)論
Resin示例演示了擴(kuò)充留言本的一些方法,包括加入一些智能的東西用于form處理。然而,由于forms取得更多的只能,即使是JSP模板也變得復(fù)雜化了。 有一個(gè)結(jié)論:XTP模板。
|