SpringMVC+Spring3+hibernate4 開發環境搭建以及一個開發實例教程
剛剛接觸了SpringMVC這個框架,因此有必要把它拿過來同hibernate、Spring框架進行集成和開發一個實例,在真正企業從頭開發的項目中往往一個穩定的開發環境至關重要,開發一個項目選擇什么樣的搭建平臺也需要有經驗才可以,并不是說你會搭建一個開發平臺然后公司就會用你搭建的開發平臺,一個項目或者一個公司看中的也不是你可以搭出框架,而是在這個框架使用過程中出現的各種問題你可以解決掉。
也就是說呢,無論開發什么項目要做到穩定、環境穩定、開發成本穩定、技術穩定、換句話說就是“風險可控”,你不能說一個新的項目前期開發到一半的時候發現這個開發環境不合適或者出現了啥新的問題你還解決不了,這不是很淡騰的事嗎?
對我們而言需要不僅僅可以搭建一個平臺而且要掌握它,掌握它可以出現的各種問題或bug,如果你沒有掌握到這種程度可以出你只是走馬觀花似得搭建了一個雞窩,沒有什么實用價值的,個人覺得老板或者面試者也是更注重后者,所以呢,這篇博客也是注重說在搭建過程中遇到的各種問題,這也印證了打江山容易但想要坐穩了不易。
本文思路
首先,看一下已經建好的整個項目目錄結構,采用了經典三層在Eclipse里面:
結構很清晰采用了springmvc注解掃描包,里面大部分內容都是通過注解實現的可見通過注解來實現某某個功能也是一種趨勢呀,注解操作簡單、寫的少卻能實現同樣的功能也是由于這個原因受到人們的歡迎。
SpringMVC與Spring集成
它同spring集成要做的事情是把bean交給spring管理,springmvc自己則不再管理bean它通過注解的方式取得spring實例化好的bean類,想讓spring管理其bean就需要實例化Spring自己的WebApplicationContext對象,這個對象是上下對象程序運行所有的參數以及設置都可以從這個對象中取得bean也不列外,我們可以在web.xml文件中設置一個監聽器在程序啟動的時候得到WebApplicationContext對象,這個對象有它自己的屬性,屬性就是我們bean的配置文件,所以它才能夠正確找到bean并將其實例化,我們看一下配置文件,再看一下監聽器類的源碼就可以知道原理。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:config/springAnnotation-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>上面配置是web.xml里配置的bean路徑參數以及spring的監聽器類,再看一看監聽器類的源碼
package org.springframework.web.context;import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener;
public class ContextLoaderListener extends ContextLoader implements ServletContextListener { private ContextLoader contextLoader;
public ContextLoaderListener() { }
public ContextLoaderListener(WebApplicationContext context) { super(context); } } ………………………………………………………………………略…………………………………………………………………………………</pre> 這個類是監聽類的部分代碼,可看到它繼承了ContextLoader這個類并將這個類作為成員變量傳入進來,進去看一下contextloader這個類。
package org.springframework.web.context; ………………………………………………………………………略………………………………………………………………………………… import ………… import org.springframework.util.StringUtils;public class ContextLoader { public static final String CONTEXT_CLASS_PARAM = "contextClass"; public static final String CONTEXT_ID_PARAM = "contextId"; public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses"; public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation"; public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector"; public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey"; private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; private static final Properties defaultStrategies; private static final Map<ClassLoader, WebApplicationContext> currentContextPerThread; private static volatile WebApplicationContext currentContext; private WebApplicationContext context; private BeanFactoryReference parentContextRef;
public ContextLoader() { } ……………………………………………………略…………………………………………………………</pre> 可以看到父類中有這個變量
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";正好是我們配置文件中配置的下面的值,把bean的配置文件值通過contextConfiglocation傳入了spring監聽器,
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:config/springAnnotation-*.xml</param-value> </context-param>
這就是spring與springmvc集成的原理,看了代碼相信大家已經很清楚,可以用一句話概括;將bean交給spring管理。
只有懂了原理在出現錯誤的時候才方便調試,以后再出現監聽器錯誤,例如空指針了、創建失敗了,不用想你就知道可能傳入的配置文件沒有傳入你懂了原理之后也可以自己改它的源碼,傳入更多參數等,其實,無論是spring還是springmvc他們的監聽器都是集成context這個父類而來,再往大了想想web層框架大部分都是集成該類,以后你在學習web框架的時候就會覺得非常簡單,你找到了他們的共同點一個網的節點你找到了剩下的就是學習他們的不同點了每個框架都有自己的特色,我理解的也不是很全面在你不理解時候多思考(它的設計思路)、多動手(看代碼源碼)會逐步理解、逐步深入。
Spring與hibernate4集成
發現現在很多公司也在使用ibatis、mabatis等框架,我們就一起對比著說說他們都是怎么集成,其實都是一樣的有著異曲同工的感覺思路和實現方式是一樣的。
設計思路;
1.配置數據源
2.配置sessionFactory或者sqlMapclient
3.配置Transaction事務
在同數據庫底層集成的框架中大部分也都是這三部,不同之處在于實現類不一樣、實現的功能一樣但對象不一樣,舉個例子;我們都知道sessionFactory屬于一個對象,但在ibatis里面不是這個對象名但有同樣的功能叫做;SqlMapClient.
ibatis這個框架是基于配置文件實現sql語句都寫在配置文件里面,通過sqlMapclient對象可以拿到配置信息,它有兩個重要的屬性即數據源和xml配置文件,其他的是一些輔助參數可有可無。
對于事務也僅僅是管理事務的類不同,但機制一樣我配置的這種都是通過代理事務類實現,好處就不多說了。
1.先看看hibernate數據源配置如下;
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/springmvc"></property> <property name="username" value="root"></property> <property name="password" value="123456"></property> </bean>我使用的是mysql數據庫,也可以改查oracle數據庫,dataSource同ibatis很相似屬性也一樣,需要注意的是在數據源中往往會加入連接池配置,這個也是在這里進行配置。2.sessionFactory
下面是hibernate、sessionFactory配置
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hbiernate.format._sql">true</prop> </props> </property> <property name="configLocations"> <list> <value>classpath*:com/tgb/web/controller/hibernate/hibernate.cfg.test.xml</value> </list> </property> </bean>對比ibatis 配置<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>classpath:sql-map-config.xml</value> </property> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="lobHandler" ref="lobHandler"/> </bean>
可以發現僅僅是屬性值不一樣,屬性都是一樣的說明他們的實現方式都是一樣的但實現類不一樣,其中有個lobHandler屬性是為了處理超大數據設置的屬性,比如一個文件1G存儲在數據庫字段中就需要用到這個配置,進行特殊處理操作。
一個sessionFactory可以對應于多個數據源即可以對用于多個數據庫,這里只是配置了一個數據庫,多個數據庫又會涉及到分布式事務概念又會稍微復雜一點,以后再介紹怎么配置,它管理著數據庫中的表結構和各種表實現對表的操作。
3.事務管理
hibernate配置事務
<bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true" > <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <prop key="add">PROPAGATION_REQUIRED,-Exception</prop> <prop key="update">PROPAGATION_REQUIRED</prop> <prop key="insert">PROPAGATION_REQUIRED</prop> <prop key="get">PROPAGATION_REQUIRED</prop> </props> </property></bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean></pre>
該事務使用了代理方式。為某個類配置事務時需要集成該事物類,如下<bean id="userManagerBase" class="com.tgb.web.controller.service.UserManager"> <property name="userDao" ref="userDao"></property> </bean><bean id="userManager" parent="transactionBase"> <property name="target" ref="userManagerBase"></property> </bean></pre><span style="font-size:14px;"><br />
</span>
用戶管理增加用戶
UserAction.java 以下為對用的各層類和方法可以實現簡單調用,接口里面還可以加入泛型在下篇博客中會設計接口里面怎么使用泛型操作。
@Controller @RequestMapping("/user") public class UserController {@Resource(name="userManager") private IUserManager service; @RequestMapping("/addUser") public void addUser() { User user=new User(); user.setId("1"); user.setAge("2"); user.setUsername("3"); service.addUser(user); }
}</pre>IUserDao interface
public interface IUserDao {void addUser(User user);
}</pre>userDaoImpl
private SessionFactory sessionFactory;public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public void addUser(User user) { sessionFactory.getCurrentSession().save(user); }</pre>IUserManager interface<br />
public interface IUserManager {void addUser(User user);
}</pre>userDaoImpl
public class UserManager implements IUserManager {private IUserDao userDao; public void setUserDao(IUserDao userDao) { this.userDao = userDao; } @Override public void addUser(User user) { userDao.addUser(user); }
}</pre>
代碼簡單相信不用注釋也可以看懂,通過看上面的內容你也會搭建這個搭建并實現簡單的實例了