2009年3月11日
ant-1.63.jar http://ant.apache.org/ Ant 的核心包,在構建Hibernate 時會用到
antlr-2.7.5H3.jar http://www.antlr.org/ 語言轉換工,Hibernate利用它實現 HQL 到 SQL的轉換
asm.jar/asm-attrs.jar http://asm.objectweb.org/ ASM 字節轉換庫
c3p0-0.8.5.2.jar http://sourceforge.net/projects/c3p0 C3PO JDBC 連接池工具
cglib-2.1.jar http://cglib.sourceforge.net/ 高效的代碼生成工具, Hibernate用它在運行時擴展 Java類和實現 Java 接口
commons-collections-2.1.1.jar http://jakarta.apache.org/commons/collections Apache 的工具集,用來增強Java對集合的處理能力
commons-logging-1.0.4.jar http://jakarta.apache.org/commons/logging/ Apache 軟件基我組所提供的日志工具
concurrent-1.3.2.jar http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html 線程同步工具,在使用JBoss 的樹狀緩存時需要用到
connector.jar http://java.sun.com/j2ee/connector/ 用連接多個應用服務器的標準連接器
dom4j-1.6.jar http://dom4.j.org/ dom4j XML 解析器
ehcache-1.1.jar http://sourceforge.net/projects/echache 緩存工具.在沒有提供其他緩存工具時,這個緩存工具是必不可少的
jaas.jar http://java.sun.com/products/jass/ 標準的 Java 權限和認證服務包
jaxen-1.1-beta-4.jar http:jaxen.org/ 通用的 XPath 處理引 擎
jboss-cache.jar http://www.jboss.com/products/jbosscache JBoss 的一種樹狀緩存實現工具
jboss-common.jar http://jboss.org/ Jboss 的基礎包,在使用 JBoss 的樹狀緩存時必須有此包
jboss-jmx.jar http://jboss.org/ JBoss 的 JMX 實現包
jboss-system.jar http://jboss.org/ JBoss 的核心,包括服務器和部署引擎
jdbc2_0-stdext.jar http://java.sun.com/products/jdbc/download.html#spec 標準的 JDBC 2.0 擴展API
jgroups2.2.7.jar http://www.jgroups.org/ 網絡通信工具包
jta.jar http://java.sun.com/products/jta 標準的 JAVA 事務處理接口
junit-3.8.1.jar http://www.junit.org/ JUnit 測試框架
log4.j-1.2.9.jar http://logging.apache.org/log4j/ log4j 庫,Apache 的日志工具
oscache-2.1.jar http://www.opensymphony.com/oscache/ Java 對象的緩存工具
proxool-0.8.3.jar http://proxool.sourceforge.net/ Proxool JDBC 連接池 工具
swarmcache-1.0rc2.jar http://swarmcache.sourceforge.net/ Hibernate 可以使用的一種緩存工具
versioncheck.jar 版本檢查工具包,用于在構建 Hibernate 的時候檢查輔助 jar 包文件的版本
xerces-2.6.2.jar http://xml.apache.org/xerces2-j/ SAX XML 解析器
xml-apis.jar http://xml.apache.org/xerces2-j/ Java語言中標準的XML 解析器
Action類的工作機制
所有的Action類是org.apache.struts.action.Action的子類。Action子類應該覆蓋父類的execute方法。當ActionForm Bean被創建,并且表單驗證順利通過后,Struts框架就會調用Action類的execute()方法。execute()方法如下定義:
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)throws IOException,ServletException
execute()方法包含以下參數:
ActionMapping:包含了這個Action的配置信息,和struts-config.xml文件中的<action>元素對應。
ActionForm:包含了用戶的表單數據,當Struts框架調用execute()方法時,ActionForm中的數據已經通過了表單驗證。
HttpServletRequest:當前的HTTP請求對象。
HttpServletResponse:當前的HTTP響應對象。
訪問封裝在MessageResources中的本地化文本
Action類的execute()方法首先獲得MessageResources對象:
MessageResources messages=getResources(request);
在Action類中定義了getResources(HttpServletRequest request)方法,該方法返回當前默認的MessageResources對象,它封裝了Resource Bundle中的文本內容。接下來Action類就可以通過MessageResources對象來訪問文本內容。例如,如果要讀取消息KEY為“hello.jsp.title”對應的文本內容,可以調用MessageResources類的getMessage(String key)方法:
String title=messages.getMessage("hello.jsp.title");
業務邏輯驗證
ActionMessages errors=new ActionMessages();
String userName=(String)((HelloForm)form).getUserName();
String badUserName="Monster";
if(userName.equalsIgnoreCase(badUserName))
{
errors.add("username",new ActionMessage("hello.dont.talk.to.monster",badUserName));
saveErrors(request,errors);
return(new ActionForward(mapping.getInput()));
}
如果用戶輸入的姓名“Monster”,將創建包含錯誤信息的ActionMessage對象,ActionMessage對象被保存島ActionMessages對象中。接下來調用在Action基類中定義的saveErrors()方法,它負責把ActionMessages對象保存島request范圍內。最后返回ActionForward對象,Struts框架會根據ActionForward對象包含的轉發信息把請求轉發島恰當的視圖組件,視圖組件通過<html:errors>標簽把request范圍內的ActionMessage對象中包含的錯誤消息顯示出來,提示用戶修改錯誤。
幾乎所有和用戶交互的應用都需要數據驗證,而從頭設計并開發完善的數據驗證機制往往很費時。幸運的是,Struts框架提供了現成的、易于使用的數據驗證功能。Struts框架的數據驗證可分為兩種類型:表單驗證和業務邏輯驗證,在本例中,它們分別運用于以下場合:
表單驗證:如果用戶沒有在表單中輸入姓名就提交表單,將生成表單驗證錯誤。
業務邏輯驗證:如果用戶在表單中輸入姓名為“Monster”,按照本應用的業務規則,則不允許向“Monster”打招呼,因此將生成業務邏輯錯誤。
第一種類型的驗證,即表單驗證由Action Bean來負責處理。
這個工作可以用以上的HelloForm.java的validate()方法負責完成這一任務:
public ActionErrors validate(ActionMapping mapping,HttpServletRequest request)
{
ActionErrors errors=new ActionErrors();
if((userName==null)||(userName.length())<1)
error.add("username",new ActionMessage("hello.no.username.error"));
return errors;
}
第二種類型的驗證,即業務邏輯驗證由Action來負責處理。
例:
package hello;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet.ServeltException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResource;
public final class HelloAction extends Action
{
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)throws Exception
{
MessageResources message=getResources(request);
Action Messages errors=new ActionMessages();
String userName=(String)((HelloForm)form).getUserName();
//ActionMessages errors=new ActionMessage();
//String userName=(String)((HelloForm)form).getUserName();
String badUserName="Monster";
if(userName.equalslgnoreCase(badUserName))
{
errors.add("username",new ActionMessage("hello.dont.talk.to.monster",badUserName));
saveErrors(request,errors);
}
return (new ActionForward(mapping.getInput()));
}
PersonBean pd=new PersonBean();
pd.setUserName(userName);
pd.saveToPersistentStore();
request.setAttribute(Constants.PERSON_KEY,pd);
request.removeAttribute(mapping.getAttribute());
return(mapping.findForward("SayHello"));
}
}
創建ActionForm Bean
當用戶提交HTML表單后,Struts框架將自動把表單數據組裝到ActionForm Bean中。ActionForm Bean 中的屬性和HTML表單中的字段一一對應。ActionForm Bean還提供數據驗證方法,以及把屬性重新設置為默認值的方法。Struts框架中定義的ActionFrom類是抽象的,必須在應用中創建它的子類,來存放具體的HTML表單數據。
package hello;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public final class HelloForm extends ActionForm
{
private String userName=null;
public String getUserName(){
return(this.userName);
}
public void setUserName(String userName)
{
this.userName=userName;
}
public void reset(ActionMapping mapping,HttpServletRequest request)
{
this.userName=null;
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request)
{
ActionErrors errors=new ActionErrors();
if((userName==null)||(userName.length()<1))
errors.add("username",new ActionMessage("hello.no.username.error"));
return errors;
}
}
ActionForm Bean 實質上是一種JavaBean,不過它除了具有JavaBean的常規方法,還有兩種特殊方法:
validate():用于表單驗證。
reset:把屬性重新設置為默認值。
hello.jsp使用<bean:message>標簽來輸出文本內容。這些文件來自于Resource Bundle,每個Resource Bundle 都對應一個或多個本地化的消息資源文件。資源文件為
application.properties:
#SDFSALKFJSLAKFLAK
//#為資源文件的注釋
hello.jsp.title=Hello-A first Struts program
對于JSP代碼:
<bean:message key="hello.jsp.title"/>
<bea:message>標簽的key屬性為“hello.jsp.title”,Resource Bundle中與匹配的內容為:
hello.jsp.title=Hello-A first Struts program
因此,以上<bean:message>標簽將把“Hello-A first Struts program”輸出島網頁上。
ActionServlet接收到一個客戶請求時,將執行如下流程。
1、檢索和用戶請求匹配的ActionMapping實例,如果不存在,就返回用戶請求路徑無效的信息。
2、如果ActionForm實例不存在,就創建一個ActionForm對象,把客戶提交的表單數據保存島ActionForm對象中。
3、根據配置信息決定是否需要表單驗證,如果需要驗證,就調用ActionForm的validate()方法。
4、如果AcctionForm的validate()方法返回null或返回一個不包含ActionMessage的ActionErrors對象,就表示表單驗證成功。
5、ActionServlet 根據ActionMapping實例包含的映射信息決定將請求轉發給哪個Action。如果相應的Action實例不存在,就先創建這個實例,然后用Action的execute()方法。
6、Action的execute()方法返回一個ActionForward對象,ActionServlet再把客戶請求轉發給ActionForward對象指向的JSP組件。
7、ActionForward對象指向的JSP組件生成動態網頁,返回給客戶。
對于以上流程的流程4,如果ActionForm的validate()方法返回一個包含一個或多個ActionMessage的ActionErrors對象,就表示表單失敗,此時ActionServlet將直接把請求轉發給包含用戶提交表單的JSP組件。在這種情況下,不會再創建Action對象并調用Action的execute()方法。
HttpServletRequest:Servlet容器把HTTP請求信息保存在HttpServletRequest對象中,Servlet組件從request對象中讀取用戶的請求數據。此外,HttpServletRequest可以存放request范圍內的共享數據。
HttpServletResponse:用于生成HTTP響應結果。
HttpSession:Servlet容器為每個WEB應用創建一個ServletContext實例,ServletContext可以存放application范圍的共享數據。
HttpServletRequest、HttpSession、ServletContext分別提供在request、session、application范圍內保存和讀取共享數據的方法:
//save shared data
setAttribute(String key,Object value);
//get shared data
getAttribute(String key);
在保存共享數據時,應該指定屬性KEY。在讀取共享數據時,將根據這個屬性KEY來檢索共享數據。
例:
把ShoppingCart對象(購物車)存放在session范圍內,存放時指定屬性KEY衛“cart”,然后再通過這個屬性KEY把ShoppingCart對象檢索出來:
ShoppingCart shoppingCart=new ShoppingCart();
ShoopingCart myCart=null;
//sava cart
session.setAttribute("cart",shoppingCart);
//get cart
myCart=(ShoppingCart)session.getAttribute("cart");
請求轉發:
Servlet的service()方法中執行以下代碼:
RequestDispatcher rd=request.getRequestDispatcher("hello.jsp");
//Forward to requested URL
rd.forward(request,response);
在JSP頁面中,可以使用<jsp:forward>標簽來轉發請求
例如:
<jsp:forward page="hello.jsp"/>
請求重定向:
WEB組件可以將請求重定向到任意URL,而不僅僅是同一應用中的URL。
重定向的源組件和目標組件之間不共用同一個HttpServletRequest對象,因此不能共享request范圍內的共享數據。
response.sendRedirect("http://jakarta.apache.org/struts/");
包含:
Servlet類使用javax.servlet.RequestDispatcher.include()
RequsetDispatcher rd;
rd=req.getRequestDispatcher("/header.jsp");
在JSP文件中,可以通過<include>指令來包含其他的WEB資源,
<%@ include file="header.jsp"%>
Servlet持久化
Servlet容器在某些情況下把這些HttpSession對象從內存中轉移到文件系統或數據庫中。
在訪問HTTPSESSION信息時再把他們加載到內存中。
好處:
1、假如有一萬個人同時在訪問某個WEB應用,SERVLET容器中會生成一萬個HTTPSESSION對象。如果吧這些對象都一直存放在內存中,將消耗大量的內存資源。顯然不可取,因此可
以把處于不活動狀態的HTTPSESSION對象轉移到文件系統或數據庫中,這樣可以提高對內存。資源的利用率。
2、假定某個客戶正在一個購物網站上購物,它將購買的物品先放在虛擬的購物車HTTPSESSION對象中。如果此時WEB服務器突然出現故障而終止,那么內存中的HTTPSESSION對象聯
通客戶的購物信息都會丟失。如果吧HTTPSESSION對象實現保存在文件系統或數據庫中,當WEB服務器重啟后,還可以從文件系統或數據庫中恢復SESSION數據
比如:在網上書店應用中,從一個客戶開始購物,到最后結賬,整個過程是一個Session.
Servlet API中定義了javax.servlet.http.HttpSession接口,Servlet容器必須實現這一接口。當一個Session開始時,Servlet容器將創建一個HttpSession對象,在HttpSession對象中可以存放客戶狀態的信息。Servelt容器為HttpSession分配一個唯一標識符,稱為Session ID.Servlet容器把Session ID作為Cookie保存在客戶的瀏覽器中。每次客戶發出HTTP請求時,Servlet容器可以從HttpRequest對象中讀取Session ID,然后根據SessionID找到相應的HttpSession對象,從而獲取客戶的狀態信息。
HttpSession接口中的方法:
getId():返回Session的ID;
invalidate():使當前的Session失效,Servlet容器會釋放HttpSession對象占用的資源。
setAttribute(String name,Object value):將一對name/Value屬性保存在HttpSession對象中
getAttribut(String name):根據name參數返回保存在HttpSession對象的屬性值。
getAttributeNames():以數組的方式HttpSession對象中所有的屬性名。
isNew():判斷是否是新創建的Session,如果是新創建的Session,返回true,否則返回false
setMaxInactiveInterval():設定一個Session可以處于不活動狀態的最大時間間隔,以秒為單位。如果超過這個時間。Session自動失效,如果設置為負數,表示不限制Session付出與不活動狀態的時間。
getMaxInactiveInterval()讀取當前Sessions可以處于不活動狀態的最大時間間隔。
在Java Servlet API中提出了跟蹤Session的另一種機制,如果客戶瀏覽器不支持Cookie,Servlet容器可以重寫客戶請求的URL,吧Session ID添加到URL信息中。
HttpServletResponse接口提供了重寫URL的方法:
public java.lang.String encodeURL(java.lang.String url)
該方法的實現機制為:
先判斷當前的Web組件是否啟用Session,如果沒有啟用Session,例如在JSP中聲明
<%@ page session="false"%>或者已經執行了session.invalidate()方法,那么直接返回參數URL
再判斷客戶瀏覽器是否支持Cookie,如果支持Cookie,就直接返回參數URL;如果不支持,就在參數URL中加入Session ID信息,然后返回修改后的URL.
轉發JSP請求
<jsp:forward>用于將客戶請求重定向到其他的HTML文件、JSP文件或者Servlet文件。
<jsp:forward>語法:
<jsp:forward page="重定向的文件"/>
<jsp:forward>標簽從一個JSP文件向另一個文件傳遞包含用戶請求的request對象。
如果使用了這個標簽,那么這個JSP文件中的所有輸出數據都不會被發送到客戶端,并且這個標簽以下的代碼不會被執行。
Cookie包含一對Key/Value
生成一個Cookie并將它寫到用戶硬盤上的語法:
Cookie theCookie=new Cookie("cookieName","cookieValue");
response.addCookie(the Cookie);
如果服務器想從用戶硬盤上獲取Cookie,可以用
Cookie cookies[]=request.getCookies();
獲取所有Cookie
然后調用Cookie的getName方法獲取Cookie的Key,調用Cookie的getValue方法獲取Cookie的Value
通過Cookie的setMaxAge(int expiry)方法設置Cookie的有效期。超過參數expity指定的時間(以秒為單位),Cookie就會失效。
例子:
<html>
<head><title>jspCookie.jsp</title></head>
<body>
<%
Cookie[] cookies=request.getCookies();
//System.out.println("dsfasfdafda");
for(int i=0;i<cookies.length;i++)
{
%>
<p>
<b>Cookie name:</b>
<%=cookies[i].getName()%>
<b>Cookie value:</b>
<%=cookies[i].getValue()%>
</p>
<p>
<b>Old max age in seconds:</b>
<%=cookies[i].getMaxAge()%>
<%
cookies[i].setMaxAge(60);
%>
<b>New max age in seconds:</b>
<%=cookies[i].getMaxAge()%>
<%
}
%>
<%!
int count1=0;
int count2=0;
%>
<%
response.addCookie(new Cookie("cookieName"+count1++,"cookieValue"+count2++));
%>
</body>
</html>
JSP聲明用于聲明JSP代表的Servlet類的成員變量和方法。
語法<%! %>
例如:
<%! int i=0;%>
也可聲明函數:
<!
public String f(int i)
{
if(i<3) return "i<3";
else return "i>=3";
}
>
每個聲明只在當前JSP頁面中有效,如果希望每個JSP頁面中都包含這些聲明,可以把他們寫成單獨的頁面,然后用<%@include%>指令把這個夜明加到其他頁面中。
JAVA程序片段:
JSP文件中,可以在<%和%>標記間直接嵌入任何有效的JAVA語言代碼。這樣嵌入的程序片段稱為Scriptlet。如果在page指令中沒有指定method屬性,則生成代碼默認service方法的主體。
JSP指令用來設置和整個JSP網頁相關屬性,如網頁的編碼方式和腳本語言等。
語法:
<%@ 指令名 屬性=“值”%>
常見的3中指令:
page:可以指定所使用的腳本語言、JSP代表的Servlet實現的接口、Servlet擴展的類以及導入的軟件包。
語法:
<%@ page 屬性1=“值1” 屬性2=“值2”%>
例:
<%@ page import="java.util.*" contentType="type/html;charset=GB2312" language="java"%>
page指令的屬性描述:
language:指定文件中所使用的腳本語言目前僅JAVA為有效值和默認值。用作整個文件。
語法:<%@ page language="java"%>
method:指定JAVA程序片段所屬的方法的名稱。JAVA程序片段會成為制動方法的主體。默認的方法是service方法。當多次使用該指令時,只有第一次范圍是有效的,該方法有效值
包括:service、doGet和doPost等。
語法:<%@ page method="doPost"%>
import:指定導入的JAVA軟件包名或類別列表。
語法:<%@page import="java.io.*,java.util.Hashtable"%>
content_type:指定響應結果的MIME類型,默認MIME類型是text/html。默認字符編碼為ISO-8859-1。
語法:<%@ page content_type="text/html;charset=GB2312"%>
session="true|false"
指定JSP頁是否使用Session。默認為TRUE
語法:<%@ page session="true"%>
errorPage="error_url"指定當發生異常時,客戶請求被重新定向到那個網頁。
語法:
<%@page errorPage="errorpage.jsp"%>
isErrorPage="true|false":表示此JSP網頁是否為處理異常的網頁。
語法:<%@ page isErrorPage="true"%>
include:JSP可以通過include指令來包含其他文件。被調用的可以是JSP文件、HTML文件或文本文件。
語法:<%@inclue file="relativeURL"%>
開發網站時,如果多數JSP網頁都含有相同的內容,可以把這部分相同的內容單獨放到一個文件中,其他的JSP文件通過include指令將這個文件包含進來,這樣做可以提高開發網站的效率,而且便于維護網頁。
taglib:自定義JSP標簽
Servlet容器在啟動時會加載Web應用,并為每個WEB應用創建唯一的ServletContext對象。可以把ServletContext看成是一個WEB應用的服務器端組件的共享內存。在ServletContext中可以存放共享數據,它提供了4個讀取或設置共享數據的方法:
setAttribute(String name,Object object):把一個對象和一個屬性名綁定。將這個對象存儲在ServletContext中。
getAttribute(String name):根據給定的屬性名返回所綁定的對象;
removeAttribute(String name):根據給定的屬性名從ServletContext中刪除相應的屬性。
getAttribateNames():返回一個Enumeration對象。它包含了存儲在ServletContext對象中的所有屬性名。
package mypack;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletContext extends HttpServlet {
/**
* Constructor of the object.
*/
private static final String CONTEXT_TYPE = "text/html";
private Object Integer;
public ServletContext() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// response.setContentType("text/html");
// PrintWriter out = response.getWriter();
doPost(request, response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 獲得Context的引用
ServletContext context = (ServletContext) getServletContext();
//response.setContentType("text/html");
PrintWriter out = response.getWriter();
Integer count = (Integer) context.getAttribute("count");
if (count == null) {
count=new Integer(0);
context.setAttribute("count",new Integer(0));
}
response.setContentType(CONTEXT_TYPE);
out.print("<html><head><title>");
out.print(CONTEXT_TYPE+"</title></head><body>");
out.print("<p>This count is:"+count+"</p>");
out.print("</body>");
count=new Integer(count.intValue()+1);
context.setAttribute("count",count);
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException
* if an error occurs
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
// Put your code here
}
}