Spring+SpringMVC+Hibernate 基本Demo(註解、Maven管理)
介紹
本片部落格主要是介紹一下Spring+SpringMVC+Hibernate框架的大致工作流程和其基本的配置程式碼,在部落格最後提供了一個基本的Demo下載,本Demo採用Maven管理依賴。
環境、工具
Java開發環境、IntelliJ IDEA 或者 MyEclipse
Tomcat伺服器(7,8,9均可)
工作流程
Spring容器想必不用多說,大家手頭端的參考書寫的估計很清楚,百度一下也有很多大神寫的也很好,我就不贅述了。在我們實際使用過程中,我們使用Spring來管理事務,Hibernate就全部託管給Spring,而Spring提供的MVC開發模組即SpringMVC當然也是由Spring管理的,其實也不一定要使用SpringMVC,Spring也可以管理Struts2等。Spring的控制反轉和依賴注入這裡也不再多說,大家可以自己去專門學習瞭解。這裡主要簡單說一下SpringMVC的工作流程,因為這與下面的配置有一定的關係。大家結合著工作原理來看配置檔案,兩相印證之下應該會對SpringMVC工作流程以及配置為何這麼配置有一些新的認識。
首先,在說SpringMVC之前,我們先來看一下一張經典的MVC開發模式的圖。
所謂MVC開發模式,Model,View和Controller三者分離,三者分離的目的主要是降低耦合程度。從圖中可以明顯看出,當我們進行Web開發時,我們採用MVC開發模式,應該要有一個清楚的層次認知(“分層”是一個說法,沒有太過具體的明確規定,不一定非要奉某種方法為真理,合適有理有據慣用好用即可),在我的理解以及專案中,主要如圖中分為了dao層(資料庫資料處理層),service層(業務邏輯層),controller層(控制層),前端即view,大家也可以去了解其它分層方法,喜歡就好。
上面那張圖就是本Demo專案結構是這樣的原因:
瞭解了專案為何這麼分層之後,來看一看SpringMVC的工作流程,這部分的介紹將會結合配置檔案一起說,先來看下面一張圖:
其實SpringMVC工作流程按照圖中的步驟來看就非常清楚啦!如果你是第一次接觸可能不太熟悉每個部分的單詞,但不用擔心時間久了慢慢就記得了,只需要大致有個概念就行了,因為這些都是框架幫助我們在後臺完成的,我們只要按照既定模式來配置好就好了。
首先,當收到來自使用者的請求時,就像你要去某公司找某人有事,你就是那個請求,DispatcherServlet首先攔截了所有的請求,就像個門衛大爺似的,進門就把你攔住了,不講清楚你是來幹啥的就不放你過去啦。DispatcherServlet然後把請求交給HandleMapping,HandleMapping就做了一件事,我來看看你是找誰的,弄明白你是找誰的我才能派人通知他不是?因為SpringMVC的Controller裡面是有很多處理方法的。就像你說你們找誰的,那門衛大叔就要把你交傳達室小夥子,查查你要找的人在不在,在哪裡。
在HandleMapping找到以後,接下來就到了HandleAdapter,HandleAdapter對Controller中具體的處理進行的封裝,可以理解為現在找到你要找的那個人啦,現在去見他把,不過不能直接見,得在我們給你的房間見,這個房間就是HandleAdapter,在這個房間進行py交易之後,你搞不清白你交易的結果是啥,接下來就需要對內容進行解析,viewResolver來對你拿到的內容進行解析,就相當於你對交易的結果搞不懂啊,人家用的人家專用的格式,你得找人家專門的部門幫你翻譯一下,最後翻譯成功,找到view,一個完整的工作流程結束。
例子不一定恰當,但是能在一定程度上來表明問題。
接下來結合上面瞭解的工作流程來看看配置檔案如何配置的吧。
新建Maven JavaWeb專案
IntelliJ IDEA建立這一點我不打算自己講,因為其他博主講的真的是太好了,我不認為自己複述一遍有什麼意義,連結如下:
http://www.cnblogs.com/sy270321/p/4723139.html
MyEclipse或者Eclipse請大家自行百度啦,這方面部落格很多的!
主要配置程式碼
先看pom檔案,匯入的jar包,在這裡我宣告,和別人亂七八糟的依賴關係不同,在匯入之後我花了很長的時間把所有不必要的依賴關係都去掉了,能簡單的絕不復雜,這裡我所匯入的包都是我能找到最簡單最方便快捷的匯入方式了,匯入的依賴看起來不多,但是幾乎已經涵蓋了所有用到的內容,每一個依賴是有什麼作用哪裡能用到都有說明,你可以根據自己實際使用情況作出修改。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>example</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!--JavaEE 7.0-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- 這個必須要加,不然連jsp頁面都打不開 jsp頁面第一行引入了這個-->
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp.jstl</artifactId>
<version>1.2.2</version>
</dependency>
<!--MySQL 5.1.38-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!--SpringMVC 4.3.5.RELEASE -->
<!--配置第一個之後會自動匯入一些spring mvc相關的依賴包,但是有可能我們需要包的沒有被自動匯入
因此,之後的第二個及以後是根據專案需要新增需要匯入的spring mvc相關的包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<!--這個包不會隨spring-webmvc匯入,這個包作用是管理Hibernate資源-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<!--這個也不會隨spring-webmvc匯入,作用是為spring-aop提供支援-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<!--Apache Commons dbcp 2.1.1 Apache提供的一些元件,dbcp配置資料來源時需要使用-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<!--支援SpringMVC檔案上傳功能-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<!--Hibernate 4.3.8.Final-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.8.Final</version>
</dependency>
<!-- FastJson 1.2.24 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
<!-- jackson-core Spring MVC配置RequestMappingHandlerAdapter時用到了-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.6</version>
</dependency>
</dependencies>
<build>
<finalName>com.example</finalName>
<plugins>
<!--這個外掛作用是指定編譯這個專案的Java版本和Project Language Level ,針對Intellij IDEA-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
看起來很少對吧,實際上你還可以根據自己情況再刪去一些自己不需要的!這些包具體幹什麼的註釋裡都有介紹,就不再多說了。最後提供下載的文件裡註釋也有的。
然後是web.xml
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!--配置預設進入頁面-->
<welcome-file-list>
<welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置Spring監聽 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 載入spring配置檔案 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<!-- 配置Spring MVC-->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<!-- 配置Hibernate Session -->
<filter-mapping>
<filter-name>openSession</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>openSession</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<!-- 配置字符集 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
在這裡我們看到了DispatcherServlet,他就是圖中那個看門大爺!然後我們看一看applicationContext.xml
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 掃描註解,過濾掉Controller -->
<context:component-scan base-package="com.example">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 引入資料庫資原始檔 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:properties/database.properties" />
</bean>
<!-- 配置資料來源 -->
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${userName}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- AOP -->
<aop:aspectj-autoproxy/>
<!-- 配置 hibernate session -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<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="hibernate.format_sql">true</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="current_session_context_class">thread</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.example.entity</value>
<!--千萬注意此處,要跟著專案名字變化!否則掃描不到實體,自然無法完成與資料庫的對映-->
</list>
</property>
</bean>
<!-- 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!--下面的路徑要換成自己具體的路徑!不然會出錯的-->
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(public * com.example.service.*Service.*(..))" advice-ref="txAdvice"/>
</aop:config>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="REQUIRED"/>
<tx:method name="list*" read-only="true" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
</beans>
然後是spring-mvc.xml
spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 掃描註解 過濾掉Service和Repository,只掃描Controller -->
<context:component-scan base-package="com.example" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<!--配置靜態資源-->
<mvc:resources location="/static/js/" mapping="/js/**"/>
<mvc:resources location="/static/img/" mapping="/img/**"/>
<mvc:resources location="/static/css/" mapping="/css/**"/>
<!--配置SpringMVC註解對應的內容-->
<!--這個是RequestMappingHandlerMapping攔截器,對應即為Controller前面的@RequestMapping註解-->
<!--HandlerMapping 作用如下:
SpringMVC工作過程中,DispatcherServlet收到請求之後會把請求交給HandlerMapping,
HandlerMapping根據配置(此處為註解)找到請求對應的Handler-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--這個是RequestMappingHandlerAdapter-->
<!--HandlerAdapter 作用如下:
SpringMVC工作過程中,HandlerMapping找到Handler,Handler對具體的處理(Controller)進行封裝,
然後由HandlerAdapter對Handler進行具體處理
在這裡我們定義了返回物件自動轉換為Json資料-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="cacheSeconds" value="0"/>
<property name="messageConverters">
<list>
<ref bean="mappingJackson2HttpMessageConverter"/>
<ref bean="mappingStringHttpMessageConverter"/>
</list>
</property>
<property name="webBindingInitializer" ref="webBindingInitializer">
</property>
</bean>
<!--設定檔案上傳的bean,如果專案中不需要上傳檔案可以去掉-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760" />
</bean>
<!--這裡就是Spring對http訊息格式轉換提供的介面-->
<bean id="mappingStringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<!--同上-->
<bean id="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="json"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
<!--註冊轉換器到SpringMVC ,並註冊在了上面的RequestMappingHandlerAdapter中-->
<bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService">
<bean class="org.springframework.core.convert.support.DefaultConversionService"></bean>
</property>
</bean>
<!-- 新增viewResolver -->
<!--viewResolver的作用是接收到返回的ModelAndView的時候把它處理成檢視(jsp檔案)-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2"/>
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
</bean>
</beans>
裡面我寫的註釋挺多了,記得結合上面的工作流程理解配置,兩相比對!