Struts2+Spring+Hibernate整合
本文主要目的是通過整合Struts2,Spring,Hibernate,開發出一個簡易的圖書管理系統,該系統具有增刪改查的基本功能。 ![]() 把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自帶的編碼過濾器,不用自己寫了,其中主要代碼 是request.setCharacterEncoding(encoding)和 response.setCharacterEncoding(encoding),對請求和響應設置編碼。 有兩個參數:encoding和forceEncoding,其中forceEncoding默認是false, (此種情況不能改變response的編碼方式)如果設置成true則不管請求是否已有編碼 都強制轉換成encoding指定的編碼,同時在響應可設置編碼的前提下設置響應編碼。 --> <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應用關閉時IntrospectorCleanupListener類負責對javabean 內省緩存進行清除;該類實現接口ServletContextListener, 對緩存在context中的javabean類進行清除操作的。 --> <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的超時時間,單位為分鐘 --> <session-config> <session-timeout>10</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> 幾點需要注意的地方:1)對于spring的配置文件和log4j日志配置文件的讀取我們用的是spring的ContextLoaderListener和Log4jConfigListener這兩個個監聽器。2)對瀏覽器發送的請求,通過配置的Struts2的過濾器(FilterDispatcher)可以對不同的url進行過濾,此處我們配置處理該web應用的所有請求。3)配置了一個spring自帶的編碼過濾器,用來處理請求和響應的編碼,本應用配置對所有請求和響應都采用該編碼過濾器,這里我們采用的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對所有bean提供一種默認的自動裝配方式,如果bean需要不同的方式, 可以在bean中配置配置autowire屬性。自動裝配方式有以下幾種: 1) no 不使用自動裝配。必須通過ref元素指定依賴,這是默認設置。 2) byName 根據屬性名自動裝配。此選項將檢查容器并根據名字查找與屬性完全一致的bean,并將其與屬性自動裝配。 3) byType 如果容器中存在一個與指定屬性類型相同的bean,那么將與該屬性自動裝配。 4) constructor 與byType的方式類似,不同之處在于它應用于構造器參數。 5) autodetect 通過bean類的自省機制(introspection)來決定是使用constructor還是byType方式進行自動裝配。 --> <beans> <!-- 如果實體定義用的是xml配置文件,則sessionFactory的class 應為"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> <!-- 配置多個hibernate.cfg.xml <property name="configLocations"> <list> <value>classpath:hibernate_admin1.cfg.xml</value> <value>classpath:hibernate_admin2.cfg.xml</value> </list> </property> --> </bean> <!-- 配置事務管理 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 這里的abstract屬性說明該bean是抽象的,不能實例化,只能用來被繼承,在這里他被BookService繼承 --> <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <!-- PROPAGATION_REQUIRED代表必須在事務中執行,-Exception表示 當有Exception拋出時事務回滾 --> <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> 這里幾點要注意的地方:1)sessionFactory的真正定義是在hibernate.cfg.xml里面,sessionFactory Bean通過configLocation屬性提供的路徑去找,因為hibernate.cfg.xml是在/WEB-INF/classes/下,所以可以通過classpath:hibernate.cfg.xml定位。2)該處配置的sessionFactory是基于Annotation對實體進行管理的。3)對于持久化操作可以配置事務管理機制保證數據的安全和合法,本實例對于目標類(BookServiceImpl)中的以find,persist,remove開頭的方法都采用事務機制。 <?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> <!-- 該屬性默認為none,有以下幾種: 1)validate 加載hibernate時,驗證創建數據庫表結構 2) create 每次加載hibernate,重新創建數據庫表結構,這就是導致數據庫表數據丟失的原因。 3) create-drop 加載hibernate時創建,退出是刪除表結構 4) update 加載hibernate自動更新數據庫結構 --> <!-- <property name="hibernate.hbm2ddl.auto">create</property> --> <!-- 這里由于我們采用的是annotation方式,所以直接指向實體對應的類即可,如果是采用實體配置文件則寫成 <mapping resource="com/css/ravollen/sshtest/entity/Book.hbm.xml"></mapping> --> <mapping class="com.css.ravollen.sshtest.entity.Book"></mapping> </session-factory> </hibernate-configuration> 該文件主要配置了數據庫底層連接的一些信息。需要注意的地方有:1)數據庫url需加上useUnicode=true&characterEncoding=UTF-8,可以解決中文亂碼問題。(其中&是&的轉義符) <?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說明該配置文件繼承自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的默認攔截器 param攔截器 將Request請求的參數設置到相應Action對象的屬性中 validation攔截器 實現使用xml配置文件({Action}-validation.xml)對Action屬性值進行驗證 --> <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> 注意這幾項:1)package的extends屬性說明該配置文件是繼承自strut-default.xml,該配置文件在struts2-core-2.0.11.2.jar包內。2)對于大量重復的result,我們可以配置成全局的result,可以減少文件冗余。3)在"保存書"這個活動中,加入了struts2的校驗框架,在該action中加入兩個攔截器"params"和“validation"就可以,此外在該Action的同一級目錄下新建一個校驗配置文件即可,命名規則:活動名+"-"+方法名+"-"+"validation.xml,如果該校驗文件引用了消息文件,則還要在同一級目錄下建一個.properties的消息文件文件,前綴與活動名一樣。(需要對消息文件進行ascii碼轉換,命令為 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; 實現類: 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實例通過ApplicationContext從Spring的上下文中得到。2)BookDAO通過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) { 說明一下:1)Struts的攔截器解析前臺參數然后將值賦給Action里的對應屬性,使得我們不用跟請求和響應直接打交道。2)對于增加書和編輯書我們用同一個方法處理,通過isAddBook來標識, addBookFlag==1是增加,==0是編輯。(不知為何用布爾型來標識前臺無法返回正確的布爾值,所以在這里用的是整形) <?xml version="1.0" encoding="UTF-8"?> 這里用到了消息資源,因此在同級目錄下還要有一個名為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 |