1. 程式人生 > >Spring+SpringMVC+Hibernate 基本Demo(註解、Maven管理)

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開發模式


    所謂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> 

    裡面我寫的註釋挺多了,記得結合上面的工作流程理解配置,兩相比對!

資源下載