Windows2003
jdk
Eclipse3.1+MyEclipse4.03
做一登錄練習。
現已經完成了login的struts部份,實現了動態ActionForm和動態validator驗證,詳細全部文件內容如下:
struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<data-sources />
<form-beans >
<form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="password" type="java.lang.String" />
<form-property name="username" type="java.lang.String" />
</form-bean>
</form-beans>
<global-exceptions />
<global-forwards >
<forward name="indexGo" path="/index.jsp" />
</global-forwards>
<action-mappings >
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="com.test.struts.action.LoginAction" />
</action-mappings>
<message-resources parameter="com.test.struts.ApplicationResources" />
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>
</struts-config>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<html>
<head>
<title>JSP for loginForm form</title>
</head>
<body>
<html:form action="/login">
username : <html:text property="username"/><html:errors property="username"/><br/>
password : <html:password property="password"/><html:errors property="password"/><br/>
<html:submit/><html:cancel/>
</html:form>
</body>
</html>
index.jsp
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<a href="login.jsp">Login</a>
</body>
</html>
LoginAction.java
//Created by MyEclipse Struts
// XSL source (default): platform:/plugin/com.genuitec.eclipse.cross.easystruts.eclipse_
package com.test.struts.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.validator.DynaValidatorForm;
/**
* MyEclipse Struts
* Creation date: 10-27-2005
*
* XDoclet definition:
* @struts.action path="/login" name="loginForm" input="login.jsp" scope="request" validate="true"
*/
public class LoginAction extends Action {
// --------------------------------------------------------- Instance Variables
// --------------------------------------------------------- Methods
/**
* Method execute
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
DynaValidatorForm loginForm = (DynaValidatorForm) form;
// TODO Auto-generated method stub
String username=(String)loginForm.get("username");
String password=(String)loginForm.get("password");
loginForm.set("password",null);
if(username.equals("sonic")||password.equals("sonic")){
System.out.println("AAA");
return mapping.findForward("indexGo");
}
else {
System.out.println("BBB");
return mapping.getInputForward();
}
}
}
ApplicationResources.properties
prompt.username=User Name
prompt.password=User Password
errors.required={0} is required.
ApplicationResources_zh_CN.properties
prompt.username=用戶名稱
prompt.password=登錄密碼
errors.required={0} 是必須的.
validation.xml
<form-validation>
<formset>
<form name="loginForm">
<field property="username" depends="required">
<arg0 key="prompt.username" />
</field>
<field property="password" depends="required">
<arg0 key="prompt.password" />
</field>
</form>
</formset>
</form-validation>
到此已經完成了全部代碼!
配置struts-config.xml文件,添加(spring)的插件
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" />
</plug-in>
修改LoginAction配置
原:
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="com.test.struts.action.LoginAction" />
</action-mappings>
改為:
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="org.springframework.web.struts.DelegatingActionProxy" />
</action-mappings>
綠色字體部份為修改內容
這里將使用spring的代理器來對Action進行控制
當提交到/login.do是將控制權交給了spring,然后由spring來決定是否轉回到struts的Action
現在來配置spring
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="/login" class="net.xiaxin.action.LoginAction" singleton="false"></bean>
</beans>
綠色字體是關于轉交控制權的配置內容
屬性singleton="false",指明了Action 的實例獲取方式為每次重新創建。解決了Struts中令人詬病的線程安全問題(Struts中,由一個Action實例處理所有的請求,這就導致了類公用資源在并發請求中的線程同步問題。)(摘自spring開發指南)
建立數據庫在 這里我使用的是mysql
CREATE TABLE `user` (
`ID` int(11) NOT NULL auto_increment,
`USERNAME` varchar(50) NOT NULL default '',
`PASSWORD` varchar(50) NOT NULL default '',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
創建Hibernate框架
使用MyEclipse的數據Database Explorer工具創建User.hmb.xml、AbstractUser.java、User.java映射文件
創建完成后可以將自動生成的hibernate.cfg.xml刪除
創建UserDAO.java、UserDAOImp.java
修改LoginAction.java文件,使用userDao的方法來進行用戶驗證
package com.test.struts.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.validator.DynaValidatorForm;
import com.test.UserDAO;
public class LoginAction extends Action {
private UserDAO userDAO;
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
DynaValidatorForm loginForm = (DynaValidatorForm) form;
// TODO Auto-generated method stub
String username = (String) loginForm.get("username");
String password = (String) loginForm.get("password");
loginForm.set("password", null);
if (userDAO.isValidUser(username,password)) {
return mapping.findForward("indexGo");
} else {
return mapping.getInputForward();
}
}
}
綠色字體為修改部份
現在剩下最后的spring配置了
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/test</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>com\test\Hibernate\User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="userDAO" class="com.test.UserDAOImp">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="userDAO" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean name="/login" class="com.test.struts.action.LoginAction" singleton="false">
<property name="userDAO">
<ref bean="userDAOProxy" />
</property>
</bean>
</beans>
現在可以進行測試了!
看了Rod的介紹Spring的文章,翻譯后的連接:
http://blog.csdn.net/taowen2002/archive/2004/05/07/15875.aspx
一,Spring簡介
Spring的特點:
1, Spring不同于其他的Framework,它要提供的是一種管理你的業務對象的方法。
2, Spring有分層的體系結構,意味著你能選擇僅僅使用它的任何一個獨立的部分,而其他的仍然使用你的相關實現。
3, 它的設計從一開始就是要幫助你編寫易于測試的代碼,Spring是使用測試驅動開發(TDD)的工程的理想框架。
4, Spring不會給你的工程添加對其他的框架依賴;同時Spring又可以稱得上是個一攬子解決方案,提供了一個典型應用所需要的大部分基礎架構。
Spring的好處:
1, Spring能有效地組織你的中間層對象;(*)
2, Spring能消除在許多工程中常見的對Singleton的過多使用;
3, 通過一種在不同應用程序和項目間一致的方法來處理配置文件,消除各種自定義格式的屬性文件的需要,僅僅需要看看類的JavaBean屬性。Inversion of Control的使用幫助完成了這種簡化;(使用的是type2的IoC)
4, 能夠很容易培養你面向接口而不是面向類的編程習慣。(這也算。。。)
5, Spring的設計會讓使用它創建的應用盡可能少的依賴于它的APIs,在Spring應用中的大多數業務對象沒有依賴于Spring。
6, 使用Spring構建的應用程序易于單元測試;
7, Spring使EJB成為一個實現選擇,而不是必需的選擇。你可以用POJOs或local EJBs來實現業務接口,卻不會影響到調用代碼。
8, Spring提供一些web應用上的EJB的替代方案,比如用AOP提供聲明性事務管理;
9, Spring為數據存取提供了一個一致的框架,不論是使用JDBC還是O/R mapping的產品(Hibernate,JDO)。
Spring的任務描述:
Spring的主要目的就是使J2EE易用和促進良好的編程習慣。
Spring不會重新發明輪子,它是讓已有的技術更加易用,比如它沒有底層事務協調處理,但是提供了一個抽象層覆蓋了JTA和任何其他的事物策略。Spring并沒有和其他的開源項目競爭,不過還是在一些領域有新的方案提供,比如它的web framework,輕量級的IoC容器和AOP框架。
二,Inversion of Control容器
Spring的設計核心是org.springframework.beans包,用來協調JavaBeans的工作。這個包一般不會被用戶直接使用,而是作為其他功能的基礎服務。
下一個高一些的抽象概念是Bean Factory,一個Spring bean factory是一個可以通過名稱來獲取objects的通用工廠,并且管理objects之間的關系。
Bean factories支持兩種對象模式:
Singleton:默認的,最常使用的,對于無狀態的對象是一種理想的模式。
Prototype:每次獲取將創建一個獨立的對象,可以讓用戶擁有他們自己的對象。
由于org.springframework.beans.factory.BeanFactory是一個簡單的接口,所以你能夠方便地實現出你自己的BeanFactory,但是很少用戶需要這樣做;常用的BeanFactory定義是:
XmlBeanFactory:解析簡單直觀的定義類和命名對象屬性的XML結構;
ListableBeanFactoryImpl:提供了解析存放在屬性文件中的bean定義的能力;
通過BeanFactory的概念,Spring成為了一個Inversion of Control容器。IoC背后的概念就是所謂的Hollywood原則:Don’t call me, I ‘ll call you。IoC將控制創建的職責從對象的代碼中搬進了框架中,使用IoC容器只需指出組件需要X對象,在運行期容器會提供給它具體的對象。而容器就是通過查看方法的參數表(例如JavaBean的屬性),或者通過配置源(XML)來得到相應的信息,從而實現向組件提供對象
Spring ApplicationContext是BeanFactory的子接口,為下列東西提供支持:
信息查找,支持國際化
事件機制,允許發布應用程序以及可選的注冊已接受到事件
可移植的文件和資源訪問
三,JDBC抽象和數據訪問異常層次
JDBC提供了不錯的數據庫抽象,但是也有痛苦的地方:
需要大量的錯誤處理代碼來確保ResultSet,Statement,Connection在使用后關閉;
沒有異常的層次,使用SQLException來響應所有的錯誤,并不知道具體錯在哪里。
Spring用兩種方法解決這些問題:
通過API把冗長易出錯的異常處理代碼從程序轉移到框架中,框架處理所有異常,而程序代碼集中精力進行SQL和處理結果上;
為要處理SQLException的程序代碼提供有意義的異常層次。當Spring第一次從數據源取得一個連接時,它檢查元數據以確定數據庫,隨后它使用這些信息把SQLException映射為自己的異常層次中的響應的異常,是你可以和有意義的異常打交道。
Spring提供兩層JDBC API,第一個在org.springframework.jdbc.core包中,使用回調機制移動控制權從程序轉移到了框架中,這是一種不同的Inversion of Control。
在org.springframework.jdbc.object包中是對JDBC的更高層次的抽象。這是建立在核心的JDBC回調功能基礎之上的,但是提供了一個能夠對RDBMS操作的API,在這個API中無論是查詢,更新或是存儲過程,都是用Java對象來建模。這組API受到了JDO查詢API的影響,非常直接而且有用。
Spring數據訪問異常層次是基于unchecked exception的,這樣開發者可以自己決定是否來捕捉這些異常從而恢復。
Spring JDBC對你帶來的好處:
你不必像JDBC那樣寫finally;
你需要編寫的代碼變少了;
你不必鉆研RDBMS文檔去解決理解,一個因為錯誤的列名而返回的詭異錯誤碼;
不管你使用何種持久化技術,你都可以方便地實現DAO模式,讓業務代碼不依賴于任何特定的數據訪問API。
四,O/R mapping集成
Spring提供了對Hibernate 2.x和JDO的集成支持,尤其是對Hibernate的集成。
為什么要使用Hibernate+Spring,而不是直接使用Hibernate呢?
1, 用Hibernate的代碼通常需要為了效率和適當的事務處理而使用相同的Session對象;Spring通過在代碼層上使用顯式的template包裝類或者使用聲明式的,AOP的方法攔截(interceptor)方式兩種方案,使得能夠很容易透明地創建和綁定Session到當前的線程。
2, 資源管理,Spring的應用程序context能夠處理Hibernate SessionFactories的位置和配置,JDBC數據源和其他的相關資源;使得易于管理和改變。
3, 集成的事務管理 Spring讓你能夠把你的Hibernate代碼包裝起來,通過2種方式:在代碼層上使用顯式的template包裝類,或者使用聲明式的,AOP的方法攔截(interceptor)。
4, Spring能夠包裝Hibernate異常,把它們從私有的,checked異常轉換為一套抽象的運行時異常;使得你能夠在任何你需要的地方捕捉和處理異常,并且JDBC異常也被轉換到相同的層次中,意味著你能在一致的編程模型中對JDBC執行相同的操作。
5, 為了避免和廠商綁定 Hibernate強大,靈活,免費,當時仍然使用私有的API;Spring對Hibernate的事務和異常的抽象,使你很容易將Hibernate-specific代碼隔離開你的應用程序部分,而不會影響Hibernate的強大功能。
6, 測試簡單 Spring的IoC使它很容易改變Hibernate session factories的位置,數據源,事務管理和映射對象執行,這使得很容易隔離和測試每一塊持久關系代碼。
五,事務管理
JTA使一個直接用起來很笨重的API,許多J2EE開發者感到EJB CMT使對于事務管理的唯一合理的選擇。
Spring提供了它對事務管理的抽象,提供了:
1, 通過類似于JdbcTemplate的回調模板編程管理事務,比起直接用JTA容易多;
2, 類似于EJB CMT的聲明式事務管理,但不需要EJB容器;
六,AOP
Spring的AOP支持的首要目標是要給POJOs提供J2EE服務,而且它有能夠在應用服務器之間移植的優勢,Spring AOP支持method interception,關鍵概念包括:
Interception:自定義行為能夠在對接口和類的調用之前之后插入;
Introduction:指定advice會導致對象實現額外的接口,混亂了繼承;
Spring使用動態代理實現AOP或者在運行時使用CGLIB生成字節碼(這是的能夠代理類)。兩種方法都能夠在任何應用服務其中使用。
Spring使實現了AOP Alliance接口的AOP框架(在學習AOP中介紹過)。
Spring AOP最常見的應用使聲明式事務管理,這是基于前面描述的TransactionTemplate抽象上的,并且可以給任何POJO提供聲明式事務管理。
Spring的聲明式事務管理類似于EJB CMT,但在以下方面不同:
l 事務管理能夠應用于任何POJO;
l 通過使用Spring的事務API能夠在事務性POJO中實現編程回掉。為此我們提供靜態的方法,使用ThreadLocal變量,因而不需要你傳遞EJBContext這樣的對象確保回滾;
l 你可以聲明式地定義“回滾規則”;
l 事務管理不綁定于JTA。
當然你還可以使用Spring AOP實現程序特有的aspects。
請對以上恢復出來的文字進行修改后提交
七,MVC web框架
Spring的MVC model類似于Struts。在多線程服務對象這點上,Spring的Controller類似于Struts Action,只有一個實例處理所有客戶請求。
Spring MVC比起Struts的優點:
1, Spring在Controller, JavaBean, model和views提供了一個非常清晰的劃分;
2, Spring的MVC是非常靈活的。不像Struts強制你繼承它的Action和Form對象,Spring MVC完全是基于接口的;
3, Spring MVC是真正的view無關的。你不會被強制使用JSP
4, 和其他對象一樣,Spring的Controller是通過IoC配置的。使它們易于測試;
5, Web層變成了業務對象層上的薄薄一層
八,EJB相關
實現EJB:
如果你選擇使用EJB,Spring能在EJB實現和客戶端訪問EJB兩方面都提供很大的好處。
Spring為session bean和message drive bean提供了方便的超類,使得通過自動載入基于包含在EJB jar文件中的XML文檔BeanFactory讓這變得很容易。
感覺不是很有用的樣子。
使用EJB:
許多EJB程序使用Service Locator和Business Delegate模式,這些比在客戶代碼中使用JDNI查找強多了,但是還是有顯著的缺點:
l 使用EJB的典型代碼依賴Service Locator或者Business Delegate singletons,難于測試;
l 在Service Locator模式沒有使用Business Delegate的情況下,程序代碼還要在EJB home重調用create()方法,并且可能導致異常,代碼依然綁定在EJB API上;
l 實現Business Delegate模式通常導致顯著的代碼重復;
我們只需要給需要EJB的Bean定義一個組件,在XML中指定它的jndi name,interface,Spring AOP框架會幫你為EJB創建一個代理,實現了業務方法的接口,緩存EJBHome,代理JNDI查找,調用響應的業務方法。
從而使你的web層代碼不依賴于EJB的使用,如果你要使用POJO或其他object代替EJB引用,你只需要改動組件定義xml,而不影響代碼。