SpringMVC之application-context.xml,了解數據庫相關配置


上一篇SpringMVC之web.xml讓我們了解到配置一個web項目的時候,如何做基礎的DispatcherServlet相關配置,作為SpringMVC上手的第一步,而application-context.xml則讓我們了解到如何將數據庫信息加載到項目中,包含關鍵的數據庫連接信息、sqlSessionFactory、事務等關鍵因素。

①、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: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/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
>


<bean class="com.honzh.common.config.EncryptPropertyPlaceholderConfigurer">
<property name="locations">
<value>file:C:/properties/ymeng.properties</value>
</property>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}?useUnicode=true&amp;characterEncoding=utf8&amp;" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />

<!-- Connection Pooling Info -->
<property name="maxActive" value="${maxActive}" />
<property name="maxIdle" value="${maxIdle}" />
<property name="defaultAutoCommit" value="false" />
<property name="timeBetweenEvictionRunsMillis" value="3600000"/>
<property name="minEvictableIdleTimeMillis" value="3600000"/>

<property name="testOnBorrow" value="true" />
<property name="validationQuery">
<value>select 1 from DUAL</value>
</property>
</bean>

<!-- 創建SqlSessionFactory,同時指定數據源 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- Mapper接口所在包名,Spring會自動查找其下的Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.honzh.biz.database.mapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<!-- transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 可通過注解控制事務 -->
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="springContextHolder" class="com.honzh.common.spring.SpringContextHolder" />
</beans>

②、重點內容介紹

1、EncryptPropertyPlaceholderConfigurer

<bean class="com.honzh.common.config.EncryptPropertyPlaceholderConfigurer">
<property name="locations">
<value>file:C:/properties/ymeng.properties</value>
</property>
</bean>

使用了file前綴引導spring從c盤固定的路徑加載數據庫連接信息。

剛看到這個類的時候,你也許會有一種似曾相識的感覺,沒錯,她繼承了PropertyPlaceholderConfigurer類,只不過我為她加了一層神秘的色彩(Encrypt嘛),其作用呢,就是為了不直接在項目運行環境中暴露數據庫連接信息,比如說數據庫用戶名、密碼、URL等,這樣就等於系統多了一層的安全級別,個人覺得還是非常有用的,所以我之前總結了一篇SpringMVC使用隱式jdbc連接信息

標題寫的是SpringMVC,同樣適用於Spring,那么這里我就不再嘮叨了。

2、dataSource

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}?useUnicode=true&amp;characterEncoding=utf8&amp;" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />

<!-- Connection Pooling Info -->
<property name="maxActive" value="${maxActive}" />
<property name="maxIdle" value="${maxIdle}" />
<property name="defaultAutoCommit" value="false" />
<property name="timeBetweenEvictionRunsMillis" value="3600000"/>
<property name="minEvictableIdleTimeMillis" value="3600000"/>

<property name="testOnBorrow" value="true" />
<property name="validationQuery">
<value>select 1 from DUAL</value>
</property>
</bean>

使用了dbcp的數據庫連接池。

DBCP(DataBase connection pool),數據庫連接池。是 apache 上的一個 java 連接池項目,也是 tomcat 使用的連接池組件。單獨使用dbcp需要2個包:commons-dbcp.jar,commons-pool.jar由於建立數據庫連接是一個非常耗時耗資源的行為,所以通過連接池預先同數據庫建立一些連接,放在內存中,應用程序需要建立數據庫連接時直接到連接池中申請一個就行,用完后再放回去。

  1. destroy-method=”close”的作用就是當數據庫連接不使用的時候,就把該連接重新放到數據池中,方便下次使用調用.很關鍵的一個元素。

  2. 關於數據庫連接信息URL、username等就不解釋了。

  3. 關於數據庫連接池信息我到現在還沒有搞得很明白,之前也調查了很多次,不見效果,無奈。。。。

  4. testOnBorrow、validationQuery:通過“select 1 from DUAL”查詢語句來驗證connection的有效性。網上還有很多資源對這塊有專業的解釋,反正我是沒有看得太明白,之前也曾專門調查過這塊東西,現在也回想不起來了,以后再碰到的時候再補充進來。

3、sqlSessionFactory

    <!-- 創建SqlSessionFactory,同時指定數據源 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

sqlSessionFactory對於Spring以及mybatis來說就比較關鍵了,spring在建立sql連接使都會使用到這個。由於我的不專業性,所以關於更深入的解釋,我就不來了,反正對於我來說,這段配置就是為了和數據庫連接鏈接、創建事務管理。

創建sqlSessionFactory時,可能還需要為mybatis配置別名,那么此處改為如下格式:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataSource" />
</bean>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<typeAliases>
<typeAlias alias='Deals' type='com.honzh.biz.database.entity.Deals' />
</typeAliases>
</configuration>

這樣在mapper的xml文件中就可以使用Deals,而不再是com.honzh.biz.database.entity.Deals全名。

<resultMap type="Deals" id="BaseResultMap">

4、transactionManager、tx:annotation-driven

   <!-- transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 可通過注解控制事務 -->
<tx:annotation-driven transaction-manager="transactionManager" />

transactionManager就是為了開啟事務。通過tx:annotation-driven就可以直接在方法或者類上加“@transactional”來開啟事務回滾。關於這段,我也必須誠實的說,我只停留在會用的基礎上。

5、springContextHolder

<bean id="springContextHolder" class="com.honzh.common.spring.SpringContextHolder" />

通過spring的IOC機制(依賴注入),配置springcontext的管理器,該類的具體內容見如下:

package com.honzh.common.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
* <strong>SpringContextHolder</strong><br>
* Spring Context Holder<br>
* <strong>Create on : 2011-12-31<br></strong>
* <p>
* <strong>Copyright (C) Ecointel Software Co.,Ltd.<br></strong>
* <p>
* @author peng.shi peng.shi@ecointel.com.cn<br>
* @version <strong>Ecointel v1.0.0</strong><br>
*/

public class SpringContextHolder implements ApplicationContextAware {

private static ApplicationContext applicationContext;

public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}

/**
* 得到Spring 上下文環境
* @return
*/

public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return applicationContext;
}

/**
* 通過Spring Bean name 得到Bean
* @param name bean 上下文定義名稱
*/

@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
checkApplicationContext();
return (T) applicationContext.getBean(name);
}

/**
* 通過類型得到Bean
* @param clazz
* @return
*/

@SuppressWarnings("unchecked")
public static <T> T getBean(Class<T> clazz) {
checkApplicationContext();
return (T) applicationContext.getBeansOfType(clazz);
}

private static void checkApplicationContext() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext未注入,請在application-context.xml中定義SpringContextHolder");
}
}

}

如此,我們就可以輕松的通過SpringContextHolder.getBean方法獲取對應的bean類,就不再通過new關鍵字來創建一個類了,當然該類必須有注解標識,比如說@Service、@Component等。

6、MapperScannerConfigurer

        <!-- Mapper接口所在包名,Spring會自動查找其下的Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.honzh.biz.database.mapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

該段配置的目的就是掃描mapper接口,也就是你sql語句的地方。當系統啟動運行時,spring會加載你的mapper類,然后檢查對應的sql語句是否正確,比如字段名是否匹配等等,若不匹配系統自然會報錯。另外特別注意的是basePackage的value值一定要正確,我就曾深受其害。

ps:
這里請注意,當mybatis-3.1.1-SNAPSHOT.jar的版本為3.0以上時,這樣的配置就可能會引發這樣的錯誤

org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class ‘${driver}’

有同仁解釋了一下這個道理,見如下

在spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 進行自動掃描的時候,設置了sqlSessionFactory 的話,可能會導致PropertyPlaceholderConfigurer失效,也就是用${jdbc.username}這樣之類的表達式,將無法獲取到properties文件里的內容。 導致這一原因是因為,MapperScannerConigurer實際是在解析加載bean定義階段的,這個時候要是設置sqlSessionFactory的話,會導致提前初始化一些類,這個時候,PropertyPlaceholderConfigurer還沒來得及替換定義中的變量,導致把表達式當作字符串復制了。 但如果不設置sqlSessionFactory 屬性的話,就必須要保證sessionFactory在spring中名稱一定要是sqlSessionFactory ,否則就無法自動注入。又或者直接定義 MapperFactoryBean ,再或者放棄自動代理接口方式。

那么此時的簡單解決辦法就是將xml改為如下格式:

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.honzh.biz.database.mapper" />
</bean>

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com