成人在线一区二区三区,久久婷婷国产,久久这里只有精品一区二区http://www.aygfsteel.com/liaojiyong/category/13297.htmlzh-cnFri, 25 May 2007 10:43:23 GMTFri, 25 May 2007 10:43:23 GMT60Spring MVC 開發(fā)快速入門(轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107416.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:51:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107416.htmlhttp://www.aygfsteel.com/liaojiyong/comments/107416.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107416.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/107416.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/107416.html  首先, 我需要在你心里建立起 Spring MVC 的基本概念. 基于 Spring 的 Web 應(yīng)用程序接收到 http://localhost:8080/hello.do(事實(shí)上請(qǐng)求路徑是 /hello.do) 的請(qǐng)求后, Spring 將這個(gè)請(qǐng)求交給一個(gè)名為 helloController 的程序進(jìn)行處理, helloController 再調(diào)用 一個(gè)名為 hello.jsp 的 jsp 文件生成 HTML 代碼發(fā)給用戶的瀏覽器顯示. 上面的名稱(/hello.do, helloController, hello.jsp) 都是變量, 你可以更改.

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

  好了, 我們開始吧. 首先我們需要一個(gè)放在 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 標(biāo)簽), 它是一個(gè) Java Servlet 程序. 我們將它命名為 ideawu. 然后我們?cè)倥渲?Servlet 映射(servlet-mapping 標(biāo)簽), 也就是你希望哪些請(qǐng)求被DispatcherServlet處理. 這里, 我們?cè)O(shè)置后綴名為 do(*.do) 的所有URL請(qǐng)求都被名為 ideawu 的 DispatcherServlet 的程序處理. 選擇 .do 只是一個(gè)習(xí)慣,但是你不要選擇 .html! 雖然《Spring in Action》選擇了 .html, 但是那是一種非常糟糕的作法, 特別是你整合 ApacheTomcat 的時(shí)候.
  • 配置 CharacterEncodingFilter (filter 標(biāo)簽), 否則你會(huì)發(fā)現(xiàn)中文亂碼. 因?yàn)槲业?jsp 和 html 文件都是 UTF-8 編碼的, 所以我在 param-value 標(biāo)簽中設(shè)置了 UTF-8. 估計(jì)你使用的是 GB2312 或者 GBK, 立即轉(zhuǎn)到 UTF-8 上來吧.
  • 分解配置文件. context-param 標(biāo)簽指明我們的配置文件還有 /WEB-INF/database.xml 和 /WEB-INF/applicationContext.xml. ContextLoaderListener(listener 標(biāo)簽) 由此得知配置文件是哪些, 它會(huì)將它們載入.

  因?yàn)槲覀儗?DispatcherServlet 命名為 ideawu, 所以我們?cè)?WEB-INF 目錄下建立一個(gè)名為 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 處理一個(gè)名為 hello 的模板時(shí), 它會(huì)渲染 /WEB-INF/jsp/hello.jsp 文件. 把 jsp 文件放到 /WEB-INF/jsp/ 目錄下是被鼓勵(lì)的, 這樣可以防止用戶不經(jīng)過 Controller 直接訪問 jsp 文件從而出錯(cuò)(有些頑皮的人很喜歡這樣做).
  • 配置 SimpleUrlHandlerMapping, 在上面的配置文件中, /hello.do 的請(qǐng)求將被 helloController 處理. "/hello.do"和"helloController" 是變量, 你可以更改. 但是你注意到了嗎, hello.do 以 .do 作為后綴名. 如果這里(本文的條件下)你 不使用.do 作為后綴名, 就沒有程序來處理這個(gè)請(qǐng)求了. 因?yàn)?DispatcherServlet 將收到的請(qǐng)求轉(zhuǎn)交給 SimpleUrlHandlerMapping, DispatcherServlet 收不到的請(qǐng)求, SimpleUrlHandlerMapping 當(dāng)然也收不到了. 你可以在 props 標(biāo)簽內(nèi)配置多個(gè) prop 標(biāo)簽.
  • 我們將在后面編寫 com.ideawu.HelloController 類.


上面, 我們?cè)?web.xml 文件中告訴 ContextLoaderListener, 我們還有另外兩個(gè)配置文件 /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 標(biāo)簽中配置多個(gè) value 標(biāo)簽.

  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>

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

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

  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

  現(xiàn)在, 我們來編寫 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() 設(shè)置的對(duì)象我們可以在 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

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



]]>
Spring+Hibernate+Struts技術(shù)的一個(gè)分頁程序(轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107408.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:43:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107408.htmlhttp://www.aygfsteel.com/liaojiyong/comments/107408.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107408.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/107408.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/107408.html 我用的是Spring+Hibernate+Struts框架:

這是我的DAO的核心代碼
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
// 用Spring支持的Hibernate方法,使Hibernate對(duì)數(shù)據(jù)庫的操作繼續(xù)瘦身
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是每頁記錄數(shù)
{
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); //為了得到總記錄數(shù)
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只是得到頁面的如:總頁數(shù)、供多少頁的信息等一般的翻頁信息;

我在Action中是這樣調(diào)用的
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.");
}

//其中g(shù)etOfficeService()只是提供接口服務(wù)的方法。


我的表現(xiàn)頁面是這樣的

<%@ 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里為了得到總計(jì)錄數(shù)執(zhí)行了一次次數(shù)據(jù)表查詢HSQL;得到數(shù)據(jù)又執(zhí)行了一次HSQL,我覺得這樣好像有些不太好,大家覺得怎樣?大家提出寶貴的意見吧!



]]>
反向控制和面向切面編程在Spring的應(yīng)用(轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107404.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:31:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107404.htmlhttp://www.aygfsteel.com/liaojiyong/comments/107404.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107404.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/107404.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/107404.html
  關(guān)鍵詞 Spring;反向控制;面向切面編程;POJO;依賴注入

  引言

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

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

  1、Spring IoC 1.1 反向控制原理

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

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

  1.2 IoC在Spring中的實(shí)現(xiàn)

  任何重要的系統(tǒng)都需要至少兩個(gè)相互合作的類來完成業(yè)務(wù)邏輯。通常,每個(gè)對(duì)象都要自己負(fù)責(zé)得到它的合作(依賴)對(duì)象。你會(huì)發(fā)現(xiàn),這樣會(huì)導(dǎo)致代碼耦合度高而且難于測試。使用IoC,對(duì)象的依賴都是在對(duì)象創(chuàng)建時(shí)由負(fù)責(zé)協(xié)調(diào)系統(tǒng)中各個(gè)對(duì)象的外部實(shí)體提供的,這樣使軟件組件松散連接成為可能。下面示意了Spring IoC 應(yīng)用,步驟如下:

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

  (2)類UpperAction實(shí)現(xiàn)Action接口,在此類中,定義一個(gè)String型的域message,并提供相應(yīng)的setter和getter方法,實(shí)現(xiàn)的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"));
}

  上面的測試代碼中,我們根據(jù)"bean.xml"創(chuàng)建了一個(gè)ApplicationContext實(shí)例,并從此實(shí)例中獲取我們所需的Action實(shí)現(xiàn),運(yùn)行測試代碼,我們看到控制臺(tái)輸出:

……
HELLO ROD JOHNSON

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

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

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

  Spring給我們帶來了如此這般的好處,那么,反過來,讓我們?cè)囅胍幌拢绻皇褂肧pring框架,回到我們傳統(tǒng)的編碼模式,情況會(huì)是怎樣呢?

  首先,我們必須編寫一個(gè)配置文件讀取類,以實(shí)現(xiàn)Message屬性的可配置化。

  其次,得有一個(gè)Factory模式的實(shí)現(xiàn),并結(jié)合配置文件的讀寫完成Action的動(dòng)態(tài)加載。于是,我們實(shí)現(xiàn)了一個(gè)ActionFactory來實(shí)現(xiàn)這個(gè)功能:

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

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

  ……

  往往這些系統(tǒng)開發(fā)中最常見的需求,會(huì)導(dǎo)致我們的代碼迅速膨脹,而Spring IoC的出現(xiàn),則大大緩解了這樣的窘境。通過以上實(shí)例,可以看出,Spring IoC為我們提供了如下幾方面的優(yōu)勢:

  (1)應(yīng)用組件不需要在運(yùn)行時(shí)尋找其協(xié)作者,因此更易于開發(fā)和編寫應(yīng)用;

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

  (3)通常,在借助于IoC容器關(guān)系業(yè)務(wù)對(duì)象的前提下,很少需要使用具體IoC容器提供的API,這使得集成現(xiàn)有的遺留應(yīng)用成為可能。

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

]]>
Spring的事務(wù)管理2.0與1.2.8的區(qū)別(轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107400.htmlliaojiyongliaojiyongFri, 30 Mar 2007 01:24:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107400.htmlhttp://www.aygfsteel.com/liaojiyong/comments/107400.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2007/03/30/107400.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/107400.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/107400.html

本文章比較了Spring自己帶的JPetStore的例子,通過配置文件詳細(xì)講解了,Spring1.2.8與2.0如何實(shí)現(xiàn)聲明式事務(wù)管理。


Spring1.2.8


Spring以前對(duì)一個(gè)事務(wù)攔截要通過代理實(shí)現(xiàn)下面的配置文件是從不同的文件中找來的,不是單獨(dú)的一個(gè)Spring配置文件。


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


?<!-- 聲明一個(gè)抽象Bean,這個(gè)Bean是不能實(shí)例化的,提供給其它需要AOP事務(wù)的Bean用,其它需要AOP事務(wù)的只要繼承這個(gè)Bean就會(huì)被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>

?<!-- 繼承之前實(shí)現(xiàn)的抽象Bean,讓這個(gè)Bean通過代理工廠生成,交給AOP托管。至于哪些方法被接管在控制Bean中已經(jīng)配置了-->
?<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>


最早發(fā)表于 http://www.openj.cn

Spring2.0?

?下面的配置與上面的配置完全對(duì)應(yīng)

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

?<!--這一處與之前有了變化,在1.2.8版本中,此處的Bean被聲明為由一個(gè)FactoryBean生成,而此處只是一個(gè)普通的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>


?<!---下面的兩處配置,才是整個(gè)事務(wù)AOP的核心,在1.2.8版本中,通過FactoryBean把事務(wù)對(duì)象(dataSource),與需要進(jìn)行事務(wù)控制的對(duì)象PetStoreImpl串起來,對(duì)PetStoreImpl有侵入性----->
?<!---而在之前的兩處配置中,事務(wù)對(duì)象(dataSource)與,需要進(jìn)行事務(wù)控制的對(duì)象PetStoreImpl沒有什么關(guān)系,它們的關(guān)系全部體現(xiàn)在下面的兩處配置中----->
?
?
?<!---pointcut屬性定義了哪此點(diǎn)需要去攔截,此處的配置的意思是所有的PetStoreFacade接口中的方法都要攔截,而攔截之后要如何處理則由advice-ref指定的Bean處理----->
?<!---配置文件中各個(gè)屬性的含義參考: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屬性原配置中沒有,如果缺少此配置,默認(rèn)值就是“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>



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


  詳細(xì)錯(cuò)誤信息:
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 (系統(tǒng)找不到指定的路徑。)
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 (系統(tǒng)找不到指定的路徑。)
?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");
?}
?
出錯(cuò)原因:
  這個(gè)問題是筆者在參與開發(fā)EasyJWeb及EasyDBO框架中遇到過的問題,因此很容易就找到了問題的所在。Java的Class.getResource(name)返回的是一個(gè)URL,而URL.getFile默認(rèn)情況下返回的是經(jīng)過URL編碼后的字符,會(huì)把中文等特殊字符變成類似%e6的形式。而一般io構(gòu)造路徑是沒有自動(dòng)解碼功能的,所以在中文路徑下要出現(xiàn)錯(cuò)誤。
?
解決辦法:
  在使用URL.getFile返回的路徑時(shí),使用前需要使用java.net.URLDecoder對(duì)路徑進(jìn)行一次解碼操作。修改后的且能通過測試的方法如下:
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");
?}
?
小結(jié):
  由于Spring開源項(xiàng)目的開發(fā)團(tuán)隊(duì)中,除了一些喜歡跟在Rod大叔的屁股后面唱中文版贊歌的“春迷”以外,當(dāng)前似乎還沒有中國人參與到正式的Spring開發(fā)小組中。因此,也許沒有在中文路徑下運(yùn)行過測試用例,導(dǎo)致我這樣的Spring初學(xué)者一不小心就遇上這樣的問題。
  問題是解決了,但是卻是一種比較罕見的方式,而且Spring開發(fā)小組事先也許沒有預(yù)想到或是故意忽略掉的問題,因此,可以稱得上是“沒商量”的中文問題。


]]>
Spring技巧之簡潔配置(轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2007/01/11/93171.htmlliaojiyongliaojiyongThu, 11 Jan 2007 07:00:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2007/01/11/93171.htmlhttp://www.aygfsteel.com/liaojiyong/comments/93171.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2007/01/11/93171.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/93171.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/93171.html??????配置Apache的一個(gè)數(shù)據(jù)源連接池,在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>兩個(gè)標(biāo)簽作為其父級(jí)<bean>標(biāo)簽的一個(gè)屬性來定義,這樣使得配置文件更加簡潔,如下所示:
<?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中還有一個(gè)非常實(shí)用的解析器,SimplePropertyNamespaceHandle,若配置文件中引用http://www.springframework.org/schema/p命令空間,則將會(huì)使用SimplePropertyNamespaceHandle來處理這個(gè)Bean的定義,可以在Spring2.0中的Bean中以更簡單的方式配置設(shè)值方法注入,如下所示:
<?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屬性來引用另外一個(gè)Bean。
????如,Spring2.0以前的一個(gè)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比以前的版本配置更加靈活、簡潔,如果手工書寫配置,則比較實(shí)用。當(dāng)然,老的配置方式有很多開發(fā)工具如MyEclipse等都能識(shí)別,不需要我們動(dòng)手一點(diǎn)一點(diǎn)的錄入配置文件,大多數(shù)工具對(duì)新的配置方式還不能識(shí)別,因此,請(qǐng)根據(jù)實(shí)際情況酌情使用。

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

]]>
Spring+hibernate 單元測試框架總結(jié) (轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2006/09/01/67081.htmlliaojiyongliaojiyongFri, 01 Sep 2006 05:43:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/09/01/67081.htmlhttp://www.aygfsteel.com/liaojiyong/comments/67081.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/09/01/67081.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/67081.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/67081.html?這兩天的花費(fèi)了一些時(shí)間在使用spring-mock進(jìn)行spring的單元測試問題上,基本上對(duì)這個(gè)問題有了一個(gè)完整的解決方案
下面將對(duì)相關(guān)學(xué)習(xí)到和思考到的一些問題進(jìn)行一下整理:
1、首先明確一下問題:要對(duì)什么進(jìn)行單元測試?
我的問題是圍繞這一個(gè)DAO展開,我定義了一個(gè)DAO接口XXXDAO,并且寫了該DAO的實(shí)現(xiàn)XXXDAOImpl,然后使用spring對(duì)接口的實(shí)現(xiàn)進(jìn)行管理:
<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>

現(xiàn)在問題開始明確了,我要對(duì)XXXDAOImpl進(jìn)行單元測試。這里需要指明一個(gè)問題就是單元測試,測試的是有實(shí)現(xiàn)代碼的實(shí)現(xiàn)類,而不是接口。

2、接著是下一個(gè)問題,如何取得Sping的上下文關(guān)系呢?
這里就需要用到spring-mock了,其中有一個(gè)測試基類是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的上下文信息,這樣的話這個(gè)測試用例就可以直接使用spirng中定義的bean了
但是這里需要注意一個(gè)問題*,就是文件路徑的問題,這里為了能夠清楚地說明文件的路徑規(guī)則我引用了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 好了,該到最后一個(gè)問題了,取得Spirng上下問中定義的bean的實(shí)例來進(jìn)行單元測試
這里有兩種方法,一種是定義一個(gè)代測單元的對(duì)象,然后定義好get,set方法,AbstractTransactionalDataSourceSpringContextTests會(huì)自動(dòng)根據(jù)Spring的上下文得到待測單元的具體實(shí)現(xiàn)。
private?ExQueryDAO?exQqueryDAO;
????
????
????
????
/**
?????*?
@return?返回?exQqueryDAO。
?????
*/

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



????
/**
?????*?
@param?exQqueryDAO?要設(shè)置的?exQqueryDAO。
?????
*/

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


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

接下來你就可以用這個(gè)bean的具體實(shí)現(xiàn)對(duì)相關(guān)方法進(jìn)行unittest了



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


最后我對(duì)整體的spring+hibernate的jsf框架進(jìn)行了一下單元測試的框架總結(jié),主要多了一個(gè)基本的BaseTestCase,用于統(tǒng)一讀取applicationContext
單元測試框架.jpg

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


]]>
SpringMVC MultiActionController的使用-最簡化教程(轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2006/09/01/67078.htmlliaojiyongliaojiyongFri, 01 Sep 2006 05:41:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/09/01/67078.htmlhttp://www.aygfsteel.com/liaojiyong/comments/67078.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/09/01/67078.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/67078.htmlhttp://www.aygfsteel.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請(qǐng)求都會(huì)被spring 的DispatcherServlet處理轉(zhuǎn)發(fā)。默認(rèn)情況下DispatcherServlet會(huì)讀取<servlet-name>-servlet.xml文件的配置信息初始化,該文件中urlMapping的定義決定當(dāng)前請(qǐng)求轉(zhuǎn)發(fā)給哪個(gè)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請(qǐng)求由名字為controller的控制器來處理,因?yàn)槭嵌鄤?dòng)作處理器,所以要定義MethodNameResolver來告訴springMVC應(yīng)該調(diào)用controller的哪個(gè)方法,這里用的是InternalPathMethodNameResolver,該方法名解釋器會(huì)把整個(gè)URL中最后一個(gè)"/"和最后一個(gè)"."之間的部分作為要調(diào)用的方法名

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""你調(diào)用的是方法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""你調(diào)用的是方法2");
        
return new ModelAndView("/index.jsp""model", model);
    }

}


通過配置文件,訪問上面這個(gè)controller中某個(gè)方法的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>
因?yàn)?font color=#0000ff>InternalPathMethodNameResolver方法名解釋器會(huì)把整個(gè)URL中最后一個(gè)"/"和最后一個(gè)"."之間的部分作為要調(diào)用的方法名,所以你可以在這個(gè)URL后面加任意文件格式的后綴,比如:
localhost:8080/page/controller/method1.jsp

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


另:開發(fā)環(huán)境:MyEclipse5.0M2+tomcat5.5
  需要用到spring.jar和jstl.jar兩個(gè)包。

附:源代碼下載


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


開發(fā)環(huán)境的塔建我就不多說了,具體可以參考我以前的幾篇日志。

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


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

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


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來生成映射文件和實(shí)體類,然后對(duì)生成的類進(jìn)行修改(刪掉了生成的Base類),
實(shí)際上Hibernate Sychonizer生成的映射文件也有錯(cuò)誤,需要修改,我也是后來在使用中發(fā)現(xiàn)的。

//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生成的有錯(cuò),后面有幾處同樣的錯(cuò)誤】
???<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;
?}
?

}

接下來將會(huì)在web中加入Spring支持和為實(shí)體類提供DAO支持。

Spring和Struts結(jié)合有幾種方法,我選了最常用的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的配置文件,下面給出的是整個(gè)的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>

經(jīng)過這樣的配置之后,Hibernate事務(wù)交由Spring管理,sessionFactory從Spring容器獲得。下面通過其中的一個(gè)DAO實(shí)例來看看這樣做帶來的方便。


//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()得到一個(gè)HibernateTemplate實(shí)例,然后執(zhí)行CRUD操作,非常簡單。需要注意的是,由于執(zhí)行一次CRUD操作后,Hibernate session關(guān)閉,如果有使用延遲加載策略的對(duì)象沒有加載,在后面的Web層很容易出現(xiàn)如下錯(cuò)誤:
failed to lazily initialize a collection of role
從網(wǎng)上搜到的解決方法是Open Session In View,
<filter>
???? <filter-name>hibernateFilter</filter-name>
???? <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
???? </filter-class>

???? <!-- singleSession默認(rèn)為true,若設(shè)為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層中需要的對(duì)象都必須在Business層中加載完成。如下面的代碼所示:

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


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


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

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

首先準(zhǔn)備好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中加入了一個(gè)UserDAO對(duì)象
userDAO,這個(gè)對(duì)象由Spring注入。

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

基本上SSH的架構(gòu)已經(jīng)完成,經(jīng)確認(rèn)后可以自己測試一下了。



]]>
Spring之Hello World (轉(zhuǎn))http://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59318.htmlliaojiyongliaojiyongThu, 20 Jul 2006 17:41:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59318.htmlhttp://www.aygfsteel.com/liaojiyong/comments/59318.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59318.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/59318.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/59318.html Spring之Hello World

1.下載Spring相關(guān)的開發(fā)包
下載地址:http://sourceforge.net/project/showfiles.php?group_id=73357
有spring-framework-1.2.6-with-dependencies.zip,一個(gè)是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,將在這個(gè)XML文件中為一個(gè)HelloBean的實(shí)例的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.運(yùn)行測試類:
??? 如果沒有出錯(cuò),輸出中將會(huì)看到“hello world”。



]]>
主站蜘蛛池模板: 石渠县| 桃源县| 衡水市| 远安县| 抚宁县| 冕宁县| 江西省| 越西县| 武胜县| 左权县| 无极县| 姜堰市| 蒙阴县| 韶关市| 青州市| 霍邱县| 明溪县| 扬州市| 东乌珠穆沁旗| 新竹县| 弥渡县| 永顺县| 华安县| 阜阳市| 聊城市| 台东市| 宜宾县| 永修县| 达孜县| 青冈县| 化德县| 宣汉县| 曲周县| 安化县| 新疆| 漳浦县| 夹江县| 巴马| 赤城县| 东海县| 岱山县|