Struts2+Spring+Hibernate整合
本文主要目的是通過(guò)整合Struts2,Spring,Hibernate,開(kāi)發(fā)出一個(gè)簡(jiǎn)易的圖書(shū)管理系統(tǒng),該系統(tǒng)具有增刪改查的基本功能。 ![]() 把jar包拷貝到WEB-INF/lib下,然后在工程中引用這些包。 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- spring的applicationContext載入 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/*.xml</param-value> </context-param> <!-- 定義log4j配置文件所在位置 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/classes/log4j.properties</param-value> </context-param> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <!-- 這里用的是spring自帶的編碼過(guò)濾器,不用自己寫(xiě)了,其中主要代碼 是request.setCharacterEncoding(encoding)和 response.setCharacterEncoding(encoding),對(duì)請(qǐng)求和響應(yīng)設(shè)置編碼。 有兩個(gè)參數(shù):encoding和forceEncoding,其中forceEncoding默認(rèn)是false, (此種情況不能改變r(jià)esponse的編碼方式)如果設(shè)置成true則不管請(qǐng)求是否已有編碼 都強(qiáng)制轉(zhuǎn)換成encoding指定的編碼,同時(shí)在響應(yīng)可設(shè)置編碼的前提下設(shè)置響應(yīng)編碼。 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- web應(yīng)用關(guān)閉時(shí)IntrospectorCleanupListener類(lèi)負(fù)責(zé)對(duì)javabean 內(nèi)省緩存進(jìn)行清除;該類(lèi)實(shí)現(xiàn)接口ServletContextListener, 對(duì)緩存在context中的javabean類(lèi)進(jìn)行清除操作的。 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!-- Listener log4jConfigLocation --> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!-- 定義session的超時(shí)時(shí)間,單位為分鐘 --> <session-config> <session-timeout>10</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> 幾點(diǎn)需要注意的地方:1)對(duì)于spring的配置文件和log4j日志配置文件的讀取我們用的是spring的ContextLoaderListener和Log4jConfigListener這兩個(gè)個(gè)監(jiān)聽(tīng)器。2)對(duì)瀏覽器發(fā)送的請(qǐng)求,通過(guò)配置的Struts2的過(guò)濾器(FilterDispatcher)可以對(duì)不同的url進(jìn)行過(guò)濾,此處我們配置處理該web應(yīng)用的所有請(qǐng)求。3)配置了一個(gè)spring自帶的編碼過(guò)濾器,用來(lái)處理請(qǐng)求和響應(yīng)的編碼,本應(yīng)用配置對(duì)所有請(qǐng)求和響應(yīng)都采用該編碼過(guò)濾器,這里我們采用的utf-8。 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- 該處的default-autowire對(duì)所有bean提供一種默認(rèn)的自動(dòng)裝配方式,如果bean需要不同的方式, 可以在bean中配置配置autowire屬性。自動(dòng)裝配方式有以下幾種: 1) no 不使用自動(dòng)裝配。必須通過(guò)ref元素指定依賴(lài),這是默認(rèn)設(shè)置。 2) byName 根據(jù)屬性名自動(dòng)裝配。此選項(xiàng)將檢查容器并根據(jù)名字查找與屬性完全一致的bean,并將其與屬性自動(dòng)裝配。 3) byType 如果容器中存在一個(gè)與指定屬性類(lèi)型相同的bean,那么將與該屬性自動(dòng)裝配。 4) constructor 與byType的方式類(lèi)似,不同之處在于它應(yīng)用于構(gòu)造器參數(shù)。 5) autodetect 通過(guò)bean類(lèi)的自省機(jī)制(introspection)來(lái)決定是使用constructor還是byType方式進(jìn)行自動(dòng)裝配。 --> <beans> <!-- 如果實(shí)體定義用的是xml配置文件,則sessionFactory的class 應(yīng)為"org.springframework.orm.hibernate3.LocalSessionFactoryBean" --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> <!-- 配置多個(gè)hibernate.cfg.xml <property name="configLocations"> <list> <value>classpath:hibernate_admin1.cfg.xml</value> <value>classpath:hibernate_admin2.cfg.xml</value> </list> </property> --> </bean> <!-- 配置事務(wù)管理 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 這里的abstract屬性說(shuō)明該bean是抽象的,不能實(shí)例化,只能用來(lái)被繼承,在這里他被BookService繼承 --> <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <!-- PROPAGATION_REQUIRED代表必須在事務(wù)中執(zhí)行,-Exception表示 當(dāng)有Exception拋出時(shí)事務(wù)回滾 --> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="persist*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="remove*">PROPAGATION_REQUIRED,-Exception</prop> </props> </property> </bean> <bean id="BookService" parent="baseTransactionProxy"> <property name="target"> <bean class="com.css.ravollen.sshtest.service.impl.BookServiceImpl"> <property name="dao"> <bean class="com.css.ravollen.sshtest.dao.impl.BookDAOImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </property> </bean> </property> </bean> <bean id="BookAction" class="com.css.ravollen.sshtest.action.BookAction"> <property name="bookService" ref="BookService"></property> </bean> </beans> 這里幾點(diǎn)要注意的地方:1)sessionFactory的真正定義是在hibernate.cfg.xml里面,sessionFactory Bean通過(guò)configLocation屬性提供的路徑去找,因?yàn)閔ibernate.cfg.xml是在/WEB-INF/classes/下,所以可以通過(guò)classpath:hibernate.cfg.xml定位。2)該處配置的sessionFactory是基于Annotation對(duì)實(shí)體進(jìn)行管理的。3)對(duì)于持久化操作可以配置事務(wù)管理機(jī)制保證數(shù)據(jù)的安全和合法,本實(shí)例對(duì)于目標(biāo)類(lèi)(BookServiceImpl)中的以find,persist,remove開(kāi)頭的方法都采用事務(wù)機(jī)制。 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.username">ravollen</property> <property name="hibernate.connection.password">726321</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/book?useUnicode=true&characterEncoding=UTF-8</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <property name="hibernate.show_sql">true</property> <!-- 該屬性默認(rèn)為none,有以下幾種: 1)validate 加載hibernate時(shí),驗(yàn)證創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu) 2) create 每次加載hibernate,重新創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu),這就是導(dǎo)致數(shù)據(jù)庫(kù)表數(shù)據(jù)丟失的原因。 3) create-drop 加載hibernate時(shí)創(chuàng)建,退出是刪除表結(jié)構(gòu) 4) update 加載hibernate自動(dòng)更新數(shù)據(jù)庫(kù)結(jié)構(gòu) --> <!-- <property name="hibernate.hbm2ddl.auto">create</property> --> <!-- 這里由于我們采用的是annotation方式,所以直接指向?qū)嶓w對(duì)應(yīng)的類(lèi)即可,如果是采用實(shí)體配置文件則寫(xiě)成 <mapping resource="com/css/ravollen/sshtest/entity/Book.hbm.xml"></mapping> --> <mapping class="com.css.ravollen.sshtest.entity.Book"></mapping> </session-factory> </hibernate-configuration> 該文件主要配置了數(shù)據(jù)庫(kù)底層連接的一些信息。需要注意的地方有:1)數(shù)據(jù)庫(kù)url需加上useUnicode=true&characterEncoding=UTF-8,可以解決中文亂碼問(wèn)題。(其中&是&的轉(zhuǎn)義符) <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!-- extends說(shuō)明該配置文件繼承自struts-default.xml --> <package name="test" extends="struts-default"> <global-results> <result name="listAllBooks">/WEB-INF/ui/booklist.jsp</result> <result name="bookInfo">/WEB-INF/ui/editBook.jsp</result> </global-results> <action name="LoadBookById" class="BookAction" method="findBookById"></action> <action name="LoadBookByParam" class="BookAction" method="findBookByParam"></action> <action name="LoadAllBooks" class="BookAction" method="findAllBooks"></action> <action name="editBook" class="BookAction" method="loadBook"></action> <action name="saveBook" class="BookAction" method="saveBook"> <!-- 都是struts2的默認(rèn)攔截器 param攔截器 將Request請(qǐng)求的參數(shù)設(shè)置到相應(yīng)Action對(duì)象的屬性中 validation攔截器 實(shí)現(xiàn)使用xml配置文件({Action}-validation.xml)對(duì)Action屬性值進(jìn)行驗(yàn)證 --> <interceptor-ref name="params" /> <interceptor-ref name="validation" /> <result name="input">/editBook.jsp</result> <result name="success" type="redirect">LoadAllBooks.action</result> </action> <action name="removeBook" class="BookAction" method="removeBook"> </action> </package> </struts> 注意這幾項(xiàng):1)package的extends屬性說(shuō)明該配置文件是繼承自strut-default.xml,該配置文件在struts2-core-2.0.11.2.jar包內(nèi)。2)對(duì)于大量重復(fù)的result,我們可以配置成全局的result,可以減少文件冗余。3)在"保存書(shū)"這個(gè)活動(dòng)中,加入了struts2的校驗(yàn)框架,在該action中加入兩個(gè)攔截器"params"和“validation"就可以,此外在該Action的同一級(jí)目錄下新建一個(gè)校驗(yàn)配置文件即可,命名規(guī)則:活動(dòng)名+"-"+方法名+"-"+"validation.xml,如果該校驗(yàn)文件引用了消息文件,則還要在同一級(jí)目錄下建一個(gè).properties的消息文件文件,前綴與活動(dòng)名一樣。(需要對(duì)消息文件進(jìn)行ascii碼轉(zhuǎn)換,命令為 native2ascii "源文件" "新文件") 接口: public interface BookDAO { package com.css.ravollen.sshtest.dao.impl; import java.util.List; public class BookDAOImpl extends HibernateDaoSupport implements BookDAO { public List<Book> findAllBooks() { public Book findBookById(Long id) { public void persistBook(Book book) { public void removeBook(Book book) { public void removeById(final Long id) {
接口: package com.css.ravollen.sshtest.service; public interface BookService { public List<Book> findAllBooks() throws Exception; public void persistBook(Book book) throws Exception; public void removeBook(Book book) throws Exception; public void removeBookById(Long id) throws Exception; 實(shí)現(xiàn)類(lèi): package com.css.ravollen.sshtest.service.impl; public class BookServiceImpl implements BookService { public Book findBookById(Long id) throws Exception { public void persistBook(Book book) throws Exception { public void removeBook(Book book) throws Exception { public void removeBookById(Long id) throws Exception { public BookDAO getDao() { public void setDao(BookDAO dao) { 注意:1)BookServiceImpl實(shí)例通過(guò)ApplicationContext從Spring的上下文中得到。2)BookDAO通過(guò)Spring的IOC注入到里面。 package com.css.ravollen.sshtest.action; /** private static Logger logger = Logger.getLogger(BookAction.class); public Long getBookId() { public void setBookId(Long bookId) { public String getSearchType() { public void setSearchType(String searchType) { public String getSearchContent() { public void setSearchContent(String searchContent) { public String findBookById(Long id) { public int getAddBookFlag() { public void setAddBookFlag(int addBookFlag) { 說(shuō)明一下:1)Struts的攔截器解析前臺(tái)參數(shù)然后將值賦給Action里的對(duì)應(yīng)屬性,使得我們不用跟請(qǐng)求和響應(yīng)直接打交道。2)對(duì)于增加書(shū)和編輯書(shū)我們用同一個(gè)方法處理,通過(guò)isAddBook來(lái)標(biāo)識(shí), addBookFlag==1是增加,==0是編輯。(不知為何用布爾型來(lái)標(biāo)識(shí)前臺(tái)無(wú)法返回正確的布爾值,所以在這里用的是整形) <?xml version="1.0" encoding="UTF-8"?> 這里用到了消息資源,因此在同級(jí)目錄下還要有一個(gè)名為BookAction.properties的資源文件。 <%@page pageEncoding="gb2312" contentType="text/html; charset=UTF-8" %> <html>
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %> <html>
|
2008年10月29日17:45:21 |