在 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-name>contextConfigLocation</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-class>org.springframework.web.context.ContextLoaderListener</listener-class>
18 </listener>
19
20 <filter>
21 <filter-name>encodingFilter</filter-name>
22 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
23 <init-param>
24 <param-name>encoding</param-name>
25 <param-value>UTF-8</param-value>
26 </init-param>
27 </filter>
28
29 <filter-mapping>
30 <filter-name>encodingFilter</filter-name>
31 <url-pattern>*.do</url-pattern>
32 </filter-mapping>
33
34 <servlet>
35 <servlet-name>ideawu</servlet-name>
36 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
37 <load-on-startup>1</load-on-startup>
38 </servlet>
39
40 <servlet-mapping>
41 <servlet-name>ideawu</servlet-name>
42 <url-pattern>*.do</url-pattern>
43 </servlet-mapping>
44
45 <welcome-file-list>
46 <welcome-file>index.jsp</welcome-file>
47 <welcome-file>index.html</welcome-file>
48 </welcome-file-list>
49
50 <jsp-config>
51 <taglib>
52 <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
53 <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
54 </taglib>
55 <taglib>
56 <taglib-uri>http://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>
它配置了以下功能:
因?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>
它配置了以下功能:
上面, 我們?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>
它配置了以下功能:
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)注釋掉了):
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 <title>Hello 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 就可以訪問了。
public String execute (String str) { return (getMessage () + str).toUpperCase () ; } |
<beans> <bean id="TheAction" class="net.chen.spring.qs.UpperAction"> <property name="message"> <value>HeLLo</value> </property> </bean> </beans> |
public void testQuickStart () { ApplicationContext ctx=new FileSystemXmlApplicationContext ("bean.xml"); Action a= (Action) ctx.getBean ("TheAction"); System.out.println (a. execute ("Rod Johnson")); } |
…… HELLO ROD JOHNSON |
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) { …… } } |
TheAction=net.chen.spring.qs.UpperAction TheAction_msg=HeLLo |
本文章比較了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>
開發(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;
?}
?
}
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)后可以自己測試一下了。
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”。