1. 程式人生 > >SSH專案整合之SSH整合

SSH專案整合之SSH整合

1 匯入ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--磁碟儲存:將快取中暫時不使用的物件,轉移到硬碟,類似於Windows系統的虛擬記憶體-->
    <!--path:指定在硬碟上儲存物件的路徑-->
    <!--java.io.tmpdir 是預設的臨時檔案路徑。 可以通過如下方式打印出具體的檔案路徑 System.out.println(System.getProperty("java.io.tmpdir"));-->
    <diskStore path="java.io.tmpdir"/>


    <!--defaultCache:預設的管理策略-->
    <!--eternal:設定快取的elements是否永遠不過期。如果為true,則快取的資料始終有效,如果為false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷-->
    <!--maxElementsInMemory:在記憶體中快取的element的最大數目-->
    <!--overflowToDisk:如果記憶體中資料超過記憶體限制,是否要快取到磁碟上-->
    <!--diskPersistent:是否在磁碟上持久化。指重啟jvm後,資料是否有效。預設為false-->
    <!--timeToIdleSeconds:物件空閒時間(單位:秒),指物件在多長時間沒有被訪問就會失效。只對eternal為false的有效。預設值0,表示一直可以訪問-->
    <!--timeToLiveSeconds:物件存活時間(單位:秒),指物件從建立到失效所需要的時間。只對eternal為false的有效。預設值0,表示一直可以訪問-->
    <!--memoryStoreEvictionPolicy:快取的3 種清空策略-->
    <!--FIFO:first in first out (先進先出)-->
    <!--LFU:Less Frequently Used (最少使用).意思是一直以來最少被使用的。快取的元素有一個hit 屬性,hit 值最小的將會被清出快取-->
    <!--LRU:Least Recently Used(最近最少使用). (ehcache 預設值).快取的元素有一個時間戳,當快取容量滿了,而又需要騰出地方來快取新的元素的時候,那麼現有快取元素中時間戳離當前時間最遠的元素將被清出快取-->
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>

</ehcache>

2、匯入log4j2.xml:

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

<!-- status : 指定log4j本身的列印日誌的級別.ALL< Trace < DEBUG < INFO < WARN < ERROR 
	< FATAL < OFF。 monitorInterval : 用於指定log4j自動重新配置的監測間隔時間,單位是s,最小是5s. -->
<Configuration status="WARN" monitorInterval="30">
	<Properties>
		<!-- 配置日誌檔案輸出目錄 ${sys:user.home} -->
		<Property name="LOG_HOME">/root/workspace/lucenedemo/logs</Property>
		<property name="ERROR_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/error</property>
		<property name="WARN_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/warn</property>
		<property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} - %msg%n</property>
	</Properties>

	<Appenders>
		<!--這個輸出控制檯的配置 -->
		<Console name="Console" target="SYSTEM_OUT">
			<!-- 控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch) -->
			<ThresholdFilter level="trace" onMatch="ACCEPT"
				onMismatch="DENY" />
			<!-- 輸出日誌的格式 -->
			<!-- %d{yyyy-MM-dd HH:mm:ss, SSS} : 日誌生產時間 %p : 日誌輸出格式 %c : logger的名稱 
				%m : 日誌內容,即 logger.info("message") %n : 換行符 %C : Java類名 %L : 日誌輸出所在行數 %M 
				: 日誌輸出所在方法名 hostName : 本地機器名 hostAddress : 本地ip地址 -->
			<PatternLayout pattern="${PATTERN}" />
		</Console>

		<!--檔案會打印出所有資訊,這個log每次執行程式會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用 -->
		<!--append為TRUE表示訊息增加到指定檔案中,false表示訊息覆蓋指定的檔案內容,預設值是true -->
		<File name="log" fileName="logs/test.log" append="false">
			<PatternLayout
				pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</File>
		<!-- 這個會打印出所有的info及以下級別的資訊,每次大小超過size, 則這size大小的日誌會自動存入按年份-月份建立的資料夾下面並進行壓縮,作為存檔 -->
		<RollingFile name="RollingFileInfo" fileName="${LOG_HOME}/info.log"
			filePattern="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
			<!--控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch) -->
			<ThresholdFilter level="info" onMatch="ACCEPT"
				onMismatch="DENY" />
			<PatternLayout
				pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
			<Policies>
				<!-- 基於時間的滾動策略,interval屬性用來指定多久滾動一次,預設是1 hour。 modulate=true用來調整時間:比如現在是早上3am,interval是4,那麼第一次滾動是在4am,接著是8am,12am...而不是7am. -->
				<!-- 關鍵點在於 filePattern後的日期格式,以及TimeBasedTriggeringPolicy的interval, 日期格式精確到哪一位,interval也精確到哪一個單位 -->
				<!-- log4j2的按天分日誌檔案 : info-%d{yyyy-MM-dd}-%i.log -->
				<TimeBasedTriggeringPolicy interval="1"
					modulate="true" />
				<!-- SizeBasedTriggeringPolicy:Policies子節點, 基於指定檔案大小的滾動策略,size屬性用來定義每個日誌檔案的大小. -->
				<!-- <SizeBasedTriggeringPolicy size="2 kB" /> -->
			</Policies>
		</RollingFile>

		<RollingFile name="RollingFileWarn" fileName="${WARN_LOG_FILE_NAME}/warn.log"
			filePattern="${WARN_LOG_FILE_NAME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
			<ThresholdFilter level="warn" onMatch="ACCEPT"
				onMismatch="DENY" />
			<PatternLayout
				pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
			<Policies>
				<TimeBasedTriggeringPolicy />
				<SizeBasedTriggeringPolicy size="2 kB" />
			</Policies>
			<!-- DefaultRolloverStrategy屬性如不設定,則預設為最多同一資料夾下7個檔案,這裡設定了20 -->
			<DefaultRolloverStrategy max="20" />
		</RollingFile>

		<RollingFile name="RollingFileError" fileName="${ERROR_LOG_FILE_NAME}/error.log"
			filePattern="${ERROR_LOG_FILE_NAME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd-HH-mm}-%i.log">
			<ThresholdFilter level="error" onMatch="ACCEPT"
				onMismatch="DENY" />
			<PatternLayout
				pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
			<Policies>
				<!-- log4j2的按分鐘 分日誌檔案 : warn-%d{yyyy-MM-dd-HH-mm}-%i.log -->
				<TimeBasedTriggeringPolicy interval="1"
					modulate="true" />
				<!-- <SizeBasedTriggeringPolicy size="10 MB" /> -->
			</Policies>
		</RollingFile>

	</Appenders>

	<!--然後定義logger,只有定義了logger並引入的appender,appender才會生效 -->
	<Loggers>
		<!--過濾掉spring和mybatis的一些無用的DEBUG資訊 -->
		<logger name="org.springframework" level="INFO"></logger>
		<logger name="org.mybatis" level="INFO"></logger>

		<!-- 第三方日誌系統 -->
		<logger name="org.springframework" level="ERROR" />
		<logger name="org.hibernate" level="ERROR" />
		<logger name="org.apache.struts2" level="ERROR" />
		<logger name="com.opensymphony.xwork2" level="ERROR" />
		<logger name="org.jboss" level="ERROR" />


		<!-- 配置日誌的根節點 -->
		<root level="all">
			<appender-ref ref="Console" />
			<appender-ref ref="RollingFileInfo" />
			<appender-ref ref="RollingFileWarn" />
			<appender-ref ref="RollingFileError" />
		</root>

	</Loggers>

</Configuration>

3、整合hibernate

3-1:建立:spring-countext.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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
		
	<import resource="classpath:spring-hibernate.xml"/>
	<import resource="classpath:spring-book.xml"/>

</beans>

3-2:建立spring-hibernate.xml檔案。
3-2-1: 注入資料庫配置檔案:
db.username=root
db.password=123
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://127.0.0.1:3306/mysql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
db.initialPoolSize=10
db.maxPoolSize=20
db.minPoolSize=5
db.maxIdleTime=60
db.acquireIncrement=5
db.maxStatements=0
db.idleConnectionTestPeriod=60
db.acquireRetryAttempts=30
db.breakAfterAcquireFailure=true
db.testConnectionOnCheckout=false
3-2-2: 配置c3p0連線池:
<!-- 註冊資料庫連線檔案db.properties -->
<context:property-placeholder location="classpath:db.properties" />
	
<!-- 配置c3p0連線池 -->
<bean id="dataSource"
	class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${db.username}"></property>
		<property name="password" value="${db.password}"></property>
		<property name="driverClass" value="${db.driverClass}"></property>
		<property name="jdbcUrl" value="${db.jdbcUrl}"></property>

		<!--初始化時獲取的連線數,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->
		<property name="initialPoolSize"
			value="${db.initialPoolSize}"></property>
		<!--連線池中保留的最大連線數。Default: 15 -->
		<property name="maxPoolSize" value="${db.maxPoolSize}"></property>
		<!--連線池中保留的最小連線數。 -->
		<property name="minPoolSize" value="${db.minPoolSize}" />
		<!--最大空閒時間,60秒內未使用則連線被丟棄。若為0則永不丟棄。Default: 0 -->
		<property name="maxIdleTime" value="${db.maxIdleTime}" />

		<!--當連線池中的連線耗盡的時候c3p0一次同時獲取的連線數。Default: 3 -->
		<property name="acquireIncrement" value="${db.acquireIncrement}" />

		<!--JDBC的標準引數,用以控制資料來源內載入的PreparedStatements數量。但由於預快取的statements 屬於單個connection而不是整個連線池。 
			所以設定這個引數需要考慮到多方面的因素。如果maxStatements與maxStatementsPerConnection均為0,則快取被關閉。Default: 
			0 -->
		<property name="maxStatements" value="${db.maxStatements}" />

		<!--每60秒檢查所有連線池中的空閒連線。Default: 0 -->
		<property name="idleConnectionTestPeriod" value="${db.idleConnectionTestPeriod}" />

		<!--定義在從資料庫獲取新連線失敗後重復嘗試的次數。Default: 30 -->
		<property name="acquireRetryAttempts" value="${db.acquireRetryAttempts}" />

		<!--獲取連線失敗將會引起所有等待連線池來獲取連線的執行緒丟擲異常。但是資料來源仍有效 保留,並在下次呼叫getConnection()的時候繼續嘗試獲取連線。 
			如果設為true,那麼在嘗試 獲取連線失敗後該資料來源將申明已斷開並永久關閉。Default: false -->
		<property name="breakAfterAcquireFailure" value="${db.breakAfterAcquireFailure}" />

		<!--因效能消耗大請只在需要的時候使用它。如果設為true那麼在每個connection提交的 時候都將校驗其有效性。建議使用idleConnectionTestPeriod 
			或automaticTestTable 等方法來提升連線測試的效能。Default: false -->
		<property name="testConnectionOnCheckout" value="${db.breakAfterAcquireFailure}" />
	</bean>
3-2-3: 註冊LocalSessionFactoryBean:
<bean id="sessionFactory"
		class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<!-- 資料來源 -->
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<!-- hibernate相關屬性 -->
		<property name="hibernateProperties">
			<props>
				<!-- 配置方言 -->
				<prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
                <!--spring與Hibernate整合無法顯示sql語句問題,請見整合後hibernate無法顯示sql語句.txt-->
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
			</props>
		</property>
		<!-- 實體對映檔案 -->
		<property name="mappingResources">
			<list>
				<value>com/zking/book/entity/Book.hbm.xml</value>
			</list>
		</property>
	</bean>
3-2-4: spring宣告式事物:
	<!--宣告式事務配置開始 -->
	<!--1) 開啟自動代理 -->
	<aop:aspectj-autoproxy />

	<!--2) 事務管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!--3) 定義事務特性 -->
	<tx:advice id="txAdvice"
		transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="insert*" propagation="REQUIRED" />

			<tx:method name="edit*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />

			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="remove*" propagation="REQUIRED" />

			<tx:method name="load*" propagation="REQUIRED" read-only="true" />
			<tx:method name="list*" propagation="REQUIRED" read-only="true" />
			<tx:method name="select*" propagation="REQUIRED" read-only="true" />
			<tx:method name="query*" propagation="REQUIRED" read-only="true" />

			<tx:method name="do*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>

	<!--4) 定義切入點 -->
	<aop:config>
		<!-- pointcut屬性用來定義一個切入點,分成四個部分理解 [* ][*..][*Biz][.*(..)] -->
		<!-- A: 返回型別,*表示返回型別不限 -->
		<!-- B: 包名,*..表示包名不限 -->
		<!-- C: 類或介面名,*Biz表示類或介面必須以Biz結尾 -->
		<!-- D: 方法名和引數,*(..)表示方法名不限,引數型別和個數不限 -->
		<aop:advisor advice-ref="txAdvice"
			pointcut="execution(* *..*Biz.*(..))" />
	</aop:config>
	<!-- 宣告式事務配置結束 -->

注意: 宣告式事務配置

  1. 必須先修改spring配置檔案的宣告部分,新增對aop標籤和tx標籤的支援

    1. 配置SessionFactory(spring和hibernate整合時已完成)

    2. 配置事務管理器 HibernateTransactionManager

    3. 配置事務的傳播特性(tx) add edit del load|list 事務傳播特性(PROPAGATION_REQUIRED|readOnly)

    4. 配置自動代理 a) 引用環繞通知txAdvice b) 定義一個切入點 execution(* *…Biz.(…)) a:返回值不限 b:包名不限 c:介面名以Biz結尾 d:方法名及引數不限 c) 自動代理的原理 在spring上下文初始化完成以後,自動代理會逐個檢查spring上下文中JavaBean實現的介面是否滿足自動代理的條件,如果滿足條件,則將此bean和通知結合生成一個代理物件,並以此代理物件替換spring上下文中的bean,之後你訪問的就是代理物件了

3-2-5、配置HibernateTemplate
<bean class="org.springframework.orm.hibernate5.HibernateTemplate" id="hibernateTemplate">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
3-2-6:分模組開發 (只配置base模組) 可能是抽象類-

例如:

<bean class="com.zking.base.entity.BaseEntity" abstract="true" id="baseEntity"></bean>
	
	<bean class="com.zking.base.dao.BaseDao" abstract="true" id="baseDao">
		<property name="hibernateTemplate" ref="hibernateTemplate"></property>
	</bean>
	
	<bean class="com.zking.base.biz.BaseBiz" abstract="true" id="baseBiz"></bean>
	<bean class="com.zking.base.web.BaseAction" abstract="true" id="baseAction"></bean>