【SSH專案實戰】國稅協同平臺-2.環境搭建和整合

光仔December發表於2015-10-19
框架整合

2.1新建資料庫及web專案
2.1.1建立itcastTax資料庫
-- 建立資料庫
CREATE DATABASE itcastTax DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
我們使用的是Mysql資料庫

2.1.2新建web專案
新建工作空間指定專案編碼(或工作空間編碼)為utf-8,再建 web project,配置buildpath


新增jstl的jar包和mysql驅動包;
javax.servlet.jsp.jstl.jar
jstl-impl.jar
mysql-connector-java-5.1.32-bin.jar


2.2框架整合
2.2.1新增struts2的jar包和配置檔案
新增jar包:
commons-fileupload-1.3.1.jar
commons-io-2.2.jar
commons-lang-2.4.jar 
commons-lang3-3.2.jar
freemarker-2.3.19.jar
ognl-3.0.6.jar
struts2-core-2.x.jar
struts2-spring-plugin-2.x.jar
xwork-core-2.x.jar 

到web-inf/lib目錄下。

新增struts.xml到src目錄下。
在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.enable.DynamicMethodInvocation" value="false" />
	<!-- 配置成開發模式 -->
	<constant name="struts.devMode" value="true" />
	<!-- 配置擴充名為action -->
	<constant name="struts.action.extention" value="action" />
	<!-- 把主題配置成simple -->
	<constant name="struts.ui.theme" value="simple" />
	
</struts>

配置web.xml:新增struts2 過濾器:

<filter>
     <filter-name>struts2</filter-name>   
     <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
     <filter-name>struts2</filter-name>
     <url-pattern>*.action</url-pattern>
</filter-mapping>


2.2.2新增hibernate的jar包和配置檔案新增hibernate jar包:

到web-inf/lib目錄下。至於hibernate.cfg.xml檔案,因專案使用spring來整合管理實體和資料庫的連線等hibernate原本的工作,所以這個配置檔案不再需要。

2.2.3新增spring的jar包和配置檔案新增spring3.0.2中的jar包:

新增spring配置檔案applicationContext.xml 到src目錄下;

<?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"
	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-3.0.xsd 
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
</beans>

在web.xml中註冊spring監聽器,啟動spring容器:
<!-- spring監聽器 -->
<listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
</context-param>

三大框架的環境已經新增完畢,下面我們開始整合。

2.3整合測試專案
2.3.1整合struts 和 spring
預期:如果可以在action中能夠正確呼叫service裡面的方法執行並返回到一個頁面中;那麼我們認定struts和spring的整合是成功的。

編寫 TestService 介面 和實現類 TestServiceImpl
package cn.edu.hpu.tax.service;


public interface TestService {
	//輸出
	public void say();
}


package cn.edu.hpu.tax.service.impl;

import org.springframework.stereotype.Service;

import cn.edu.hpu.tax.service.TestService;

@Service("testService")
public class TestServiceImpl implements TestService{


	@Override
	public void say() {
		System.out.println("Hello Service!");
	}
	
}

編寫JUnit測試類,測試spring載入是否正確:
package cn.edu.hpu.tax.test;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.edu.hpu.tax.service.TestService;


public class TestMerge {


	private ClassPathXmlApplicationContext ctx;
	@Test
	public void testSpring(){
		ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		TestService ts=(TestService)ctx.getBean("testService");
		ts.say();
	}
}

在applicationContext.xml中新增bean掃描配置資訊;
這邊使用匯入配置檔案的方式配置。
①首先在cn.edu.hpu.test.conf中建立test-spring.xml,裡面內容:
<?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"
	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-3.0.xsd 
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    <!-- 掃描Service -->
    <context:component-scan base-package="cn.edu.hpu.tax.test.service.impl"></context:component-scan>
</beans>

裡面的配置就是普通的bean掃描,只是將掃描範圍縮小了。

②將test-spring.xml匯入到applicationContext.xml中如下:
<!-- 引入外部spring配置檔案 -->
<import resource="classpath:cn/edu/hpu/tax/*/conf/*-spring.xml"/>

執行TestMerge的testSpring方法,執行成功,說明我們的spring配置沒有問題。

下面測試我們的struts和spring是否能整合使用:
編寫TestAction類:
package cn.edu.hpu.tax.test;

import javax.annotation.Resource;

import cn.edu.hpu.tax.service.TestService;

import com.opensymphony.xwork2.ActionSupport;

public class TestAction extends ActionSupport{
	
	@Resource
	TestService testService;


	//預設方法
	public String execute(){
		testService.say();
		return SUCCESS;
	}
}

注意:
注入testService;有兩種方式:
(1)註解注入
@Resource
TestService testService;
這種方式spring會按照"testService"找相應的類去注入

@Resource
public void setTestService(TestService testService) {
	this.testService = testService;
}
這種方式spring會按照setTestService中的"testService"(找的時候首字母轉為小寫)找相應的類去注入。使用set方法是為了在注入前加入一些其他程式碼(在set方法裡)。

(2)配置檔案注入
也是在action加入set方法,不過不用加註解,然後在struts配置檔案的property中加入想注入的service類就可以了。

在test的conf資料夾下新建test-struts.xml中配置TestAction :
<struts>
	<package name="test-action" namespace="/" extends="struts-default">
		<action name="test_*" class="cn.edu.hpu.tax.test.TestAction" method="{1}">
			<result name="success">/WEB-INF/jsp/test/test.jsp</result>
		</action>
	</package>
</struts>

將test-struts.xml匯入到struts.xml檔案中。
<!-- 包含test的struts配置檔案 -->
<include file="cn/edu/hpu/test/tax/conf/test-struts.xml"/>

在webRoot/WEB-INF/jsp目錄下新建test/test.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP</title>
  <body>
    測試struts與spring整合成功!
  </body>
</html>

在瀏覽器中輸入:http://localhost/HpuTax/test.action(我的tomcat是80埠)檢視後臺是否能輸入service中的列印資訊:

測試成功!

2.3.2整合hibernate 和 spring 
在applicationContext.xml中配置如下原本在hibernate.cfg.xml中需要配置的資訊,在spring中配置後hibernate.cfg.xml 可刪除(沒有加就忽略)。

1、配置c3p0資料庫連線源:
<pre name="code" class="html"><!-- 匯入外部的properties配置檔案 -->
<context:property-placeholder location="classpath:db.properties" />

<!-- 配置c3p0資料來源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
	<property name="jdbcUrl" value="${jdbcUrl}"></property>
	<property name="driverClass" value="${driverClass}"></property>
	<property name="user" value="${user}"></property>
	<property name="password" value="${password}"></property>
	<!--初始化時獲取三個連線,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->
	<property name="initialPoolSize" value="${initialPoolSize}"></property>
	<!--連線池中保留的最小連線數。Default: 3 -->
	<property name="minPoolSize" value="3"></property>
	<!--連線池中保留的最大連線數。Default: 15 -->
	<property name="maxPoolSize" value="${maxPoolSize}"></property>
	<!--當連線池中的連線耗盡的時候c3p0一次同時獲取的連線數。Default: 3 -->
	<property name="acquireIncrement" value="3"></property>
	<!--最大空閒時間,1800秒內未使用則連線被丟棄,若為0則永不丟棄。Default: 0 -->
	<property name="maxIdleTime" value="1800"></property>
</bean>

2、db.properties
jdbcUrl=jdbc:mysql://localhost:3306/hputax?
useUnicode=true&characterEncoding=utf8
driverClass=com.mysql.jdbc.Driver
user=root
password=1234
initialPoolSize=10
maxPoolSize=30

3、配置sessionFactory,並將dataSource指向c3p0建立的dataSource:
<bean id="sessionFactory"
	class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSource"></property>
	<property name="hibernateProperties">
		<props>
			<!-- 資料庫方言 -->
			<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
			<prop key="hibernate.show_sql">true</prop>
			<!-- 通過hbm配置檔案去更新 -->
			<prop key="hibernate.hbm2ddl.auto">update</prop>
			<prop key="javax.persistence.validation.mode">none</prop>
		</props>
	</property>
	<property name="mappingLocations">
		<list>
			<value>classpath:cn/edu/hpu/tax/test/entity/*.hbm.xml</value>
		</list>
	</property>
</bean>

編寫實體類Person
package cn.edu.hpu.tax.test.entity;

import java.io.Serializable;

public class Person implements Serializable {
	private String id;
	private String name;
	
	public Person() {


	}
	
	public Person(String name) {
		this.name = name;
	}


	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}

和對應的對映檔案Person.hbm.xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<hibernate-mapping>
	<class name="cn.edu.hpu.tax.test.entity.Person" table="person">
		<id name="id" type="java.lang.String">
			<column name="id" length="32" />
			<generator class="uuid.hex" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="name" length="20" not-null="true" />
		</property>
	</class>
</hibernate-mapping>


我們執行testHibernate()測試方法:
package cn.edu.hpu.tax.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;


import cn.edu.hpu.tax.service.TestService;
import cn.edu.hpu.tax.test.entity.Person;


import org.junit.Before;


public class TestMerge {


	private ClassPathXmlApplicationContext ctx;
	@Before
	public void testCtx(){
		ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
	}
	
	@Test
	public void testSpring(){
		TestService ts=(TestService)ctx.getBean("testService");
		ts.say();
	}
	
	@Test
	public void testHibernate(){
		SessionFactory sf=(SessionFactory)ctx.getBean("sessionFactory");
		Session session=sf.openSession();
		Transaction transaction=session.beginTransaction();
		//儲存人員
		session.save(new Person("人員1"));
		transaction.commit();
		session.close();
	}
}

看到我們的控制檯輸出一句插入語句,並且我們的資料庫已經有值:



測試框架分層的整合(service 與 dao)
TestDao 中新增方法 save ,在TestService中通過呼叫testDao來儲存人員資訊。
package cn.edu.hpu.tax.test.dao;

import java.io.Serializable;

import cn.edu.hpu.tax.test.entity.Person;

public interface TestDao {
	
	//儲存人員
	public void save(Person person);
	
	//根據id查詢人員
	public Person findPerson(Serializable id);
}

package cn.edu.hpu.tax.test.dao.impl;

import java.io.Serializable;

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

import cn.edu.hpu.tax.test.dao.TestDao;
import cn.edu.hpu.tax.test.entity.Person;


public class TestDaoImpl extends HibernateDaoSupport implements TestDao{


	@Override
	public void save(Person person) {
		getHibernateTemplate().save(person);
	}
	
	@Override
	public Person findPerson(Serializable id) {
		return getHibernateTemplate().get(Person.class, id);
	}	


}
因為上面使用了HibernateDaoSupport,所以我們要在test-spring注入sessionFactory(在HibernateDaoSupport中已經封裝好了setSessionFactory()方法,所以開發人員不用操心)
<bean id="testDao" class="cn.edu.hpu.tax.test.dao.impl.TestDaoImpl">
     <property name="sessionFactory" ref="sessionFactory"></property>
</bean>

然後我們的Service層去呼叫Dao的方法:
package cn.edu.hpu.tax.test.service.impl;

import java.io.Serializable;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import cn.edu.hpu.tax.test.dao.TestDao;
import cn.edu.hpu.tax.test.entity.Person;
import cn.edu.hpu.tax.test.service.TestService;


@Service("testService")
public class TestServiceImpl implements TestService{


	@Resource
	TestDao testDao;
	
	@Override
	public void say() {
		System.out.println("Hello Service!");
	}


	@Override
	public Person findPerson(Serializable id) {
		return testDao.findPerson(id);
	}


	@Override
	public void save(Person person) {
		testDao.save(person);
	}
	
}

下面我們編寫一個測試方法:
@Test
public void testServiceAndDao(){
	TestService ts=(TestService)ctx.getBean("testService");
	ts.save(new Person("tom"));
}

執行測試方法,發現成功在資料庫中新增person資訊:



然後我們來測試查詢,將剛剛儲存的資料查出來:
@Test
public void testServiceAndDao2(){
	TestService ts=(TestService)ctx.getBean("testService");
	System.out.println(ts.findPerson("402881e6507a17b501507a17b69f0000").getName());
}

發現取值成功:


2.3.3配置spring事務管理
<!-- 事務管理 --> 
<bean id="txManager"
	class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>


<!-- 事務通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
	<tx:attributes>
		<tx:method name="find*" read-only="true" />
		<tx:method name="get*" read-only="true" />
		<tx:method name="load*" read-only="true" />
		<tx:method name="list*" read-only="true" />
		<tx:method name="search*" read-only="true" />
		<tx:method name="*" rollback-for="Throwable" />
	</tx:attributes>
</tx:advice>


<!-- 配置需要進行事務控制的類 -->
<aop:config>
	<aop:pointcut id="serviceOperation" expression="bean(*Service)" />
	<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>

【注意:上面的pointcut  expression 表示攔截以Service結尾的bean,或者可寫成
execution(* cn.itcast..service.impl.*.*(..))】
完善 TestService介面和TestServiceImpl;利用service中的操作來驗證上面配置的事務管理是否生效。

測試方法
我們在Service中在find方法前進行save:
@Override
public Person findPerson(Serializable id) {
	save(new Person("jack"));
	return testDao.findPerson(id);
}

然後我們測試:
@Test
public void testTransationReadOnly(){
	//只讀事務,如果在只讀事務中出現更新操作則回滾
	TestService ts=(TestService)ctx.getBean("testService");
	System.out.println(ts.findPerson("402881e6507a17b501507a17b69f0000").getName());
}

執行之後我們發現報了這個錯誤:


說明我們的只讀控制是成功的。

接下來測試我們的回滾:
我們在Service的save插入值語句之後,故意寫一條錯誤的程式碼:
@Override
public void save(Person person) {
	testDao.save(person);
	int i=1/0;
}

測試方法:
@Test
public void testTransationRoolBack(){
	//回滾事務,如果在只讀事務中出現任務異常則回滾先前的操作
	TestService ts=(TestService)ctx.getBean("testService");
	ts.save(new Person("tom2"));
}

執行測試方法,發現報錯:

然後資料庫並沒有儲存名字為“tom2”的資料,說明我們的事務回滾控制成功!

至此,我們的框架配置、整合和測試完畢

轉載請註明出處:http://blog.csdn.net/acmman/article/details/49247179

相關文章