springMVC纯java代码配置(一)- 数据源与事务管理(转载的哦)
原文地址:http://my.oschina.net/devleon/blog/530803?fromerr=9Z8ZFdbf
?
摘要自Spring3.0開 始,Spring正式將JavaConfig引入了Spring框架,我們可以基于純Java代碼來配置Spring容器和Web容器,不再需要任何 XML文件。摒棄XML文件而采用全Java配置的模式正逐漸變成主流。當然我們也不否認現階段的一些配置還依然需要依托XML,Java應用徹底拋棄 XML配置文件還有很長的一段路要走。在本文中,我們將基于純Java代碼來配置一個Spring Web項目。
回憶一下,我們通常需要在applicationContext.xml和xxx-servlet.xml中配置哪些東西?一般來講,我們會配置組 件掃描、數據源、事務管理器、自定義的一些工具類、切面、消息轉換器、靜態資源處理以及視圖等。為了有條理的組織我們的配置類,我們將這些東西分為幾個部 分來配置。
我們首先來配置數據源和事務管理器。既然我們是基于純Java代碼來配置,我們就需要考慮配置的可擴展性,我們希望提供的配置能夠最大可能的適用于 不同的項目,而不是只能用于一個項目。所以,對于數據源和事務管理,我們首先提供一個抽象類DBConfig,這個類提供了事務管理器和一些自定義的數據 庫訪問工具,然后提供一個實現數據源抽象方法。源碼如下:
package?com.kiiwow.framework.config.context.spring.rest.dbconfig;import?javax.sql.DataSource;import?org.springframework.context.annotation.Bean; import?org.springframework.jdbc.core.JdbcTemplate; import?org.springframework.jdbc.datasource.DataSourceTransactionManager;import?com.kiiwow.framework.database.jdbc.JDBCAccess; import?com.kiiwow.framework.database.jdbc.JDBCAccessContext;/***?基本的數據庫配置*?統一配置了數據庫訪問工具和事務管理器 ?*?具體的數據庫配置類需要實現數據源創建的抽象方法 ?*?這個類為實現不同的數據源提供了接口 ?* ?*?@author?leon.gan ?* ?*/ public?abstract?class?DBConfig?{ ????/** ?????*?數據源,由子類實現 ?????*/ ????public?abstract?DataSource?dataSource(); ???? ????/** ?????*?事務管理器 ?????*/ ????@Bean ????public?DataSourceTransactionManager?dataSourceTransactionManager()?{ ????????DataSourceTransactionManager?dataSourceTransactionManager?=?new?DataSourceTransactionManager(); ????????dataSourceTransactionManager.setDataSource(dataSource()); ????????return?dataSourceTransactionManager; ????} ???? ????/** ?????*?SpringJDBC?Template ?????*/ ????@Bean ????public?JdbcTemplate?jdbcTemplate()?{ ????????JdbcTemplate?jdbcTemplate?=?new?JdbcTemplate(); ????????jdbcTemplate.setDataSource(dataSource()); ????????return?jdbcTemplate; ????} ???? ????/** ?????*?JDBC訪問接口 ?????*/ ????@Bean ????public?JDBCAccess?jdbcAccess()?{ ????????JDBCAccess?jdbcAccess?=?new?JDBCAccess(); ????????jdbcAccess.setJdbcTemplate(jdbcTemplate()); ????????return?jdbcAccess; ????} ???? ????/** ?????*?實際用于執行SQL的工具 ?????*/ ????@Bean ????public?JDBCAccessContext?jdbcAccessContext()?{ ????????JDBCAccessContext?jdbcAccessContext?=?new?JDBCAccessContext(); ????????jdbcAccessContext.setJdbcAccess(jdbcAccess()); ????????return?jdbcAccessContext; ????} ???? }我們需要將DBConfig中的事務管理器和數據庫訪問工具注冊成為被Spring管理的Bean,在方法上添加@Bean注解即可,默認是單例。 這個類并沒有指定具體的數據源,而是由子類去實現dataSource()方法來指定,這樣就做到了可擴展。(對于以上代碼中Jdbc相關的工具類,請參考博文《對JdbcTemplate進行簡易封裝以使其更加易用》)接下來,我們提供一個BasicDataSourceDBConfig,這個類繼承自DBConfig,并實現dataSource()方法提供了一個BasicDataSource數據源。源碼如下:
package?com.kiiwow.framework.config.context.spring.rest.dbconfig;import?javax.inject.Inject; import?javax.sql.DataSource;import?org.apache.commons.dbcp.BasicDataSource; import?org.springframework.context.annotation.Bean; import?com.kiiwow.framework.config.context.spring.KiiwowEnvironment; /** ?*?Apache?BasicDataSource?數據源配置 ?* ?*?@author?leon.gan ?* ?*/ public?class?BasicDataSourceDBConfig?extends?DBConfig?{ ????@Inject ????KiiwowEnvironment?environment; ???? ????@Bean ????public?DataSource?dataSource()?{ ????????BasicDataSource?ds?=?new?BasicDataSource(); ????????ds.setDriverClassName(environment.getProperty("jdbc.driver")); ????????ds.setUrl(environment.getProperty("kiiwow_jdbc.url")); ????????ds.setUsername(environment.getProperty("kiiwow_jdbc.username")); ????????ds.setPassword(environment.getProperty("kiiwow_jdbc.password")); ????????ds.setTestOnBorrow(true); ????????ds.setValidationQuery("select?1?from?dual"); ????????return?ds; ????} ???? }我們在實際使用時,只要使用BasicDataSourceDBConfig這個類即可。同理,我們也可以提供一個C3p0DataSourceDBConfig類來實現C3P0數據源,源碼如下:
package?com.kiiwow.framework.config.context.spring.rest.dbconfig;import?javax.inject.Inject; import?javax.sql.DataSource;import?org.springframework.context.annotation.Bean; import?com.kiiwow.framework.config.context.spring.KiiwowEnvironment; import?com.mchange.v2.c3p0.ComboPooledDataSource; /** ?*?C3P0數據源配置 ?* ?*?@author?leon.gan ?* ?*/ public?class?C3p0DataSourceDBConfig?extends?DBConfig?{ ????@Inject ????KiiwowEnvironment?environment; ???? ????@Bean ????public?DataSource?dataSource()?{ ????????try?{ ????????????ComboPooledDataSource?dataSource?=?new?ComboPooledDataSource(); ????????????dataSource.setDriverClass(environment.getProperty("db.c3p0.driverClassName")); ????????????dataSource.setJdbcUrl(environment.getProperty("kiiwow_db.c3p0.url")); ????????????dataSource.setUser(environment.getProperty("kiiwow_db.c3p0.username")); ????????????dataSource.setPassword(environment.getProperty("kiiwow_db.c3p0.password")); ????????????//當連接池在沒有可用空閑連接時每次可以新增的連接數 ????????????dataSource.setAcquireIncrement(environment.getRequiredProperty("c3p0.acquireIncrement",?int.class,?5)); ????????????//連接池初始連接數 ????????????dataSource.setInitialPoolSize(environment.getRequiredProperty("c3p0.initialPoolSize",?int.class,?5)); ????????????//連接池可持有的最大連接數 ????????????dataSource.setMaxPoolSize(environment.getRequiredProperty("c3p0.maxPoolSize",?int.class,?200)); ????????????//連接池可持有的最小連接數 ????????????dataSource.setMinPoolSize(environment.getRequiredProperty("c3p0.minPoolSize",?int.class,?5)); ????????????//連接池中的連接失效的閥值(即最大未被使用時長) ????????????dataSource.setMaxIdleTime(environment.getRequiredProperty("c3p0.maxIdleSize",?int.class,?1800)); ????????????//與MaxIdleTime配合使用,必須小于MaxIdleTime的值,用于減少連接池中的連接 ????????????dataSource.setMaxIdleTimeExcessConnections(environment.getRequiredProperty("c3p0.maxIdleTimeExcessConnections",?int.class,?1200)); ????????????//連接最大存活時間,超過這個時間將被斷開,正在使用的連接在使用完畢后被斷開 ????????????dataSource.setMaxConnectionAge(environment.getRequiredProperty("c3p0.maxConnectionAge",?int.class,?1000)); ????????????//進行空閑連接測試的SQL ????????????dataSource.setPreferredTestQuery(environment.getProperty("c3p0.preferredTestQuery",?"select?1?from?dual")); ????????????//進行空閑連接測試的時間間隔 ????????????dataSource.setIdleConnectionTestPeriod(environment.getRequiredProperty("c3p0.idleConnectionTestPeriod",?int.class,?120)); ????????????return?dataSource; ????????}?catch?(Exception?e)?{ ????????????throw?new?RuntimeException(e); ????????} ????} ???? }在上面的代碼中,出現了一個KiiwowEnvironment類,這個類是對 org.springframework.core.env.Environment的封裝,以實現編碼解碼功能。為了說明這個類的作用,我們首先來看看 Environment這個接口的作用。這個接口是與@PropertySources注解配合工作的,我們在@PropertySources注解中指 定的配置文件會自動被加載到Environment的實現中以key-value形式存儲,我們可以通過Environment提供的 getProperty(String key)等方法通過屬性名獲取屬性值。
在我們的設計中有一個特殊的需求,我們希望配置在properties文件中的數據庫連接以及賬號密碼都是經過加密的,這樣可以一定程度上防止數據庫信息泄 露。所以我們定義在properties文件中所有以"kiiwow_"開頭的屬性,其對應的值都是經過Base64編碼的結果,所以在我們通過 Environment取出這些值的時候也要進行解碼。不幸的是,Environment并不具備編碼解碼功能,我們需要自己實現,所以有了 KiiwowEnvironment這個類。源碼如下:
package?com.kiiwow.framework.config.context.spring;import?javax.inject.Inject;import?org.springframework.core.env.Environment; import?org.springframework.stereotype.Component; import?com.kiiwow.framework.util.DigestUtils; /** ?*?自定義環境類 ?*?基于JavaConfig配置Spring的情況下,使用@PropertySource注解將配置屬性注入Environment中后 ?*?Environment不能支持解碼已編碼的屬性值。所以提供這個類對數據獲取進行解碼操作。 ?* ?*?@author?leon.gan ?* ?*/ @Component public?class?KiiwowEnvironment?{ ????@Inject ????Environment?env; ???? ????/** ?????*?所有以kiiwow_開頭的屬性,其值都需要經過Base64解碼后使用 ?????*/ ????public?String?getProperty(String?propertyName)?{ ????????if?(propertyName.startsWith("kiiwow_"))?{ ????????????String?originalValue?=?env.getProperty(propertyName); ????????????return?DigestUtils.decodeBase64(originalValue); ????????}?else?{ ????????????return?env.getProperty(propertyName); ????????} ????} ???? ????/** ?????*?沒有配置屬性時采用默認值 ?????*/ ????public?String?getProperty(String?propertyName,?String?defaultValue)?{ ????????if?(propertyName.startsWith("kiiwow_"))?{ ????????????String?originalValue?=?env.getProperty(propertyName); ????????????return?originalValue?==?null???null?:?DigestUtils.decodeBase64(originalValue); ????????}?else?{ ????????????return?env.getProperty(propertyName)?==?null???defaultValue?:?env.getProperty(propertyName); ????????} ????} ???? ????/** ?????*?將值轉換為指定類型 ?????*/ ????public?<T>?T?getRequiredProperty(String?propertyName,?Class<T>?targetType)?{ ????????return?env.getRequiredProperty(propertyName,?targetType); ????} ???? ????/** ?????*?屬性不存在則返回默認值 ?????*/ ????public?<T>?T?getRequiredProperty(String?propertyName,?Class<T>?targetType,?T?defaultValue)?{ ????????try?{ ????????????return?env.getRequiredProperty(propertyName,?targetType); ????????}?catch?(Exception?e)?{ ????????????return?defaultValue; ????????} ????} ???? }從上面的代碼可以看到,我們只是將org.springframework.core.env.Environment 注入,然后在調用他的getProperty(String key)等方法前增加了判斷屬性名是否以"kiiwow_"開頭的邏輯。同時提供了處理屬性名不存在于配置文件則返回默認值的方法。特別注意,我們需要將 這個類注冊成為Spring容器的一個組件,即在類上使用@Component注解,否則org.springframework.core.env.Environment是無法注入的。(這個解決方法特別感謝@YouKnowNothing 的幫助)。
至此,我們對于數據源和事務管理的配置就結束了。我們可以自由繼承DBConfig類來擴展我們需要的數據源,也能對配置文件中的敏感信息進行編碼 防止信息泄露。不過需要指出的是,這種處理敏感信息的方法依然不是最優的。由于我們要進行解碼,所以我們只能使用雙向加密策略,如果別人知道了你的編碼策 略,也能夠輕松破解。我們將在下一篇文章中講解對于靜態資源、視圖解析器、消息轉換器的配置以及web.xml的Java代碼化。
感謝您的閱覽,勞煩點個贊。
轉載于:https://www.cnblogs.com/SummerinShire/articles/5583767.html
總結
以上是生活随笔為你收集整理的springMVC纯java代码配置(一)- 数据源与事务管理(转载的哦)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日志服务接入方式之Unity 3D篇
- 下一篇: shell初涉