简体   繁体   中英

Understanding Spring MVC configuration

I have a Spring MVC application, and I was pretty confident I understand all the various configuration I have set up, however, in a recent exercise I have been switching over to use pure annotation based config (apart from the security configuration) and I have seen a change in the application's behavior which has made me think twice on a few points.

The main behavior change, is that it appears that my old app was running an OpenSessionInView type pattern - as several of my domain objects were lazy loading elements, but those elements could then still be accessed outside of the transactional/service layer classes (eg in my controllers) - having switched to annotations, this now fails as you would expect with lazy loading errors as the session is not open in my controller layer.

Below is the config I have been using - can any one explain which part of this is responsible for the OpenSessionInView type behavior my app was displaying previously?

App Context config file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xmlns:cloud="http://schema.cloudfoundry.org/spring" xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd   
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd   
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd   
    http://www.springframework.org/schema/jee 
    http://www.springframework.org/schema/jee/spring-jee.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://schema.cloudfoundry.org/spring 
    http://schema.cloudfoundry.org/spring/cloudfoundry-spring-0.7.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/cache 
    http://www.springframework.org/schema/cache/spring-cache.xsd">


    <context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
    <context:spring-configured />
    <context:annotation-config />
    <mvc:annotation-driven />
    <aop:aspectj-autoproxy proxy-target-class="true" />
    <context:component-scan base-package="com.tmm.enterprise.adapter"></context:component-scan>
    <context:component-scan base-package="com.tmm.enterprise.service"></context:component-scan>
    <context:component-scan base-package="com.tmm.enterprise.helper"></context:component-scan>
    <context:component-scan base-package="com.tmm.enterprise.util"></context:component-scan>
    <context:component-scan base-package="com.tmm.enterprise.repository"></context:component-scan>
    <context:component-scan base-package="com.tmm.enterprise.core.dao"></context:component-scan>
    <context:component-scan base-package="com.tmm.enterprise.security.dao"></context:component-scan>


    <!--Http client -->
    <bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
        <property name="state" ref="httpState" />
    </bean>

    <!--Http state -->
    <bean id="httpState" factory-bean="httpStateFactory" factory-method="buildState"/> 

    <!--Http client -->
    <bean id="httpClientFactory"
        class="org.springframework.http.client.CommonsClientHttpRequestFactory">
        <constructor-arg ref="httpClient" />
    </bean>

    <!--RestTemplate -->
    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg ref="httpClientFactory" />
    </bean>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        lazy-init="default" autowire="default">
        <property name="driverClass" value="${database.driverClassName}" />
        <property name="jdbcUrl" value="${database.url}" />
        <property name="user" value="${database.username}" />
        <property name="password" value="${database.password}" />
    </bean>    


    <bean class="org.springframework.orm.jpa.JpaTransactionManager"
        id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <bean id="applicationController" class="com.tmm.enterprise.service.ApplicationService"></bean>

    <bean id="socialConfig"
        class="com.tmm.enterprise.configuration.SocialConfiguration"></bean>
    <bean id="cachingConfig"
        class="com.tmm.enterprise.configuration.CachingConfiguration"></bean>

    <tx:annotation-driven mode="aspectj"
        transaction-manager="transactionManager" proxy-target-class="true" />


    <bean
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitName" value="persistenceUnit" />
    </bean>

    <bean id="geocoder" class="com.google.code.geocoder.Geocoder" />

    <bean id="validatorFactory" class="javax.validation.Validation"
        factory-method="buildDefaultValidatorFactory" />

    <bean id="validator" factory-bean="validatorFactory"
        factory-method="getValidator" />
</beans>

MVC Config:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:p="http://www.springframework.org/schema/p" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd     
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd     
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <!-- The controllers are autodetected POJOs labeled with the @Controller annotation. -->
    <context:component-scan base-package="com.tmm.enterprise.controller" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

    <!-- Turns on support for mapping requests to Spring MVC @Controller methods
         Also registers default Formatters and Validators for use across all @Controllers -->
    <mvc:annotation-driven/>

    <mvc:resources mapping="/resouces/**" location="/styles, /images, /javascript, /libs" />

    <!-- a higher value meaning greater in terms of sorting.  -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="3">
        <property name="alwaysUseFullPath" value="true" />
    </bean>

    <!-- register "global" interceptor beans to apply to all registered HandlerMappings -->
    <mvc:interceptors>
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang"/>
    </mvc:interceptors>

    <!-- selects a static view for rendering without the need for an explicit controller -->
    <mvc:view-controller path="/login"/>
    <!--mvc:view-controller path="/index"/-->
    <mvc:view-controller path="/uncaughtException"/>
    <mvc:view-controller path="/resourceNotFound"/>
    <mvc:view-controller path="/dataAccessFailure"/>
    <mvc:view-controller path="/jobs" view-name="jobsPage"/>
    <mvc:view-controller path="/applications" view-name="jobsPage"/>
    <mvc:view-controller path="/users" view-name="usersPage"/>
    <mvc:view-controller path="/companies" view-name="companiesPage"/>
    <mvc:view-controller path="/tos" view-name="tos"/>
    <mvc:view-controller path="/about" view-name="about"/>
    <mvc:view-controller path="/privacypolicy" view-name="privacyPolicy"/>
    <mvc:view-controller path="/sitemap.xml" view-name="sitemap"/>

    <!-- Resolves logical view names returned by Controllers to Tiles; a view
         name to resolve is treated as the name of a tiles definition -->
    <bean class="org.springframework.js.ajax.AjaxUrlBasedViewResolver" id="tilesViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    </bean>

    <!-- Configures the Tiles layout system -->
    <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/layouts/layouts.xml</value>
                <!-- Scan views directory for Tiles configurations -->
                <value>/WEB-INF/views/**/views.xml</value>
            </list>
        </property>
    </bean>

    <!-- Resolves localized messages*.properties and application.properties files in the application to allow for internationalization. 
        The messages*.properties files translate Roo generated messages which are part of the admin interface, the application.properties
        resource bundle localizes all application specific messages such as entity names and menu items. -->
    <bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource" p:basenames="WEB-INF/i18n/application" p:fallbackToSystemLocale="false"/>

    <!-- store preferred language configuration in a cookie -->
    <bean class="org.springframework.web.servlet.i18n.CookieLocaleResolver" id="localeResolver" p:cookieName="locale"/> 

    <!-- resolves localized <theme_name>.properties files in the classpath to allow for theme support -->
    <bean class="org.springframework.ui.context.support.ResourceBundleThemeSource" id="themeSource"/>

    <!-- store preferred theme configuration in a cookie -->
    <bean class="org.springframework.web.servlet.theme.CookieThemeResolver" id="themeResolver" p:cookieName="theme" p:defaultThemeName="standard"/>

    <!-- This bean resolves specific types of exceptions to corresponding logical - view names for error views. 
         The default behaviour of DispatcherServlet - is to propagate all exceptions to the servlet container: 
         this will happen - here with all other types of exceptions. -->
    <bean class="com.tmm.enterprise.controller.exception.NerdExceptionHandler" p:defaultErrorView="uncaughtException">
        <property name="exceptionMappings">
            <props>
                <prop key=".DataAccessException">dataAccessFailure</prop>
                <prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop>
                <prop key=".TypeMismatchException">resourceNotFound</prop>
                <prop key=".MissingServletRequestParameterException">resourceNotFound</prop>
            </props>
        </property>
    </bean>


    <!-- Controllers --> 
    <bean id="connectController" class="com.tmm.enterprise.controller.ConnectController"></bean>

    <!-- allows for integration of file upload functionality -->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>

    <bean id="ajaxViewResolver"
        class="com.tmm.enterprise.views.AjaxViewResolver">
        <property name="ajaxView">
            <bean class="com.tmm.enterprise.views.AjaxView" />
        </property>
        <property name="ajaxPrefix" value="ajax_"></property>
    </bean>

    <bean id="editableViewResolver"
        class="com.tmm.enterprise.views.EditableViewResolver">
        <property name="editableView">
            <bean class="com.tmm.enterprise.views.EditableView" />
        </property>
        <property name="editablePrefix" value="editable_"></property>
    </bean>
</beans>

The OpenSessionInView(Hibernate)/OpenEntityManagerInView(JPA) behaviour is often part of a filter defined in web.xml, but can also be done using an interceptor, as described in this answer . You can use the OpenEntityManagerInViewInterceptor for JPA.

<mvc:interceptors>
    <bean class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
        <property name="sessionFactory">
            <ref local="sessionFactory" />
        </property>
    </bean>
</mvc:interceptors>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM