亚洲成aⅴ人片久青草影院按摩,亚洲精品你懂的在线观看,亚洲第一精品在线视频http://m.tkk7.com/liaojiyong/category/13297.htmlzh-cnFri, 25 May 2007 10:43:23 GMTFri, 25 May 2007 10:43:23 GMT60Spring MVC 開發快速入門(轉)http://m.tkk7.com/liaojiyong/archive/2007/03/30/107416.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:51:00 GMThttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107416.htmlhttp://m.tkk7.com/liaojiyong/comments/107416.htmlhttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107416.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/107416.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/107416.html  首先, 我需要在你心里建立起 Spring MVC 的基本概念. 基于 Spring 的 Web 應用程序接收到 http://localhost:8080/hello.do(事實上請求路徑是 /hello.do) 的請求后, Spring 將這個請求交給一個名為 helloController 的程序進行處理, helloController 再調用 一個名為 hello.jsp 的 jsp 文件生成 HTML 代碼發給用戶的瀏覽器顯示. 上面的名稱(/hello.do, helloController, hello.jsp) 都是變量, 你可以更改.

  在 Spring MVC 中, jsp 文件中盡量不要有 Java 代碼, 只有 HTML 代碼和"迭代(forEach)"與"判斷(if)"兩個jstl標簽. jsp 文件只作為渲染(或稱為視圖 View)模板使用.

  好了, 我們開始吧. 首先我們需要一個放在 WEB-INF 目錄下的 web.xml 文件:

web.xml:
 1 <?xmlversion="1.0"encoding="UTF-8"?>
2
3 web-appversion="2.4"xmlns="http://java.sun.com/xml/ns/j2ee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
6 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
7
8 context-param
9 param-namecontextConfigLocation</param-name>
10 param-value
11 /WEB-INF/database.xml
12 /WEB-INF/applicationContext.xml
13 </param-value>
14 </context-param>
15
16 listener
17 listener-classorg.springframework.web.context.ContextLoaderListener</listener-class>
18 </listener>
19
20 filter
21 filter-nameencodingFilter</filter-name>
22 filter-classorg.springframework.web.filter.CharacterEncodingFilter</filter-class>
23 init-param
24 param-nameencoding</param-name>
25 param-valueUTF-8</param-value>
26 </init-param>
27 </filter>
28
29 filter-mapping
30 filter-nameencodingFilter</filter-name>
31 url-pattern*.do</url-pattern>
32 </filter-mapping>
33
34 servlet
35 servlet-nameideawu</servlet-name>
36 servlet-classorg.springframework.web.servlet.DispatcherServlet</servlet-class>
37 load-on-startup1</load-on-startup>
38 </servlet>
39
40 servlet-mapping
41 servlet-nameideawu</servlet-name>
42 url-pattern*.do</url-pattern>
43 </servlet-mapping>
44
45 welcome-file-list
46 welcome-fileindex.jsp</welcome-file>
47 welcome-fileindex.html</welcome-file>
48 </welcome-file-list>
49
50 jsp-config
51 taglib
52 taglib-urihttp://java.sun.com/jsp/jstl/core</taglib-uri>
53 taglib-location/WEB-INF/tld/c.tld</taglib-location>
54 </taglib>
55 taglib
56 taglib-urihttp://java.sun.com/jsp/jstl/fmt</taglib-uri>
57 taglib-location/WEB-INF/tld/fmt.tld</taglib-location>
58 </taglib>
59 </jsp-config>
60
61 </web-app>

  它配置了以下功能:

  • 配置 DispatcherServlet (servlet 標簽), 它是一個 Java Servlet 程序. 我們將它命名為 ideawu. 然后我們再配置 Servlet 映射(servlet-mapping 標簽), 也就是你希望哪些請求被DispatcherServlet處理. 這里, 我們設置后綴名為 do(*.do) 的所有URL請求都被名為 ideawu 的 DispatcherServlet 的程序處理. 選擇 .do 只是一個習慣,但是你不要選擇 .html! 雖然《Spring in Action》選擇了 .html, 但是那是一種非常糟糕的作法, 特別是你整合 ApacheTomcat 的時候.
  • 配置 CharacterEncodingFilter (filter 標簽), 否則你會發現中文亂碼. 因為我的 jsp 和 html 文件都是 UTF-8 編碼的, 所以我在 param-value 標簽中設置了 UTF-8. 估計你使用的是 GB2312 或者 GBK, 立即轉到 UTF-8 上來吧.
  • 分解配置文件. context-param 標簽指明我們的配置文件還有 /WEB-INF/database.xml 和 /WEB-INF/applicationContext.xml. ContextLoaderListener(listener 標簽) 由此得知配置文件是哪些, 它會將它們載入.

  因為我們將 DispatcherServlet 命名為 ideawu, 所以我們在 WEB-INF 目錄下建立一個名為 ideawu-servlet.xml 的文件:

  ideawu-servlet.xml:
 1 <?xmlversion="1.0"encoding="UTF-8"?>
2 <!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN""
http://www.springframework.org/dtd/spring-beans.dtd"

3
4 beans
5
6 beanid="viewResolver"class="org.springframework.web.servlet.
_view.InternalResourceViewResolver"

7 propertyname="prefix"value="/WEB-INF/jsp/" />
8 propertyname="suffix"value=".jsp" />
9 </bean>
10
11 beanid="simpleUrlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
12 propertyname="mappings"
13 props
14 propkey="/hello.do"helloController</prop>
15 </props>
16 </property>
17 </bean>
18
19 beanid="helloController"class="com.ideawu.HelloController"
20 <!--
21 <property name="helloManager" ref="helloManager" />
22 --
23 </bean>
24
25 </beans>

  它配置了以下功能:

  • 配置 InternalResourceViewResolver, 它是 jsp 渲染模板的處理器. 如果你告訴 InternalResourceViewResolver 處理一個名為 hello 的模板時, 它會渲染 /WEB-INF/jsp/hello.jsp 文件. 把 jsp 文件放到 /WEB-INF/jsp/ 目錄下是被鼓勵的, 這樣可以防止用戶不經過 Controller 直接訪問 jsp 文件從而出錯(有些頑皮的人很喜歡這樣做).
  • 配置 SimpleUrlHandlerMapping, 在上面的配置文件中, /hello.do 的請求將被 helloController 處理. "/hello.do"和"helloController" 是變量, 你可以更改. 但是你注意到了嗎, hello.do 以 .do 作為后綴名. 如果這里(本文的條件下)你 不使用.do 作為后綴名, 就沒有程序來處理這個請求了. 因為 DispatcherServlet 將收到的請求轉交給 SimpleUrlHandlerMapping, DispatcherServlet 收不到的請求, SimpleUrlHandlerMapping 當然也收不到了. 你可以在 props 標簽內配置多個 prop 標簽.
  • 我們將在后面編寫 com.ideawu.HelloController 類.


上面, 我們在 web.xml 文件中告訴 ContextLoaderListener, 我們還有另外兩個配置文件 /WEB-INF/database.xml 和 /WEB-INF/applicationContext.xml.

  applicationContext.xml:

 1 <?xmlversion="1.0"encoding="UTF-8"?>
2 <!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN""
http://www.springframework.org/dtd/spring-beans.dtd"

3
4 beans
5
6 beanid="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
7 propertyname="locations"
8 list
9 value/WEB-INF/jdbc.properties</value>
10 </list>
11 </property>
12 </bean>
13
14 </beans>

  它配置了以下功能:

  • 讀取 /WEB-INF/jdbc.properties 文件. 你可以在 list 標簽中配置多個 value 標簽.

  database.xml:

 1 <?xmlversion="1.0"encoding="UTF-8"?>
2 <!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN""
http://www.springframework.org/dtd/spring-beans.dtd"

3
4 beans
5
6 <!-- Remove this if your database setting is fine.
7 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
8 <property name="driverClassName" value="${jdbc.driverClassName}"/>
9 <property name="url" value="${jdbc.url}"/>
10 <property name="username" value="${jdbc.username}"/>
11 <property name="password" value="${jdbc.password}"/>
12 </bean>
13 --
14
15 <!-- Transaction manager for a single JDBC DataSource
16 <bean id="transactionManager"
       class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

17 <property name="dataSource" ref="dataSource"/>
18 </bean>
19 --
20
21 <!--
22 <bean id="attributeManager" class="com.ideawu.core.AttributeManager">
23 <property name="dataSource" ref="dataSource"/>
24 </bean>
25 --
26
27 </beans>

  它配置了以下功能(不過,已經注釋掉了):

  • 配置數據庫連接. 類似${jbbc.url}是一種訪問變量的方法. 我們可以從 /WEB-INF/jdbc.properties 中找到這個變量的值. 如果你的數據庫已經配置好, 就將第一個注釋去掉.

  jdbc.properties:

1 jdbc.driverClassName=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=UTF-8
3 jdbc.username=test
4 jdbc.password=12345

  現在, 我們來編寫 Java 代碼吧.

 1 /***********************************************************
2 * Date: 2006-8-26
3 * File: HelloController.java
4 * Author: ideawu
5 ***********************************************************/
6
7 package com.ideawu;
8
9 import org.springframework.web.servlet.mvc.Controller;
10 import org.springframework.web.servlet.ModelAndView;
11
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14
15 /**
16 * @author ideawu
17 *
18 */
19 publicclass HelloController implements Controller {
20 /*
21 private HelloManager helloManager;
22
23 public void setHelloManager(HelloManager helloManager) {
24 this.helloManager = helloManager;
25 }
26 */
27
28 public ModelAndView handleRequest(HttpServletRequest request,
29 HttpServletResponse response)throws Exception{
30
31 request.setAttribute("hello_1""你好啊, Spring!");
32 request.setAttribute("hello_2""Hello World!");
33
34 returnnew ModelAndView("hello");
35 }
36
37 }

  return new ModelAndView("hello"); 告訴 InternalResourceViewResolver jsp 模板的名字叫作 hello. request.setAttribute() 設置的對象我們可以在 jsp 文件中使用.

  hello.jsp:

 1 <%@ pagecontentType="text/html; charset=UTF-8" %>
2 <%@ taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core" %>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""
    http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"

4 html xmlns="http://www.w3.org/1999/xhtml"
5 head
6 metahttp-equiv="Content-Type"content="text/html; charset=utf-8" />
7 titleHello World!</title
8 </head
9 body
10
11 h2${hello_1}</h2
12
13 h2${hello_2}</h2
14
15 </body
16 </html

  你可以下載整個 Web 應用程序. 在 Debian Linux, Tomcat 5.5.16, JDK1.5.0 下運行良好. 解壓后得到一個 spring 文件夾, 放到你的 webapps 目錄下, 在瀏覽器中輸入 http://localhost:8080/spring/hello.do 就可以訪問了。



liaojiyong 2007-03-30 09:51 發表評論
]]>
Spring+Hibernate+Struts技術的一個分頁程序(轉)http://m.tkk7.com/liaojiyong/archive/2007/03/30/107408.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:43:00 GMThttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107408.htmlhttp://m.tkk7.com/liaojiyong/comments/107408.htmlhttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107408.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/107408.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/107408.html 我用的是Spring+Hibernate+Struts框架:

這是我的DAO的核心代碼
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
// 用Spring支持的Hibernate方法,使Hibernate對數據庫的操作繼續瘦身
public List getOfficeBySearchCriteria(final String hsql,final int pageNo,final int page_size) throws DataAccessException // hsql 是如:"select office1 from Office as office1 order by office1.officename";pageNo 是第幾頁;page_size是每頁記錄數
{
String sql;
int total_count=0;
List offices=new ArrayList();
//offices= getHibernateTemplate().find("from Office office1 where office1.officename like ?", "%"+officeName+"%");
offices= getHibernateTemplate().find(hsql); //為了得到總記錄數
total_count=offices.size();
crossPageInfo= crossPageBean.getCrossPageInfo(total_count,pageNo,page_size);

sql=hsql+ " limit " + (pageNo-1)*page_size + "," +page_size;
offices= getHibernateTemplate().find(sql); //為了得到頁記錄信息 System.out.println("The list offices size: "+offices.size());
return offices;
}

//其中crossPageBean.getCrossPageInfo只是得到頁面的如:總頁數、供多少頁的信息等一般的翻頁信息;

我在Action中是這樣調用的
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
CrossPageInfo crossPageInfo=new CrossPageInfo();
String hsql="select office1 from Office office1 order by office1.officename";
String pageNo=request.getParameter("pageNo");
int pageNoi=1;
if(pageNo==null)
pageNo="1";
pageNoi=Integer.parseInt(pageNo);
int pageSize=5;
//List offices=getOfficeService().getAllOffice();
List offices=getOfficeService().getOfficeBySearchCriteria(hsql,pageNoi,pageSize);
crossPageInfo=getOfficeService().getCrossPageInfo();
System.out.println("The CorssPgaeInfo :"+crossPageInfo.getPageNo());
System.out.println(crossPageInfo.getPageSize());

request.setAttribute("offices",offices);
request.setAttribute("pageInfo",crossPageInfo);
return mapping.findForward("success");
//throw new UnsupportedOperationException("Generated method 'execute(...)' not implemented.");
}

//其中getOfficeService()只是提供接口服務的方法。


我的表現頁面是這樣的

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %>
<%@ page import="com.uplus.util.CrossPageInfo"%>

<html>
<head>
<title>
mySearchCList
</title>

</head>
<body bgcolor="#ffffff">
<form name="form1" action="officesearch.do" method="post">
<table >
<tr>
<td>OfficeName:<input name="officeName" type="text"></td><td><input type="submit" name="sb" value="Search"></td>
</tr>
</table>
</form>
<br><a href="/jsp/office/officeadd.jsp">Add</a>

<table bgcolor="#DBE9F1" align="center" class="InputFrameMain" style="MARGIN: 0px" cellSpacing="1" cellPadding="0" BGALIGN="CENTER" BGVALIGn="middle" width="100%" VALIGN="middle" >
<tr><td align="center">OfficeName</td><td align="center">OfficePhone</td></tr>
<logic:iterate id="office" name="offices" >
<tr bgcolor="#ffffff">
<td align="center"><a href="officesee.do?id=<bean:write name='office' property='id'/>" target="_blank"><bean:write name="office" property="officename"/></a></td>
<td align="center"><bean:write name="office" property="officephone"/></td>
<td align="center"><a href="officeedit.do?id=<bean:write name='office' property='id'/>" >Update </a>
<td align="center"><a href="officedel.do?id=<bean:write name='office' property='id'/>" onclick="return confirm('Would You Detele It? ')" >Delete </a>
</tr>
</logic:iterate>
</table>
<%CrossPageInfo cpInfo=(CrossPageInfo)request.getAttribute("pageInfo");%>

<table width="100%" align="center" class="InputFrameMain" style="MARGIN: 0px" cellPadding="0" cellSpacing="0">
<tr ><form action="officelist.do" method="post" onsubmit='return checkform2(this)'>
<td width=70%>Total <font color="blue"><%=cpInfo.getTotalRow()%></font>&items found,Total&<font color="blue"><%=cpInfo.getTotalPage()%></font> Pages,Current No <font color="blue"><%=cpInfo.getPageNo()%> </font>Page.
Go to <input name="pageNo" type="text" size="5" class="input">Page
<input name="sb2" type="submit" class="button" value="Go">
</td></form>
<td width=30% align='left'>
<%if(cpInfo.getPageNo()>1){%>
&<a href="officelist.do?pageNo=1">
<%}%>First</a>
<%if(cpInfo.getPageNo()>1){ %>
&<a href="officelist.do?pageNo=<%=cpInfo.getPageNo()-1%>">
<%}%>Previous</a>
<%if(cpInfo.getPageNo()<cpInfo.getTotalPage()){ %>
&<a href="officelist.do?pageNo=<%=cpInfo.getPageNo()+1%>">
<%}%>Next</a>
<%if(cpInfo.getTotalPage()>cpInfo.getPageNo()){%>
&<a href="officelist.do?pageNo=<%=cpInfo.getTotalPage()%>">
<%}%>Last</a></td>
</tr>

</table>
</body>
</html>


大家可以看一下我的處理過程,其中在DAO里為了得到總計錄數執行了一次次數據表查詢HSQL;得到數據又執行了一次HSQL,我覺得這樣好像有些不太好,大家覺得怎樣?大家提出寶貴的意見吧!



liaojiyong 2007-03-30 09:43 發表評論
]]>
反向控制和面向切面編程在Spring的應用(轉)http://m.tkk7.com/liaojiyong/archive/2007/03/30/107404.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:31:00 GMThttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107404.htmlhttp://m.tkk7.com/liaojiyong/comments/107404.htmlhttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107404.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/107404.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/107404.html
  關鍵詞 Spring;反向控制;面向切面編程;POJO;依賴注入

  引言

  在J2EE的整個發展歷程中,現在正是一個非常時刻。從很多方面來說,J2EE都是一個偉大的成功:它成功地在從前沒有標準的地方建立了標準;大大提升了企業級軟件的開放程度,并且得到了整個行業和開發者的廣泛認可。然而,J2EE在一些方面已經開始捉襟見肘。J2EE應用開發的成本通常很高。J2EE應用項目至少和從前的非J2EE項目一樣容易失敗——如果不是更容易失敗的話。這樣的失敗率高得讓人難以接受。在這樣的失敗率之下,軟件開發幾乎變成了碰運氣。而在J2EE遭遇失敗的場景中,EJB通常都扮演著重要的角色。因此,J2EE社群不斷地向著更簡單的解決方案、更少使用EJB的方向發展[1]。然而,每個應用程序都需要一些基礎設施,拒絕使用EJB并不意味著拒絕EJB所采用的基礎設施解決方案。那么,如何利用現有的框架來提供這些基礎設施服務呢,伴隨著這個問題的提出,一個輕量級的J2EE解決方案出現了,這就是Spring Framework。

  Spring是為簡化企業級系統開發而誕生的,Spring框架為J2EE應用常見的問題提供了簡單、有效的解決方案,使用Spring,你可以用簡單的POJO(Plain Old Java Object)來實現那些以前只有EJB才能實現的功能。這樣不只是能簡化服務器端開發,任何Java系統開發都能從Spring的簡單、可測試和松耦合特征中受益。可以簡單的說,Spring是一個輕量級的反向控制(IoC)和面向切面編程(AOP)容器框架[3]。Spring IoC,借助于依賴注入設計模式,使得開發者不用理會對象自身的生命周期及其關系,而且能夠改善開發者對J2EE模式的使用;Spring AOP,借助于Spring實現的攔截器,開發者能夠實現以聲明的方式使用企業級服務,比如安全性服務、事務服務等。Spring IoC和 Spring ; AOP組合,一起形成了Spring,這樣一個有機整體,使得構建輕量級的J2EE架構成為可能,而且事實證明,非常有效。沒有Spring IoC的Spring AOP是不完善的,沒有Spring AOP的Spring IoC是不健壯的。本文是以Spring架構的成功的實際商務系統項目為背景,闡述了反向控制原理和面向切面的編程技術在Spring框架中的應用,同時抽取適量代碼示意具體應用,并和傳統開發模式進行對比,展示了Spring framework的簡單,高效,可維護等優點。

  1、Spring IoC 1.1 反向控制原理

  反向控制是Spring框架的核心。但是,反向控制是什么意思?到底控制的什么方面被反向了呢?2004年美國專家Martin Fowler發表了一篇論文《Inversion of Control Containers and the Dependency Injection pattern》闡述了這個問題,他總結說是獲得依賴對象的方式反向了,根據這個啟示,他還為反向控制提出了一個更貼切的名字:Dependency Injection(DI 依賴注入)。

  通常,應用代碼需要告知容器或框架,讓它們找到自身所需要的類,然后再由應用代碼創建待使用的對象實例。因此,應用代碼在使用實例之前,需要創建對象實例。然而,IoC模式中,創建對象實例的任務交給IoC容器或框架(實現了IoC設計模式的框架也被稱為IoC容器),使得應用代碼只需要直接使用實例,這就是IoC。相對IoC 而言,“依賴注入”的確更加準確的描述了這種設計理念。所謂依賴注入,即組件之間的依賴關系由容器在運行期決定,形象的來說,即由容器動態的將某種依賴關系注入到組件之中。

  1.2 IoC在Spring中的實現

  任何重要的系統都需要至少兩個相互合作的類來完成業務邏輯。通常,每個對象都要自己負責得到它的合作(依賴)對象。你會發現,這樣會導致代碼耦合度高而且難于測試。使用IoC,對象的依賴都是在對象創建時由負責協調系統中各個對象的外部實體提供的,這樣使軟件組件松散連接成為可能。下面示意了Spring IoC 應用,步驟如下:

  (1)定義Action接口,并為其定義一個execute方法,以完成目標邏輯。多年前,GoF在《Design Pattern:Elements of Reusable Object-Oriented Software》一書中提出“Programming to an Interface,not an implementation”的原則,這里首先將業務對象抽象成接口,正是為了實施這個原則。

  (2)類UpperAction實現Action接口,在此類中,定義一個String型的域message,并提供相應的setter和getter方法,實現的execute方法如下:

public String execute (String str) {
 return (getMessage () + str).toUpperCase () ;
}

  (3)編寫Spring配置文件(bean.xml)

<beans>
<bean id="TheAction" class="net.chen.spring.qs.UpperAction">
<property name="message">
<value>HeLLo</value>
</property>
</bean>
</beans>

  (4)測試代碼

public void testQuickStart () {
 ApplicationContext ctx=new
 FileSystemXmlApplicationContext ("bean.xml");
 Action a= (Action) ctx.getBean ("TheAction");
 System.out.println (a. execute ("Rod Johnson"));
}

  上面的測試代碼中,我們根據"bean.xml"創建了一個ApplicationContext實例,并從此實例中獲取我們所需的Action實現,運行測試代碼,我們看到控制臺輸出:

……
HELLO ROD JOHNSON

  仔細觀察一下上面的代碼,可以看到:

  (1)我們的組件并不需要實現框架指定的接口,因此可以輕松的將組件從Spring中脫離,甚至不需要任何修改,這在基于EJB框架實現的應用中是難以想象的。

  (2)組件間的依賴關系減少,極大改善了代碼的可重用性。Spring的依賴注入機制,可以在運行期為組件配置所需資源,而無需在編寫組件代碼時就加以指定,從而在相當程度上降低了組件之間的耦合。

  Spring給我們帶來了如此這般的好處,那么,反過來,讓我們試想一下,如果不使用Spring框架,回到我們傳統的編碼模式,情況會是怎樣呢?

  首先,我們必須編寫一個配置文件讀取類,以實現Message屬性的可配置化。

  其次,得有一個Factory模式的實現,并結合配置文件的讀寫完成Action的動態加載。于是,我們實現了一個ActionFactory來實現這個功能:

public class ActionFactory {
 public static Action getAction (String actionName) {Properties pro = new Properties ();
 try {
  pro.load (new FileInputStream ("config.properties"));
  String actionImplName =(String)pro.get(actionName);
  String actionMessage =(String) pro.get (actionName+"_msg");
  Object obj =Class.forName (actionImplName).newInstance ();
  BeanUtils.setProperty(obj,"message",actionMessage);
  return (Action) obj;
 } catch (FileNotFoundException e) {
  ……
 }
}

  配置文件則采用properties文件形式如下所示:

TheAction=net.chen.spring.qs.UpperAction
TheAction_msg=HeLLo

  測試代碼也作相應修改。現在不論實現的好壞,總之通過上面新增的多行代碼,終于實現了類似的功能。如果現在有了一個新的需求,這樣這個ActionFactory每次都新建一個類的實例,顯然這對系統性能不利,考慮到我們的兩個Action都是線程安全的,修改一下ActionFactory,保持系統中只有一個Action實例供其它線程調用。另外Action對象創建后,需要做一些初始化工作。修改一下ActionFactory,使其在創建Action實例之后,隨即就調用Action.init方法執行初始化。Action的處理這樣就差不多了。下面我們來看看另外一個Factory

  ……

  往往這些系統開發中最常見的需求,會導致我們的代碼迅速膨脹,而Spring IoC的出現,則大大緩解了這樣的窘境。通過以上實例,可以看出,Spring IoC為我們提供了如下幾方面的優勢:

  (1)應用組件不需要在運行時尋找其協作者,因此更易于開發和編寫應用;

  (2)由于借助于IoC容器管理組件的依賴關系,使得應用的單元測試和集成測試更利于展開;

  (3)通常,在借助于IoC容器關系業務對象的前提下,很少需要使用具體IoC容器提供的API,這使得集成現有的遺留應用成為可能。

  因此,通過使用IoC能夠降低組件之間的耦合度,最終,能夠提高類的重用性,利于測試,而且更利于整個產品或系統集成和配置。

liaojiyong 2007-03-30 09:31 發表評論
]]>
Spring的事務管理2.0與1.2.8的區別(轉)http://m.tkk7.com/liaojiyong/archive/2007/03/30/107400.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:24:00 GMThttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107400.htmlhttp://m.tkk7.com/liaojiyong/comments/107400.htmlhttp://m.tkk7.com/liaojiyong/archive/2007/03/30/107400.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/107400.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/107400.html

本文章比較了Spring自己帶的JPetStore的例子,通過配置文件詳細講解了,Spring1.2.8與2.0如何實現聲明式事務管理。


Spring1.2.8


Spring以前對一個事務攔截要通過代理實現下面的配置文件是從不同的文件中找來的,不是單獨的一個Spring配置文件。


?<!-- Transaction manager for a single JDBC DataSource -->
?<!-- 聲明一個事務管理器 -->
?<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
??<property name="dataSource" ref="dataSource"/>
?</bean>


?<!-- 聲明一個抽象Bean,這個Bean是不能實例化的,提供給其它需要AOP事務的Bean用,其它需要AOP事務的只要繼承這個Bean就會被AOP接管-->
?<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
??? abstract="true">
??<property name="transactionManager" ref="transactionManager"/>
??<property name="transactionAttributes">
???<props>
????<prop key="insert*">PROPAGATION_REQUIRED</prop>
????<prop key="update*">PROPAGATION_REQUIRED</prop>
????<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
???</props>
??</property>
?</bean>

?<!-- 繼承之前實現的抽象Bean,讓這個Bean通過代理工廠生成,交給AOP托管。至于哪些方法被接管在控制Bean中已經配置了-->
?<bean id="petStore" parent="baseTransactionProxy">
??<property name="target">
???<bean class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
????<property name="accountDao" ref="accountDao"/>
????<property name="categoryDao" ref="categoryDao"/>
????<property name="productDao" ref="productDao"/>
????<property name="itemDao" ref="itemDao"/>
????<property name="orderDao" ref="orderDao"/>
???</bean>
??</property>
??<!-- Uncomment the following in order to enable mail sending aspect -->
??<!--
??<property name="postInterceptors">
???<list>
????<ref bean="emailAdvisor"/>
???</list>
??</property>
???-->
?</bean>


最早發表于 http://www.openj.cn

Spring2.0?

?下面的配置與上面的配置完全對應

?<!--這一個Bean的配置與之前完全一樣,沒有變化---->
?<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
??<property name="dataSource" ref="dataSource"/>
?</bean>

?<!--這一處與之前有了變化,在1.2.8版本中,此處的Bean被聲明為由一個FactoryBean生成,而此處只是一個普通的Bean,要簡單許多,透明性要好很多---->
?<bean id="petStore" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
??<property name="accountDao" ref="accountDao"/>
??<property name="categoryDao" ref="categoryDao"/>
??<property name="productDao" ref="productDao"/>
??<property name="itemDao" ref="itemDao"/>
??<property name="orderDao" ref="orderDao"/>
?</bean>


?<!---下面的兩處配置,才是整個事務AOP的核心,在1.2.8版本中,通過FactoryBean把事務對象(dataSource),與需要進行事務控制的對象PetStoreImpl串起來,對PetStoreImpl有侵入性----->
?<!---而在之前的兩處配置中,事務對象(dataSource)與,需要進行事務控制的對象PetStoreImpl沒有什么關系,它們的關系全部體現在下面的兩處配置中----->
?
?
?<!---pointcut屬性定義了哪此點需要去攔截,此處的配置的意思是所有的PetStoreFacade接口中的方法都要攔截,而攔截之后要如何處理則由advice-ref指定的Bean處理----->
?<!---配置文件中各個屬性的含義參考:http://www.redsaga.com/spring_ref/2.0/html/aop.html#aop-schema ----->

?<aop:config>
??<aop:advisor pointcut="execution(* *..PetStoreFacade.*(..))" advice-ref="txAdvice"/>?
?</aop:config>


?
?<!--下面的transaction-manager屬性原配置中沒有,如果缺少此配置,默認值就是“transactionManager”在此加上,讓人看的更明白。-->
?<!-- 參考 http://blog.xmnow.cn/doc/cn/spring2.0-reference_final_zh_cn/ch09s05.html --->
?<tx:advice id="txAdvice"? transaction-manager="transactionManager">
??<tx:attributes>
???<tx:method name="insert*"/>
???<tx:method name="update*"/>
???<tx:method name="*" read-only="true"/>
??</tx:attributes>
?</tx:advice>



liaojiyong 2007-03-30 09:24 發表評論
]]>
Spring2.0項目中的中文問題http://m.tkk7.com/liaojiyong/archive/2007/01/11/93179.htmlliaojiyongliaojiyongThu, 11 Jan 2007 07:10:00 GMThttp://m.tkk7.com/liaojiyong/archive/2007/01/11/93179.htmlhttp://m.tkk7.com/liaojiyong/comments/93179.htmlhttp://m.tkk7.com/liaojiyong/archive/2007/01/11/93179.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/93179.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/93179.html  這里提前申明,這個話題不是針對Spring項目,因此請“春迷”們自重、沒事勿擾,文中不足之處歡迎大家批評指教。
  我們知道,一個開源軟件項目,給用戶的單元測試最基本的要求是能全部通過測試,在Java中就是在運行單元測試的時候應該要看見一個綠條。Spring項目的單元測試寫得非常好,也非常全面。然而,單元測試中卻有一些問題,在中文路徑上無法完全通過測試,必須放到英文路徑下才能完全通過測試,因此,這屬于一種“沒商量”的中文問題。
  單元測試:
  包:org.springframework.beans.factory.xml
  類:XmlBeanFactoryTests
  方法:testFileSystemResourceWithImport
  錯誤圖示:
?


  詳細錯誤信息:
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from file [C:\Documents%20and%20Settings\Administrator\%e6%a1%8c%e9%9d%a2\spring\spring-framework-2.0-rc2\bin\org\springframework\beans\factory\xml\resource.xml]; nested exception is java.io.FileNotFoundException: C:\Documents%20and%20Settings\Administrator\%e6%a1%8c%e9%9d%a2\spring\spring-framework-2.0-rc2\bin\org\springframework\beans\factory\xml\resource.xml (系統找不到指定的路徑。)
Caused by: java.io.FileNotFoundException: C:\Documents%20and%20Settings\Administrator\%e6%a1%8c%e9%9d%a2\spring\spring-framework-2.0-rc2\bin\org\springframework\beans\factory\xml\resource.xml (系統找不到指定的路徑。)
?at java.io.FileInputStream.open(Native Method)
?at java.io.FileInputStream.<init>(FileInputStream.java:106)
?at org.springframework.core.io.FileSystemResource.getInputStream(FileSystemResource.java:85)
?at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
?at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:315)
?at org.springframework.beans.factory.xml.XmlBeanFactory.<init>(XmlBeanFactory.java:73)
?at org.springframework.beans.factory.xml.XmlBeanFactory.<init>(XmlBeanFactory.java:61)
?at org.springframework.beans.factory.xml.XmlBeanFactoryTests.testFileSystemResourceWithImport(XmlBeanFactoryTests.java:946)
?at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
?at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
?at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
?at java.lang.reflect.Method.invoke(Method.java:585)
?at junit.framework.TestCase.runTest(TestCase.java:154)
?at junit.framework.TestCase.runBare(TestCase.java:127)
?at junit.framework.TestResult$1.protect(TestResult.java:106)
?at junit.framework.TestResult.runProtected(TestResult.java:124)
?at junit.framework.TestResult.run(TestResult.java:109)
?at junit.framework.TestCase.run(TestCase.java:118)
?at junit.framework.TestSuite.runTest(TestSuite.java:208)
?at junit.framework.TestSuite.run(TestSuite.java:203)
?at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
?at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
?at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
?at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
?at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
?at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

測試代碼:
public void testFileSystemResourceWithImport() {
??String file = getClass().getResource("resource.xml").getFile();
??XmlBeanFactory xbf = new XmlBeanFactory(new FileSystemResource(file));
??// comes from "resourceImport.xml"
??ResourceTestBean resource1 = (ResourceTestBean) xbf.getBean("resource1");
??// comes from "resource.xml"
??ResourceTestBean resource2 = (ResourceTestBean) xbf.getBean("resource2");
?}
?
出錯原因:
  這個問題是筆者在參與開發EasyJWeb及EasyDBO框架中遇到過的問題,因此很容易就找到了問題的所在。Java的Class.getResource(name)返回的是一個URL,而URL.getFile默認情況下返回的是經過URL編碼后的字符,會把中文等特殊字符變成類似%e6的形式。而一般io構造路徑是沒有自動解碼功能的,所以在中文路徑下要出現錯誤。
?
解決辦法:
  在使用URL.getFile返回的路徑時,使用前需要使用java.net.URLDecoder對路徑進行一次解碼操作。修改后的且能通過測試的方法如下:
public void testFileSystemResourceWithImport() {
??String file = getClass().getResource("resource.xml").getFile();
??try{
??file=java.net.URLDecoder.decode(file,"UTF-8");
??}
??catch(Exception e)
??{
???e.printStackTrace();
??}?
??XmlBeanFactory xbf = new XmlBeanFactory(new FileSystemResource(file));
??// comes from "resourceImport.xml"
??ResourceTestBean resource1 = (ResourceTestBean) xbf.getBean("resource1");
??// comes from "resource.xml"
??ResourceTestBean resource2 = (ResourceTestBean) xbf.getBean("resource2");
?}
?
小結:
  由于Spring開源項目的開發團隊中,除了一些喜歡跟在Rod大叔的屁股后面唱中文版贊歌的“春迷”以外,當前似乎還沒有中國人參與到正式的Spring開發小組中。因此,也許沒有在中文路徑下運行過測試用例,導致我這樣的Spring初學者一不小心就遇上這樣的問題。
  問題是解決了,但是卻是一種比較罕見的方式,而且Spring開發小組事先也許沒有預想到或是故意忽略掉的問題,因此,可以稱得上是“沒商量”的中文問題。


liaojiyong 2007-01-11 15:10 發表評論
]]>
Spring技巧之簡潔配置(轉)http://m.tkk7.com/liaojiyong/archive/2007/01/11/93171.htmlliaojiyongliaojiyongThu, 11 Jan 2007 07:00:00 GMThttp://m.tkk7.com/liaojiyong/archive/2007/01/11/93171.htmlhttp://m.tkk7.com/liaojiyong/comments/93171.htmlhttp://m.tkk7.com/liaojiyong/archive/2007/01/11/93171.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/93171.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/93171.html??????配置Apache的一個數據源連接池,在Spring?2.0以前的版本中,我們可以使用類似下面的配置:
<?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>org.gjt.mm.mysql.Driver</value></property>
??<property?name="url">
???<value>jdbc:mysql://127.0.0.1:3306/easyjf-bbs</value>?</property>
??<property?name="username"><value>root</value>?</property>
??<property?name="password"><value>mypass</value></property>
?</bean>
</beans>?
??????在Spring2.0中,可以把<value>及<ref>兩個標簽作為其父級<bean>標簽的一個屬性來定義,這樣使得配置文件更加簡潔,如下所示:
<?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="org.gjt.mm.mysql.Driver"?/>
??<property?name="url"
???value="jdbc:mysql://127.0.0.1:3306/easyjf-bbs"?/>
??<property?name="username"?value="root"?/>
??<property?name="password"?value="mypass"?/>
?</bean>
</beans>

??????另外,Spring2.0中還有一個非常實用的解析器,SimplePropertyNamespaceHandle,若配置文件中引用http://www.springframework.org/schema/p命令空間,則將會使用SimplePropertyNamespaceHandle來處理這個Bean的定義,可以在Spring2.0中的Bean中以更簡單的方式配置設值方法注入,如下所示:
<?xml?version="1.0"?encoding="UTF-8"?>
<beans?xmlns="http://www.springframework.org/schema/beans"
?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
?xmlns:p="http://www.springframework.org/schema/p"
?xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean?id="dataSource"
??class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close"
??p:driverClassName="org.gjt.mm.mysql.Driver"
??p:url="jdbc:mysql://127.0.0.1:3306/easyjf-bbs"?p:username="root"?p:password="mysql"?/>
</beans>

在上面的配置中,使用p:url則可以直接注入BasicDataSource的url屬性值,可以使用p:url-ref屬性來引用另外一個Bean。
????如,Spring2.0以前的一個DAO配置:
<bean?id="userDao"?class="com.easyjf.bbs.dbo.springjdbc.UserDaoSpringJdbc">
???????<property?name="dataSource"><ref?bean="dataSource"/></property>
???</bean>??
??使用簡短屬性方式,則改成如下:
<bean?id="userDao"?class="com.easyjf.bbs.dbo.springjdbc.UserDaoSpringJdbc"?p:dataSource-ref="dataSource"?/>

Spring2.0比以前的版本配置更加靈活、簡潔,如果手工書寫配置,則比較實用。當然,老的配置方式有很多開發工具如MyEclipse等都能識別,不需要我們動手一點一點的錄入配置文件,大多數工具對新的配置方式還不能識別,因此,請根據實際情況酌情使用。

由于水平有限,文中不足之處歡迎廣大Spring愛好者不吝指教,請“春迷”勿攏!?

liaojiyong 2007-01-11 15:00 發表評論
]]>
Spring+hibernate 單元測試框架總結 (轉)http://m.tkk7.com/liaojiyong/archive/2006/09/01/67081.htmlliaojiyongliaojiyongFri, 01 Sep 2006 05:43:00 GMThttp://m.tkk7.com/liaojiyong/archive/2006/09/01/67081.htmlhttp://m.tkk7.com/liaojiyong/comments/67081.htmlhttp://m.tkk7.com/liaojiyong/archive/2006/09/01/67081.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/67081.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/67081.html?這兩天的花費了一些時間在使用spring-mock進行spring的單元測試問題上,基本上對這個問題有了一個完整的解決方案
下面將對相關學習到和思考到的一些問題進行一下整理:
1、首先明確一下問題:要對什么進行單元測試?
我的問題是圍繞這一個DAO展開,我定義了一個DAO接口XXXDAO,并且寫了該DAO的實現XXXDAOImpl,然后使用spring對接口的實現進行管理:
<bean?id="XXXDAO"?class="com.easou.datastat.base.dao.impl.XXXDAOImpl">
????
<property?name="sessionFactory">
??????
<ref?bean="sessionFactory"/>
????
</property>
????
<property?name="hibernateTemplate">
??????
<ref?bean="hibernateTemplate"/>
????
</property>
??
</bean>

現在問題開始明確了,我要對XXXDAOImpl進行單元測試。這里需要指明一個問題就是單元測試,測試的是有實現代碼的實現類,而不是接口。

2、接著是下一個問題,如何取得Sping的上下文關系呢?
這里就需要用到spring-mock了,其中有一個測試基類是AbstractTransactionalDataSourceSpringContextTests
我讓測試用例XXXDAOImplTestcase繼承AbstractTransactionalDataSourceSpringContextTests,然后override其中的方法getConfigLocations()
具體代碼如下:
public?class?XXXDAOImplTestCase?extends?AbstractTransactionalDataSourceSpringContextTests?{

????
????@Override
????
protected?String[]?getConfigLocations()?{
????????
//?TODO?get?the?spring?context
????????
????????String[]?config?
=?new?String[]{"file:D:\\javawork\\workspace\\datastat\\docroot\\WEB-INF\\applicationContext.xml","file:D:\\javawork\\workspace\\datastat\\docroot\\WEB-INF\\applicationContext-base.xml"};
????????
????????
return?config;

????}

}

不難看出,該方法是為了讀入spring的上下文信息,這樣的話這個測試用例就可以直接使用spirng中定義的bean了
但是這里需要注意一個問題*,就是文件路徑的問題,這里為了能夠清楚地說明文件的路徑規則我引用了spring-mock官方的getConfigLocation方法說明
Subclasses must implement this method to return the locations of their config files. A plain path will be treated as class path location. E.g.: "org/springframework/whatever/foo.xml". Note however that you may prefix path locations with standard Spring resource prefixes. Therefore, a config location path prefixed with "classpath:" with behave the same as a plain path, but a config location such as "file:/some/path/path/location/appContext.xml" will be treated as a filesystem location.

3 好了,該到最后一個問題了,取得Spirng上下問中定義的bean的實例來進行單元測試
這里有兩種方法,一種是定義一個代測單元的對象,然后定義好get,set方法,AbstractTransactionalDataSourceSpringContextTests會自動根據Spring的上下文得到待測單元的具體實現。
private?ExQueryDAO?exQqueryDAO;
????
????
????
????
/**
?????*?
@return?返回?exQqueryDAO。
?????
*/

????
public?ExQueryDAO?getExQqueryDAO()?{
????????
return?exQqueryDAO;
????}



????
/**
?????*?
@param?exQqueryDAO?要設置的?exQqueryDAO。
?????
*/

????
public?void?setExQqueryDAO(ExQueryDAO?exQqueryDAO)?{
????????
this.exQqueryDAO?=?exQqueryDAO;
????}


另外一種就是使用applicationContext.getBean("XXXDAO");的方法取得實例
XXXDAO xxxDAO = (XXXDAO)applicationContext.getBean("XXXDAO");

接下來你就可以用這個bean的具體實現對相關方法進行unittest了



這里補充一個問題就是單元測試的運行環境問題*,由于你可能在spring的配置文件中指定一些外部類所以你必須在junit的運行環境中指定使用到的classpath,下面是eclipse的junit配置classpath
junit-classpath.JPG


最后我對整體的spring+hibernate的jsf框架進行了一下單元測試的框架總結,主要多了一個基本的BaseTestCase,用于統一讀取applicationContext
單元測試框架.jpg

可以看到下面的pagebean和jsp頁面以及相關的taglib的單元測試我還沒有完成:),我將在今后幾天繼續研究相關的單元測試問題


liaojiyong 2006-09-01 13:43 發表評論
]]>
SpringMVC MultiActionController的使用-最簡化教程(轉)http://m.tkk7.com/liaojiyong/archive/2006/09/01/67078.htmlliaojiyongliaojiyongFri, 01 Sep 2006 05:41:00 GMThttp://m.tkk7.com/liaojiyong/archive/2006/09/01/67078.htmlhttp://m.tkk7.com/liaojiyong/comments/67078.htmlhttp://m.tkk7.com/liaojiyong/archive/2006/09/01/67078.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/67078.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/67078.html
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>

    
<display-name>springapp</display-name>
        
    
<servlet>
        
<servlet-name>springMVC</servlet-name>
        
<servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        
</servlet-class>
        
<load-on-startup>1</load-on-startup>
    
</servlet>

    
<servlet-mapping>
        
<servlet-name>springMVC</servlet-name>
        
<url-pattern>/page/*</url-pattern>
    
</servlet-mapping>

</web-app>
servlet-mapping定義所有以/page/開頭的url請求都會被spring 的DispatcherServlet處理轉發。默認情況下DispatcherServlet會讀取<servlet-name>-servlet.xml文件的配置信息初始化,該文件中urlMapping的定義決定當前請求轉發給哪個controller來處理。

Step2:定義/WEB-INF/springMVC-servlet.xml
 
<?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="InternalPathMethodNameResolver"
        class
="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />
        
    
<!-- 視圖解析器 -->
    
<bean id="viewResolver"
        class
="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
<property name="viewClass">
            
<value>org.springframework.web.servlet.view.JstlView</value>
        
</property>
    
</bean>
    
    
<bean id="controller" class="com.controller.IndexController">
        
<property name="methodNameResolver">
            
<ref bean="InternalPathMethodNameResolver" />
        
</property>
    
</bean>

    
<bean id="urlMapping"
        class
="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        
<property name="mappings">
            
<props>
                
<prop key="/controller/*">controller</prop>
            
</props>
        
</property>
    
</bean>
</beans>
urlMapping定義/controller/開頭的url請求由名字為controller的控制器來處理,因為是多動作處理器,所以要定義MethodNameResolver來告訴springMVC應該調用controller的哪個方法,這里用的是InternalPathMethodNameResolver,該方法名解釋器會把整個URL中最后一個"/"和最后一個"."之間的部分作為要調用的方法名

Step3:定義controller類并繼承MultiActionController 
package com.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

public class IndexController extends MultiActionController {
    
    
public ModelAndView method1(HttpServletRequest request,
            HttpServletResponse respnose) 
throws ServletException, IOException {
        Map model 
= new HashMap();
        model.put(
"message""你調用的是方法1");
        
return new ModelAndView("/index.jsp""model", model);
    }

    
    
public ModelAndView method2(HttpServletRequest request,
            HttpServletResponse respnose) 
throws ServletException, IOException {
        Map model 
= new HashMap();
        model.put(
"message""你調用的是方法2");
        
return new ModelAndView("/index.jsp""model", model);
    }

}


通過配置文件,訪問上面這個controller中某個方法的url即為:localhost:8080/page/controller/方法名


Step4:/index.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt"%> 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head></head>  
<body>

    
<c:out value="${model.message}"/>
</body>
</html>
因為InternalPathMethodNameResolver方法名解釋器會把整個URL中最后一個"/"和最后一個"."之間的部分作為要調用的方法名,所以你可以在這個URL后面加任意文件格式的后綴,比如:
localhost:8080/page/controller/method1.jsp

localhost:8080/page/controller/method2.html
很爽吧,和真實的URL地址一樣。


另:開發環境:MyEclipse5.0M2+tomcat5.5
  需要用到spring.jar和jstl.jar兩個包。

附:源代碼下載


liaojiyong 2006-09-01 13:41 發表評論
]]>
SSH(Spring + Struts + Hibernate)小試(轉)http://m.tkk7.com/liaojiyong/archive/2006/07/21/59320.htmlliaojiyongliaojiyongThu, 20 Jul 2006 17:45:00 GMThttp://m.tkk7.com/liaojiyong/archive/2006/07/21/59320.htmlhttp://m.tkk7.com/liaojiyong/comments/59320.htmlhttp://m.tkk7.com/liaojiyong/archive/2006/07/21/59320.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/59320.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/59320.html 之前對Spring Struts Hibernate都稍有了解,Spring的IOC給我留下了很深的印象,容器管理的對象生成
方法極大地簡化了程序邏輯,Spring也提供了用于Web的Spring MVC 框架,由于我感覺其易用性還是不及
Struts,所以我還是選擇Struts作為前端WEB框架,Hibernate我一直沒有在Web應用中試過,這次當然不會
錯過機會了。


開發環境的塔建我就不多說了,具體可以參考我以前的幾篇日志。

在Eclipse中新建一個動態Web工程,將Struts 、Spring、Hibernate需要的jar都添加到WEB-INF/lib目錄下,
將Struts標簽所需的tld文件、struts-config.xml文件(可以由StrutsIDE生成)添加到WEB-INF下,另外在
此目錄下添加一個Spring的配置文件applicationContext.xml。


我參考的例子是夏昕的《深入淺出Hibernate》上的第6章,很好的一個論壇示例。

首先按照書上的ER模型,在數據庫(MySQL)中建立相應的數據庫。


create database forum;

use forum;

create table user(
?id int not null auto_increment primary key,
?name varchar(50),
?pwd varchar(50),
?email varchar(50)

)type=innodb;


create table board(
?id int not null auto_increment primary key,?
?parent_id int,
?create_by int not null,
?name varchar(50) not null,
?remark varchar(255),
?create_time datetime,

?index(parent_id),
?index(create_by),

?foreign key(parent_id) references board(id) on delete cascade,
?foreign key(create_by) references user(id) on delete no action
?
)type=innodb;


create table article(
?id int not null auto_increment primary key,?
?parent_id int ,
?board_id int not null,
?article_type int not null,
?title varchar(255),
?body text,
?create_by int not null,

?create_time datetime,
?hits int unsigned,
?bytes int unsigned,
?last_update_by int not null,
?last_update_time datetime,

?index(parent_id),
?index(board_id),
?index(create_by),
?index(last_update_by),

?foreign key(parent_id) references article(id) on delete no action,
?foreign key(board_id) references board(id) on delete cascade,
?foreign key(create_by) references user(id) on delete no action,
?foreign key(last_update_by) references user(id) on delete no action
?
)type=innodb;

之后,我選擇了用Hibernate Sychonizer來生成映射文件和實體類,然后對生成的類進行修改(刪掉了生成的Base類),
實際上Hibernate Sychonizer生成的映射文件也有錯誤,需要修改,我也是后來在使用中發現的。

//User.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
?"-//Hibernate/Hibernate Mapping DTD//EN"
?"
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd " >

<hibernate-mapping package="com.lzy.forum.domain">
?<class
??name="User"
??table="user"
?>

??<id
???name="Id"
???type="integer"
???column="id"
??>
???<generator class="native"/>
??</id>

??<property
???name="Name"
???column="name"
???type="string"
???not-null="false"
???length="50"
??/>
??<property
???name="Pwd"
???column="pwd"
???type="string"
???not-null="false"
???length="50"
??/>
??<property
???name="Email"
???column="email"
???type="string"
???not-null="false"
???length="50"
??/>
?

??<set name="ArticlesByLastUpdateBy" inverse="true" lazy="true">
???<key column="last_update_by"/>
???<one-to-many class="Article"/>
??</set>

??<set name="ArticlesByCreateBy" inverse="true" lazy="true">
???<key column="create_by"/>這里的create_by是后來修改的,Hibernate Sychonizer生成的有錯,后面有幾處同樣的錯誤】
???<one-to-many class="Article"/>
??</set>

??<set name="Boards" inverse="true" lazy="true">
???<key column="create_by"/>【這里的create_by是后來修改的】

???<one-to-many class="Board"/>
??</set>


?</class>?
</hibernate-mapping>

//User.java
package com.lzy.forum.domain;


public class User{
?private static final long serialVersionUID = 1L;

//? primary key
?private java.lang.Integer id;

?// fields
?private java.lang.String name;
?private java.lang.String pwd;
?private java.lang.String email;

?// collections
?private java.util.Set<Article> articlesByLastUpdateBy;
?private java.util.Set<Article> articlesByCreateBy;
?private java.util.Set<Board> boards;
?
?
?public java.util.Set<Article> getArticlesByCreateBy() {
??return articlesByCreateBy;
?}
?public void setArticlesByCreateBy(java.util.Set<Article> articlesByCreateBy) {
??this.articlesByCreateBy = articlesByCreateBy;
?}
?public java.util.Set<Article> getArticlesByLastUpdateBy() {
??return articlesByLastUpdateBy;
?}
?public void setArticlesByLastUpdateBy(
???java.util.Set<Article> articlesByLastUpdateBy) {
??this.articlesByLastUpdateBy = articlesByLastUpdateBy;
?}
?public java.util.Set<Board> getBoards() {
??return boards;
?}
?public void setBoards(java.util.Set<Board> boards) {
??this.boards = boards;
?}
?public java.lang.String getEmail() {
??return email;
?}
?public void setEmail(java.lang.String email) {
??this.email = email;
?}
?public java.lang.Integer getId() {
??return id;
?}
?public void setId(java.lang.Integer id) {
??this.id = id;
?}
?public java.lang.String getName() {
??return name;
?}
?public void setName(java.lang.String name) {
??this.name = name;
?}
?public java.lang.String getPwd() {
??return pwd;
?}
?public void setPwd(java.lang.String pwd) {
??this.pwd = pwd;
?}


}

//Board.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
?"-//Hibernate/Hibernate Mapping DTD//EN"
?"
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd " >

<hibernate-mapping package="com.lzy.forum.domain">
?<class
??name="Board"
??table="board"
?>
???<meta attribute="sync-DAO">false</meta>
??<id
???name="Id"
???type="integer"
???column="id"
??>
???<generator class="native"/>
??</id>

??<property
???name="Name"
???column="name"
???type="string"
???not-null="true"
???length="50"
??/>
??<property
???name="Remark"
???column="remark"
???type="string"
???not-null="false"
???length="255"
??/>
??<property
???name="CreateTime"
???column="create_time"
???type="timestamp"
???not-null="false"
???length="19"
??/>
??<many-to-one
???name="CreateBy"
???column="create_by"
???class="User"
???not-null="true"
??>
??</many-to-one>
??<many-to-one
???name="Parent"
???column="parent_id"
???class="Board"???
???not-null="false"
???lazy="false">
??</many-to-one>
?

??<set name="Articles" inverse="true" lazy="true" order-by="id">
???<key column="board_id"/>【這里的board_id是后來修改的】
???<one-to-many class="Article"/>
??</set>

??<set name="ChildBoards" inverse="true"? lazy="true" order-by="id">
???<key column="parent_id"/>這里的parent_id是后來修改的】
???<one-to-many class="Board"/>
??</set>


?</class>?
</hibernate-mapping>

//Board.java
package com.lzy.forum.domain;

?


public class Board? {
?private static final long serialVersionUID = 1L;

//? primary key
?private java.lang.Integer id;

?// fields
?private java.lang.String name;
?private java.lang.String remark;
?private java.util.Date createTime;

?// many to one
?private com.lzy.forum.domain.User createBy;
?private com.lzy.forum.domain.Board parent;

?// collections
?private java.util.Set<com.lzy.forum.domain.Article> articles;
?private java.util.Set<com.lzy.forum.domain.Board> childBoards;
?
?
?public java.util.Set<com.lzy.forum.domain.Article> getArticles() {
??return articles;
?}
?public void setArticles(java.util.Set<com.lzy.forum.domain.Article> articles) {
??this.articles = articles;
?}
?public java.util.Set<com.lzy.forum.domain.Board> getChildBoards() {
??return childBoards;
?}
?public void setChildBoards(java.util.Set<com.lzy.forum.domain.Board> childBoards) {
??this.childBoards = childBoards;
?}
?public com.lzy.forum.domain.User getCreateBy() {
??return createBy;
?}
?public void setCreateBy(com.lzy.forum.domain.User createBy) {
??this.createBy = createBy;
?}
?public java.util.Date getCreateTime() {
??return createTime;
?}
?public void setCreateTime(java.util.Date createTime) {
??this.createTime = createTime;
?}
?public java.lang.Integer getId() {
??return id;
?}
?public void setId(java.lang.Integer id) {
??this.id = id;
?}
?public java.lang.String getName() {
??return name;
?}
?public void setName(java.lang.String name) {
??this.name = name;
?}
?public com.lzy.forum.domain.Board getParent() {
??return parent;
?}
?public void setParent(com.lzy.forum.domain.Board parent) {
??this.parent = parent;
?}
?public java.lang.String getRemark() {
??return remark;
?}
?public void setRemark(java.lang.String remark) {
??this.remark = remark;
?}


}

//Article.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
?"-//Hibernate/Hibernate Mapping DTD//EN"
?"
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd " >

<hibernate-mapping package="com.lzy.forum.domain">
?<class
??name="Article"
??table="article"
?>
??<meta attribute="sync-DAO">false</meta>
??<id
???name="Id"
???type="integer"
???column="id"
??>
???<generator class="native"/>
??</id>

??<property
???name="ArticleType"
???column="article_type"
???type="integer"
???not-null="true"
???length="11"
??/>
??<property
???name="Title"
???column="title"
???type="string"
???not-null="false"
???length="255"
??/>
??<property
???name="Body"
???column="body"
???type="string"
???not-null="false"
??/>
??<property
???name="Hits"
???column="hits"
???type="integer"
???not-null="false"
???length="10"
??/>
??<property
???name="Bytes"
???column="bytes"
???type="integer"
???not-null="false"
???length="10"
??/>
??<property
???name="CreateTime"
???column="create_time"
???type="timestamp"
???not-null="false"
???length="19"
??/>
??<property
???name="LastUpdateTime"
???column="last_update_time"
???type="timestamp"
???not-null="false"
???length="19"
??/>
??<many-to-one
???name="LastUpdateBy"
???column="last_update_by"
???class="User"
???not-null="true"
??>
??</many-to-one>
??<many-to-one
???name="CreateBy"
???column="create_by"
???class="User"
???not-null="true"
??>
??</many-to-one>
??<many-to-one
???name="Parent"
???column="parent_id"
???class="Article"
???not-null="false"
??>
??</many-to-one>
??<many-to-one
???name="Board"
???column="board_id"
???class="Board"
???not-null="true"
??>
??</many-to-one>
?

??<set name="Articles" inverse="true" lazy="false" order-by="id">
???<key column="parent_id"/>【這里的parent_id是后來修改的】
???<one-to-many class="Article"/>
??</set>


?</class>?
</hibernate-mapping>



//Article.java
package com.lzy.forum.domain;

import java.util.Date;

?


public class Article? {
?private static final long serialVersionUID = 1L;
?// primary key
?private java.lang.Integer id;

?// fields
?private java.lang.Integer articleType;
?private java.lang.String title;
?private java.lang.String body;
?private java.lang.Integer hits;
?private java.lang.Integer bytes;
?private java.util.Date lastUpdateTime;
?private java.util.Date createTime;
?

?// many to one
?private com.lzy.forum.domain.User lastUpdateBy;
?private com.lzy.forum.domain.User createBy;
?private com.lzy.forum.domain.Article parent;
?private com.lzy.forum.domain.Board board;

?// collections
?private java.util.Set<com.lzy.forum.domain.Article> articles;

?public java.util.Set<com.lzy.forum.domain.Article> getArticles() {
??return articles;
?}

?public void setArticles(java.util.Set<com.lzy.forum.domain.Article> articles) {
??this.articles = articles;
?}

?public java.lang.Integer getArticleType() {
??return articleType;
?}

?public void setArticleType(java.lang.Integer articleType) {
??this.articleType = articleType;
?}

?public com.lzy.forum.domain.Board getBoard() {
??return board;
?}

?public void setBoard(com.lzy.forum.domain.Board board) {
??this.board = board;
?}

?public java.lang.String getBody() {
??return body;
?}

?public void setBody(java.lang.String body) {
??this.body = body;
?}

?public java.lang.Integer getBytes() {
??return bytes;
?}

?public void setBytes(java.lang.Integer bytes) {
??this.bytes = bytes;
?}

?public com.lzy.forum.domain.User getCreateBy() {
??return createBy;
?}

?public void setCreateBy(com.lzy.forum.domain.User createBy) {
??this.createBy = createBy;
?}

?public java.lang.Integer getHits() {
??return hits;
?}

?public void setHits(java.lang.Integer hits) {
??this.hits = hits;
?}

?public java.lang.Integer getId() {
??return id;
?}

?public void setId(java.lang.Integer id) {
??this.id = id;
?}

?public com.lzy.forum.domain.User getLastUpdateBy() {
??return lastUpdateBy;
?}

?public void setLastUpdateBy(com.lzy.forum.domain.User lastUpdateBy) {
??this.lastUpdateBy = lastUpdateBy;
?}

?public java.util.Date getLastUpdateTime() {
??return lastUpdateTime;
?}

?public void setLastUpdateTime(java.util.Date lastUpdateTime) {
??this.lastUpdateTime = lastUpdateTime;
?}

?public com.lzy.forum.domain.Article getParent() {
??return parent;
?}

?public void setParent(com.lzy.forum.domain.Article parent) {
??this.parent = parent;
?}

?public java.lang.String getTitle() {
??return title;
?}

?public void setTitle(java.lang.String title) {
??this.title = title;
?}
?public java.util.Date getCreateTime(){
??return createTime;
?}

?public void setCreateTime(java.util.Date createTime) {
??// TODO Auto-generated method stub
??this.createTime = createTime;
?}
?

}

接下來將會在web中加入Spring支持和為實體類提供DAO支持。

Spring和Struts結合有幾種方法,我選了最常用的PlugIn方式,在struts-config.xml中加入

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
??????<set-property property="contextConfigLocation"
?????????? ?value="/WEB-INF/action-servlet.xml" />
?</plug-in>

WEB-INF目錄下的action-servlet.xml就是Spring的配置文件,下面給出的是整個的action-servlet.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

//Data Source

?<bean id="dataSource"
??class="org.springframework.jdbc.datasource.DriverManagerDataSource">
??<property name="driverClassName">
???<value>com.mysql.jdbc.Driver</value>
??</property>
??<property name="url">
???<value>jdbc:mysql://localhost:3306/forum</value>
??</property>
??<property name="username">
???<value>test</value>
??</property>
??<property name="password">
???<null />
??</property>
?</bean>

// For Hibernate
?<bean id="sessionFactory"
??class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
??<property name="dataSource">
???<ref local="dataSource" />
??</property>
??<property name="mappingResources">
???<list>
????<value>com/lzy/forum/domain/User.hbm.xml</value>
????<value>com/lzy/forum/domain/Article.hbm.xml</value>
????<value>com/lzy/forum/domain/Board.hbm.xml</value>
???</list>
??</property>
??<property name="hibernateProperties">
???<props>
????<prop key="hibernate.dialect">
?????org.hibernate.dialect.MySQLDialect
????</prop>
????<prop key="hibernate.show_sql">true</prop>
???</props>
??</property>
?</bean>

?<bean id="transactionManager"
??class="org.springframework.orm.hibernate3.HibernateTransactionManager">
??<property name="sessionFactory">
???<ref local="sessionFactory" />
??</property>
?</bean>

?

// For DAO
?<bean id="userDAO"
??class="com.lzy.forum.dao.impl.UserDAOHibernate">
??<property name="sessionFactory">
???<ref local="sessionFactory" />
??</property>
?</bean>

?

?<bean id="boardDAO"
??class="com.lzy.forum.dao.impl.BoardDAOHibernate">
??<property name="sessionFactory">
???<ref local="sessionFactory" />
??</property>
?</bean>

?<bean id="articleDAO"
??class="com.lzy.forum.dao.impl.ArticleDAOHibernate">
??<property name="sessionFactory">
???<ref local="sessionFactory" />
??</property>
?</bean>

//For Struts Action

?<bean name="/regist" class="com.lzy.forum.action.RegistAction"
??singleton="false">
??<property name="userDAO">
???<ref local="userDAO" />
??</property>

?</bean>


?<bean name="/login" class="com.lzy.forum.action.LoginAction"
??singleton="false">
??<property name="userDAO">
???<ref local="userDAO" />
??</property>

?</bean>

?<bean name="/boardManage"
??class="com.lzy.forum.action.BoardManageAction" singleton="false">
??<property name="userDAO">
???<ref local="userDAO" />
??</property>
??<property name="boardDAO">
???<ref local="boardDAO" />
??</property>

?</bean>

?<bean name="/boardNavigate"
??class="com.lzy.forum.action.BoardNavigateAction" singleton="false">
??<property name="boardDAO">
???<ref local="boardDAO" />
??</property>

?</bean>

?<bean name="/boardDisplay"
??class="com.lzy.forum.action.BoardDisplayAction" singleton="false">
??<property name="boardDAO">
???<ref local="boardDAO" />
??</property>

?</bean>

?<bean name="/articleManage"
??class="com.lzy.forum.action.ArticleManageAction" singleton="false">
??<property name="userDAO">
???<ref local="userDAO" />
??</property>
??<property name="boardDAO">
???<ref local="boardDAO" />
??</property>
??<property name="articleDAO">
???<ref local="articleDAO" />
??</property>


?</bean>


</beans>

經過這樣的配置之后,Hibernate事務交由Spring管理,sessionFactory從Spring容器獲得。下面通過其中的一個DAO實例來看看這樣做帶來的方便。


//BoardDAO.java

package com.lzy.forum.dao;

import java.util.ArrayList;

import com.lzy.forum.domain.Board;

public interface BoardDAO {
?
?public boolean isBoardExist(String name);
?
?public void addBoard(Board board);
?
?public void deleteBoard(Board board);
?
?public Board loadBoard(int id);
?
?public Board loadBoard(String name);
?
?public Board loadBoardWithArticles(int id);
?
?public ArrayList getRootBoardsList();
?
?
?
}


//BoardDAOHibernate.java

package com.lzy.forum.dao.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Set;

import org.hibernate.Hibernate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.lzy.forum.dao.BoardDAO;
import com.lzy.forum.domain.Board;

public class BoardDAOHibernate extends HibernateDaoSupport implements BoardDAO {

?public void deleteBoard(Board board) {
??// TODO Auto-generated method stub
??this.getHibernateTemplate().delete(board);
?}

?public void addBoard(Board board) {
??// TODO Auto-generated method stub
??this.getHibernateTemplate().saveOrUpdate(board);

?}

?public boolean isBoardExist(String name) {
??// TODO Auto-generated method stub
??ArrayList list = (ArrayList) this.getHibernateTemplate().find(
????"from Board where name = ? ", new Object[] { name });
??if (list.size() > 0) {
???// System.out.println("find it");
???return true;
??}
??return false;
?}

?public Board loadBoard(int id) {
??// TODO Auto-generated method stub
??ArrayList list = (ArrayList) this.getHibernateTemplate().find(
????"from Board where id = ? ", new Object[] { id });

??Board b = null;
??if (list.size() > 0) {
???b = (Board) list.get(0);
??}

??return b;
?}

?public Board loadBoard(String name) {
??// TODO Auto-generated method stub
??ArrayList list = (ArrayList) this.getHibernateTemplate().find(
????"from Board where name = ? ", new Object[] { name });

??Board b = null;
??if (list.size() > 0) {
???b = (Board) list.get(0);
??}

??return b;
?}

?public ArrayList getRootBoardsList() {
??// TODO Auto-generated method stub
??ArrayList list = (ArrayList) this.getHibernateTemplate().find(
????"from Board b left join fetch b.ChildBoards where b.Parent = null order by b.id");
??System.out.println(list.size() + " root boards found ");
??

??ListIterator index = list.listIterator();
??while (index.hasNext()) {

???Board s = (Board) index.next();
???//this.getSession(true);
???//Hibernate.initialize(s.getChildBoards());
???///*
??? Set children? = (Set) s.getChildBoards();
??? Iterator it = children.iterator();
???
??? while(it.hasNext()){
??? Board b = (Board)it.next();
??? //Hibernate.initialize(b);
??? System.out.println(b.getName());
??? }
??? //*/

???//System.out.println(children.size() + "child(ren) found ");
???//s.setChildBoards(s.getChildBoards());
??}

??return list;
?}

?public Board loadBoardWithArticles(int id) {
??// TODO Auto-generated method stub
??ArrayList list = (ArrayList) this.getHibernateTemplate().find(
????"from Board b left join fetch b.Articles where b.Id = ? ", new Object[] { id });

??Board b = null;
??if (list.size() > 0) {
???b = (Board) list.get(0);
??}

??return b;

?}


}


BoardDAOHibernate繼承 HibernateDaoSupport后,通過getHibernateTemplate()得到一個HibernateTemplate實例,然后執行CRUD操作,非常簡單。需要注意的是,由于執行一次CRUD操作后,Hibernate session關閉,如果有使用延遲加載策略的對象沒有加載,在后面的Web層很容易出現如下錯誤:
failed to lazily initialize a collection of role
從網上搜到的解決方法是Open Session In View,
<filter>
???? <filter-name>hibernateFilter</filter-name>
???? <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
???? </filter-class>

???? <!-- singleSession默認為true,若設為false則等于沒用OpenSessionInView -->
??? <init-param>
?????? <param-name>singleSession</param-name>
?????? <param-value>true</param-value>
??? </init-param>
? </filter>

?? <filter-mapping>
???? <filter-name>hibernateFilter</filter-name>
???? <url-pattern>*.do</url-pattern>
?? </filter-mapping>
我試了試,還是有一些問題,所以后來還是放棄了這種方法,所有在Web層中需要的對象都必須在Business層中加載完成。如下面的代碼所示:

ArrayList list = (ArrayList) this.getHibernateTemplate().find(
????"from Board b left join fetch b.Articles where b.Id = ? ", new Object[] { id });


這樣Hibernate和Spring的結合也算完成了。其他的一些DAO類和實現代碼我沒有給出,但是大同小異,和Board的實現類似。


最后將是Struts 和Spring的結合,將在下一篇給出。

前面通過PlugIn我們實現了Spring Context的加載,不過僅僅加載Context并沒有什么實際
意義,我們還需要修改配置,將Struts Action交給Spring容器進行管理。下面將通過一個Regsit
實例加以說明。

首先準備好regist.jsp和login.jsp,在regist.jsp中 的form有name,password,password2,email域。

在struts-config.xml中添加配置:

<form-bean name="registForm" type="com.lzy.forum.form.RegistForm" />

<action path="/regist" name="registForm"
type="org.springframework.web.struts.DelegatingActionProxy"

validate="true" input="/regist.jsp" scope="request">
<forward name="failure" path="/regist.jsp" />
<forward name="success" path="/login.jsp" />
</action>


RegistForm,RegistAction按照原來Struts的方法去寫,我在RegistAction中加入了一個UserDAO對象
userDAO,這個對象由Spring注入。

<bean name="/regist" class="com.lzy.forum.action.RegistAction"
singleton="false">
<property name="userDAO">
<ref local="userDAO" />
</property>
</bean>

基本上SSH的架構已經完成,經確認后可以自己測試一下了。



liaojiyong 2006-07-21 01:45 發表評論
]]>
Spring之Hello World (轉)http://m.tkk7.com/liaojiyong/archive/2006/07/21/59318.htmlliaojiyongliaojiyongThu, 20 Jul 2006 17:41:00 GMThttp://m.tkk7.com/liaojiyong/archive/2006/07/21/59318.htmlhttp://m.tkk7.com/liaojiyong/comments/59318.htmlhttp://m.tkk7.com/liaojiyong/archive/2006/07/21/59318.html#Feedback0http://m.tkk7.com/liaojiyong/comments/commentRss/59318.htmlhttp://m.tkk7.com/liaojiyong/services/trackbacks/59318.html Spring之Hello World

1.下載Spring相關的開發包
下載地址:http://sourceforge.net/project/showfiles.php?group_id=73357
有spring-framework-1.2.6-with-dependencies.zip,一個是spring-framework-1.2.6.zip,最好下載with-dependencies的,里面有另外一些附加包,下載后解壓縮,dist目錄下是spring自身的jar,lib目錄下是附加的jar。
2.新建Java Project,將spring.jar(dist目錄下)和commons-logging.jar(lib目錄下)添加到project的build path中。
3.新建POJO Bean類:HelloBean
//HelloBean.java
/**
?*
?*/
package com.lzy;

/**
?* @author lzy
?*
?*/
public class HelloBean{
?
?private String hello;
?
?public void sayHello(){
??System.out.println(this.getHello());
?}

?/**
? * @return Returns the hello.
? */
?public String getHello() {
??return hello;
?}

?/**
? * @param hello The hello to set.
? */
?public void setHello(String hello) {
??this.hello = hello;
?}
?

}


4.新建文件bean.xml,將在這個XML文件中為一個HelloBean的實例的hello屬性賦值。
//bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<description>Spring Quick Start</description>
<bean id="helloBean" class="com.lzy.HelloBean">
??<property name="hello">
???<value>hello world</value>
??</property>
</bean>
</beans>

5.新建測試類:TestSpring
//TestSpring.java
/**
?*
?*/
package com.lzy;

import java.util.Locale;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
?* @author lzy
?*
?*/
public class TestSpring {

?/**
? * @param args
? */
?public static void main(String[] args) {
??// TODO Auto-generated method stub
??
??ApplicationContext ctx=new FileSystemXmlApplicationContext("bean.xml");
????HelloBean hello=(HelloBean)ctx.getBean("helloBean");
??hello.sayHello();
?}

}


6.運行測試類:
??? 如果沒有出錯,輸出中將會看到“hello world”。



liaojiyong 2006-07-21 01:41 發表評論
]]>
主站蜘蛛池模板: 亚洲an日韩专区在线| 亚洲欧洲精品无码AV| 又粗又硬又黄又爽的免费视频 | 亚洲AV无码久久精品蜜桃| 99免费在线观看视频| 免费黄色网址网站| 久久免费的精品国产V∧| AV大片在线无码永久免费| 精品久久免费视频| 国产亚洲精品看片在线观看| 亚洲影院在线观看| 亚洲色大成网站www永久网站| 日本中文字幕免费看| 久久这里只精品国产免费10| 中文字幕视频在线免费观看| 在线观看免费视频资源| 亚洲三级高清免费| 亚洲成AV人网址| 久久综合亚洲色一区二区三区| 亚洲精品9999久久久久无码| 9久热精品免费观看视频| 1000部拍拍拍18免费网站| 亚洲成年人啊啊aa在线观看| 亚洲AV无码一区东京热| 亚洲天然素人无码专区| 一级有奶水毛片免费看| 久久精品免费一区二区喷潮| 毛茸茸bbw亚洲人| 激情五月亚洲色图| 97在线免费视频| 成熟女人特级毛片www免费| 在线观看亚洲成人| 久久夜色精品国产噜噜亚洲a| 一区二区三区免费电影| 免费看黄的成人APP| 成人免费无码大片a毛片| 亚洲精品色午夜无码专区日韩| 亚洲国产成人精品激情| 国产精品极品美女自在线观看免费| 91精品国产免费久久久久久青草| 免费大黄网站在线看|