1. 程式人生 > >Struts2+Spring4+Hibernate5框架搭建(XML方式)

Struts2+Spring4+Hibernate5框架搭建(XML方式)

SSH框架如何整合?

SSH的框架整合,主要是分為兩個部分。

其一:Spring整合Hibernate,總體來說就是將sessionFactory交給Spring容器來管理。(Spring整合AOP事務不做說明)

其二:Spring整合struts,就是Spring幫助struts2來管理action物件。

這裡主要是想注重框架的搭建過程,讓整個框架跑通。IDEEclipse,準備先採用xml的方式完成環境的搭建,這種純xml的方式儘管不是很流行了,但是有些東西還是必須要會使用的。至於主流的使用當然是xml+註解的方式,有機會會補上的。這裡算是記錄下自己搭建框架的過程吧,方便自己以後的使用,因為記憶力是有限的,該記錄的還是要記錄。開始,開始。。。。。。。


第一步:建立web工程

第二步:導包

我將所有需要用到的jar包資源已經上傳。

jar資源連結:SSH框架搭建jar包

使用方法:解壓完成以後,只需要將所有jar包copy到WEB-INF下的lib中即可。部分截圖如下:


ps:總共匯入了40個包,如果後期需要新增功能,按照自己的需求新增jar包即可


第三步:準備資料庫

這裡使用mysql資料庫,建立一個名為build_ssh的資料庫,並添加了一張表以及幾條測試資料,建表語句及插入的資料如下:

CREATE TABLE user_test(	
	user_id INT PRIMARY KEY AUTO_INCREMENT,
	user_name VARCHAR(20),
	user_password VARCHAR(20)
); 
INSERT INTO user_test VALUES(1,'jack','123');
INSERT INTO user_test VALUES(2,'rose','123');


第四步:搭建Spring環境,並整合web專案

1)建立application.xml,匯入約束,Spring環境搭建成功!

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">		
 
</beans>
2)配置WEB-INF下的web.xml

在搭建struts2的環境之前,根據struts2的執行原理,一定要首先想到配置struts2的入口過濾器,這點我經常就忘記,所以順帶就配置了struts2的入口過濾器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>build_ssh</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
   <!-- Spring啟動監聽器 -->
  <listener>
   		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 確定Spring配置檔案路徑 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
  
  <!-- 配置struts2的入口過濾器 -->
  <filter>
  	<filter-name>struts2</filter-name>
  	<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  	<!-- <init-param>
  		<param-name>struts.enable.DynamicMethodInvocation</param-name>
  		<param-value>true</param-value>
  	</init-param> -->
  </filter>
  <filter-mapping>
  	<filter-name>struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
</web-app>

第五步:Spring整合Hibernate

使用Spring整合hibernate的思路是:首先建立一個實體類,編寫對映檔案和hibernate的配置檔案,把原先在hibernate中的基本配置(連線JDBC的步驟)交給Spring來管理,並且在Spring中(applicationContext.xml)配置session工廠,讓Spring容器來管理session工廠。完成上述步驟以後,編寫測試類,測試Spring是否與Hibernate整合成功。

1)建立實體類

package com.ssh.domain;

public class User {
	private int userId;
	private String userName;
	private String userPassword;
	
	public int getUserId() {
		return userId;
	}
	public String getUserName() {
		return userName;
	}
	public String getUserPassword() {
		return userPassword;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
	@Override
	public String toString() {
		return "User [userId=" + userId + ", userName=" + userName + ", userPassword=" + userPassword + "]";
	}
	
}

2)建立實體類的對映檔案User.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.ssh.domain">
   <class name="User" table="user_test">
      <id name="userId" column="user_id">
            <generator class="identity"></generator> <!-- 這裡主鍵生成策略換成native也是可以的 -->
      </id>
	  <property name="userName" column="user_name"></property>
	  <property name="userPassword" column="user_password"></property>  
   </class>
</hibernate-mapping>    

3)建立hibernate的配置檔案hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<!-- 會話工廠 -->
	<session-factory>
		<!-- 資料庫方言,根據資料庫選擇 -->
	    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

		<!--為了方便除錯是否在執行hibernate時在日誌中輸出sql語句 -->
		<property name="hibernate.show_sql">true</property>
		<!-- 是否對日誌中輸出的sql語句進行格式化 -->
		<property name="hibernate.format_sql">true</property>
		<!--是否自動建表,這裡關掉了,我們自己前面已經建好了-->
		<property name="hibernate.hbm2ddl.auto">none</property>
		
		<!-- 載入對映檔案 -->
		<mapping resource="com/ssh/domain/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
4)配置applicationContext.xm,讓Spring來管理session工廠,並且把原來hibernate中關於資料庫連線的部分也一併交給Spring容器來管理。

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
				
		
	<!-- 開啟IOC支援,包掃描 -->
	<!-- 掃描該包下的所有類,用於IOC,由spring幫我們生成物件,因為測試的時候會用到註解所以這裡先將開關開啟 -->
	<context:component-scan base-package="com.ssh"></context:component-scan>
	
	<!-- 配置資料來源 -->
	<!-- 原先在hibernate.cfg.xml中配置的連線,現在交給Spring來管理 -->
	<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
			<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
			<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/build_ssh"></property>
			<property name="user" value="root"></property><!--修改成自己的使用者名稱和密碼-->
			<property name="password" value="root"></property>
	</bean>
	
	<!-- 配置sessionFactory,由Spring來管理session工廠 -->
	<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<!-- hibernate的基礎配置和可選配置 -->
		<property name="configLocations" value="classpath:hibernate.cfg.xml"></property>
	</bean>

    
</beans>
5)編寫測試類,驗證Spring是否整合hibernate成功

package com.ssh.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.ssh.domain.User;

@RunWith(SpringJUnit4ClassRunner.class)  //spring整合了junit測試
@ContextConfiguration("classpath:applicationContext.xml")  //用於載入spring的配置檔案,初始化容器
public class HIbernateTest {
	
	  @Autowired
	  private SessionFactory factory;  //spring容器為我們提供了工廠物件,這裡使用註解的方式去容器中拿到該物件
	
	  @Test
	  public void fun2(){
		Session session = factory.openSession();     //從session工廠中拿到session物件
		Transaction tx = session.beginTransaction();   //開啟事務
		// 要執行的操作是儲存一個使用者
		User u = new User();
		u.setUserName("evil");
		u.setUserPassword("123");
		session.save(u);       //將user物件持久化到資料庫中

		tx.commit();       //提交事務
		session.close();   //關閉session
	  }
}

6)結果驗證:在方法上右擊junit test,出現下面結果,物件被持久化到了資料庫中,恭喜你整合第一步成功!

Hibernate: 
    insert 
    into
        user_test
        (user_name, user_password) 
    values
        (?, ?)


資料‘tom’已插入...

截至目前,專案的結構如圖所示:(尋思著也該截一個圖了,至於其它的包,因為下面使用到,所以我先提前建好了)


第六步:Spring整合Struts2

spring整合struts2的思路:我們想通過瀏覽器輸入地址,請求到struts2的一個action,然後跳轉至結果頁面。所以我們首先應該建立一個userAction,然後再struts2中配置好該action,但是該action物件我們要交給spring容器來幫我們生成(以前是struts幫我們生成),所以還需要在spring的配置檔案中,配置好該action物件。

1)編寫測試用的UserAction

package com.ssh.web;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {
		
	 public String save(){
		 System.out.println("Spring整合struts2成功!");
		 return SUCCESS;
	 }
}

2)配置struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<!-- 開發使用,熱載入 -->
    <constant name="struts.devMode" value="true"></constant>  
    <!-- 啟用spring工廠,整合Spring的總開關 -->
    <constant name="struts.objectFactory" value="spring"></constant>
    
    <package name="struts" namespace="/" extends="struts-default">
       <action name="UserAction_*" class="userAction" method="{1}"><!--注意這裡的class="userAction",不是類的全路徑了,是從Spring容器中獲取的action-->
           <result name="success">/index.jsp</result>
       </action>         
    </package>
</struts>	

3)配置applicationContext.xml,讓Spring來幫我們生成UserAction物件

在配置檔案下方加入以下程式碼即可:

<!-- 配置action物件 -->
	<bean name="userAction" class="com.ssh.web.UserAction" scope="prototype"><!-- 千萬不要忽略scope這個屬性,因為action物件是多例的 -->
		<!-- <property name="userService" ref="userService"></property> -->
	</bean>

4)在WebContext下建立index.jsp檔案

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	Spring整合struts2成功了!
</body>
</html>

5)在tomcat上部署專案,執行,瀏覽器上輸入地址:http://localhost:8080/build_ssh/UserAction_save 。如果跳轉至index.jsp頁面看到提示資訊,則證明Spring整合struts2成功!


至此,三大框架的整合完成了三分之二了,還有重要的一點,就是spring整合AOP事務


第七步:Spring整合AOP事務

spring整合AOP事務的思路:我們採用註冊的案例來體現Spring整合AOP事務,前臺在註冊頁面填寫好表單以後,提交表單到action中,action中通過物件驅動的方式接受前臺傳遞過來的使用者名稱和密碼,從web層進入到service層,然後繼而到dao層中。原本我們想要通過hibernate持久化一個物件到資料庫中,必須先要獲得session,開啟事務,呼叫session.save()方法持久化物件,提交事務,物件此時就會持久化到了資料庫中。現在由spring為我們做這些關於事務的操作(開啟事務,提交事務,回滾事務),我們只注重於業務邏輯----即儲存使用者。那Spring具體是怎麼整合事務的?以上只是簡單的描述,具體步驟不在這裡詳細說明,有空總結一發。下面開始採用註冊案例來體現我們的spring對事務的管理。

專案的結構如圖:



1)dao層編寫

package com.ssh.dao;

import com.ssh.domain.User;

public interface UserDao {
	void saveUser(User user);
}	
實現類

package com.ssh.dao.impl;

import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import com.ssh.dao.UserDao;
import com.ssh.domain.User;
//導包時要注意,不要將hibernate5的包導成了hibernate4或3
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
	/*
	 * 為什麼要繼承HibernateDaoSupport?
	 * 答:因為dao層本來是依賴於HibernateTemplate的,該模板中封裝了一些事務的操作,需要我們在Spring的配置檔案中配置HIbernateTemplate.
	 * 我們繼承自HibernateDaoSupport,就使得dao層直接依賴於sessionFactory
	 * 當然這裡也可以寫HibernateTeplate,方法很多種,自己用著舒服就行
	 */
	@Override
	public void saveUser(User user) {
		this.getHibernateTemplate().save(user);
	}

}

2)service層編寫

package com.ssh.service;

import com.ssh.domain.User;

public interface UserService {
	void saveUser(User user);
}
實現類

package com.ssh.service.impl;

import com.ssh.dao.UserDao;
import com.ssh.domain.User;
import com.ssh.service.UserService;

public class UserServiceImpl implements UserService {
	
	//service層依賴於dao,我們想要獲得dao層物件,不用自己建立了,直接去容器中拿就可以,
	//但是前提是需要在容器中配置好dao層的東西。
	//而且這裡需要提供get和set方法,以便於我們在容器中使用屬性注入的方式給service層注入dao的依賴
	private UserDao userDao;
	
	@Override
	public void saveUser(User user) {
		userDao.saveUser(user);
	}

	public UserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

}

3)web層的編寫(還是使用原來的action,修改了其中的方法,並添加了一個service的屬性和一個物件驅動)

package com.ssh.web;

import com.opensymphony.xwork2.ActionSupport;
import com.ssh.domain.User;
import com.ssh.service.UserService;

public class UserAction extends ActionSupport {
    
	//採用物件驅動的方式接收前臺傳過來的值
	private User user =new User();
	
	private UserService userService;

	public String save() {
		userService.saveUser(user);
		return SUCCESS;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}
}
4)在Spring中配置事務
<!-- 配置事務管理器 -->
		<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
			<property name="sessionFactory" ref="sessionFactory"></property>
		</bean>
		
		<!-- 配置通知 -->
		<tx:advice id="txAdvice" transaction-manager="transactionManager">
			<tx:attributes>
				<tx:method name="save*" read-only="false"/>
				<tx:method name="update*" read-only="false"/>
				<tx:method name="delete*" read-only="false"/>
				<tx:method name="find*" read-only="true"/>
				<tx:method name="*" read-only="false"/>				
			</tx:attributes>
		</tx:advice>
		
		
		<!-- 配置切面 -->
		<aop:config>
			<aop:pointcut expression="execution(* com.ssh.service.*.*(..))" id="txPC"/>
			<aop:advisor advice-ref="txAdvice" pointcut-ref="txPC"/>
		</aop:config>
5)配置各層的bean物件

<!-- 配置dao -->
    <bean name="userDao" class="com.ssh.dao.impl.UserDaoImpl">
    	<property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <!-- 配置service -->
	<bean name="userService" class="com.ssh.service.impl.UserServiceImpl">
		<property name="userDao" ref="userDao"></property>
	</bean>
	<!-- 配置action物件 -->
	<bean name="userAction" class="com.ssh.web.UserAction" scope="prototype"><!-- 千萬不要忽略scope這個屬性,因為action物件是多例的 -->
		<property name="userService" ref="userService"></property>
	</bean>


至此,完整的applicationContext.xml配置完成,以下就是完整的配置檔案,莫要覺得亂糟糟!

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
				
		
	<!-- 開啟IOC支援,包掃描 -->
	<!-- 掃描該包下的所有類,用於IOC,由spring幫我們生成物件,因為測試的時候會用到註解所以這裡先將開關開啟 -->
	<context:component-scan base-package="com.ssh"></context:component-scan>
	
	<!-- 配置資料來源 -->
	<!-- 原先在hibernate.cfg.xml中配置的連線,現在交給Spring來管理 -->
	<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
			<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
			<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/build_ssh"></property>
			<property name="user" value="root"></property>
			<property name="password" value="root"></property>
	</bean>
	
	<!-- 配置sessionFactory,由Spring來管理session工廠 -->
	<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<!-- hibernate的基礎配置和可選配置 -->
		<property name="configLocations" value="classpath:hibernate.cfg.xml"></property>
	</bean>
	
	<!-- 配置事務管理器 -->
		<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
			<property name="sessionFactory" ref="sessionFactory"></property>
		</bean>
		
		<!-- 配置通知 -->
		<tx:advice id="txAdvice" transaction-manager="transactionManager">
			<tx:attributes>
				<tx:method name="save*" read-only="false"/>
				<tx:method name="update*" read-only="false"/>
				<tx:method name="delete*" read-only="false"/>
				<tx:method name="find*" read-only="true"/>
				<tx:method name="*" read-only="false"/>				
			</tx:attributes>
		</tx:advice>
		
		
		<!-- 配置切面 -->
		<aop:config>
			<aop:pointcut expression="execution(* com.ssh.service.*.*(..))" id="txPC"/>
			<aop:advisor advice-ref="txAdvice" pointcut-ref="txPC"/>
		</aop:config>
	
	<!-- 配置dao -->
    <bean name="userDao" class="com.ssh.dao.impl.UserDaoImpl">
    	<property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <!-- 配置service -->
	<bean name="userService" class="com.ssh.service.impl.UserServiceImpl">
		<property name="userDao" ref="userDao"></property>
	</bean>
	<!-- 配置action物件 -->
	<bean name="userAction" class="com.ssh.web.UserAction" scope="prototype"><!-- 千萬不要忽略scope這個屬性,因為action物件是多例的 -->
		<property name="userService" ref="userService"></property>
	</bean>
	
	
    
</beans>

7)編寫前臺頁面register.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>註冊頁面</title>
</head>
<body>
	<form action="${pageContext.request.contextPath}/UserAction_save" method="post"> 
		使用者名稱:<input name="user.userName" type="text"/><br>
		密碼:<input name="user.userPassword" type="password"/><br>
		<input type="submit" value="註冊"/>
	</form>
</body>
</html>

8)測試註冊:瀏覽器輸入地址訪問register.jsp頁面


輸入使用者名稱和密碼,點選註冊,會跳轉到成功頁面!



到此,Spring整合AOP完成,如果不加AOP事務配置的話或事務配置錯誤的話,會丟擲如下異常資訊:



因為沒有配置事務之前,Spring整合hibernate的預設事務原則是隻讀,我們 無法儲存一個物件到資料庫中,不能夠做“寫”的操作。


總結;前路漫漫,其修遠兮!

本人菜鳥,只想著做個記錄,方便自己以後回顧,如果文章對童鞋們有絲毫的小幫助,我也會感到快樂的!

如果覺得有什麼地方錯誤,請各位及時指出,以免我誤及他人!

最後,謝謝!(如果你能看到的話)