Spring-MVC:创建良好的基础架构(配置)并避免重复

Spring-MVC : Creating a good infrastructure(configuration) and avoiding duplicates

我一直在开发 Spring-MVC 应用程序。最近我 运行 遇到了一些 @Scheduled 方法的问题,我注意到整个配置被加载了 4 次。因此,@Scheduled 方法被调用了 4 次。

3 个不正确的配置因 NullPointerException 而消失(我在 SO 上被告知),一个幸存。我非常想知道如何正确配置我的项目,所以只有一个配置被加载,而不是 4 个,并在此过程中了解 Spring-MVC,Spring。

由于 servlet-context 很大,我在 pastebin 上发布 web.xml,所以我也可以有地方放置 JAVA 代码。

Servlet-context.xml :

  <context:annotation-config/>

    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <beans:bean class="org.springframework.mobile.device.DeviceWebArgumentResolver"/>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>
    <mvc:interceptors>
        <beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor"/>
    </mvc:interceptors>

    <mvc:default-servlet-handler/>

    <resources mapping="/resources/" location="/resources/"/>

    <beans:bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/"/>
        <beans:property name="suffix" value=".jsp"/>
    </beans:bean>

    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
                destroy-method="close">
        <beans:property name="driverClassName" value="org.postgresql.Driver"/>
        <beans:property name="url"
                        value="jdbc:postgresql://localhost:5432/dbname"/>
        <beans:property name="username" value="dbuser"/>
        <beans:property name="password" value="dbpass"/>
        <beans:property name="removeAbandoned" value="true"/>
        <beans:property name="removeAbandonedTimeout" value="20"/>
        <beans:property name="defaultAutoCommit" value="false"/>
    </beans:bean>


    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory"
                class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource"/>
        <beans:property name="annotatedClasses">
            <beans:list>
                <beans:value>com.journaldev.spring.model.Person</beans:value>
                <beans:value>com.journaldev.spring.model.Notes</beans:value>
                <beans:value>com.journaldev.spring.model.Canvas</beans:value>
                <beans:value>com.journaldev.spring.model.Section</beans:value>
                <beans:value>com.journaldev.spring.model.Attachment</beans:value>

                <beans:value>com.journaldev.spring.model.GroupAccount</beans:value>
                <beans:value>com.journaldev.spring.model.GroupMembers</beans:value>
                <beans:value>com.journaldev.spring.model.GroupCanvas</beans:value>
                <beans:value>com.journaldev.spring.model.GroupSection</beans:value>
                <beans:value>com.journaldev.spring.model.GroupNotes</beans:value>
                <beans:value>com.journaldev.spring.model.GroupAttachments
                </beans:value>

                <beans:value>com.journaldev.spring.model.Token</beans:value>
                <beans:value>com.journaldev.spring.model.WaitingMembers
                </beans:value>
                <beans:value>com.journaldev.spring.model.NoteHistory</beans:value>
                <beans:value>com.journaldev.spring.model.GroupNoteHistory
                </beans:value>

                <beans:value>com.journaldev.spring.model.Feedback</beans:value>
                <beans:value>com.journaldev.spring.model.UnreadNotes</beans:value>
                <beans:value>com.journaldev.spring.model.SessionState</beans:value>
                <beans:value>com.journaldev.spring.model.FeatureRequest
                </beans:value>
                <beans:value>com.journaldev.spring.model.FeatureComment
                </beans:value>
                <beans:value>com.journaldev.spring.model.FeatureLike</beans:value>
                <beans:value>com.journaldev.spring.model.OnlineUsers</beans:value>
                <beans:value>com.journaldev.spring.model.NoteCount</beans:value>
                <beans:value>com.journaldev.spring.model.NoteLock</beans:value>
                <beans:value>com.journaldev.spring.model.ChatMessages</beans:value>
                <beans:value>com.journaldev.spring.model.Conversation</beans:value>
                <beans:value>com.journaldev.spring.model.Replies</beans:value>
                <beans:value>com.journaldev.spring.model.Notification</beans:value>
                <beans:value>com.journaldev.spring.model.Statistics</beans:value>
                <beans:value>com.journaldev.spring.model.PrivateChannel</beans:value>
                <beans:value>com.journaldev.spring.model.GroupChannels</beans:value>
            </beans:list>
        </beans:property>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect
                </beans:prop>
                <beans:prop key="hibernate.show_sql">false</beans:prop>
                <beans:prop key="connection.pool_size">200</beans:prop>
                <beans:prop key="c3p0.max_size">200</beans:prop>
                <beans:prop key="c3p0.timeout">1000</beans:prop>
             <!--   <beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>
                <beans:prop key="hibernate.order_updates">true</beans:prop>-->
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

    <task:annotation-driven/>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <beans:bean id="transactionManager"
                class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <!-- Person beans being here -->
    <beans:bean id="personDAO" class="com.journaldev.spring.dao.PersonDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>
    <beans:bean id="personService"
                class="com.journaldev.spring.service.PersonServiceImpl">
        <beans:property name="personDAO" ref="personDAO"/>
    </beans:bean>


    <!--  <beans:bean id="bayeux" class="org.cometd.server.BayeuxServerImpl" init-method="start" destroy-method="stop">
          <beans:property name="transports">
              <beans:list>
                  <beans:bean id="jsonTransport" class="org.cometd.server.transport.JSONTransport">
                      <beans:constructor-arg ref="bayeux"/>
                  </beans:bean>
                  <beans:bean id="jsonpTransport" class="org.cometd.server.transport.JSONPTransport">
                      <beans:constructor-arg ref="bayeux"/>
                  </beans:bean>
              </beans:list>
        </beans:property>
      </beans:bean>-->

    <!-- Group Account beans begin here -->

    <beans:bean id="groupAccountDAO"
                class="com.journaldev.spring.dao.GroupAccountDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="groupAccountService"
                class="com.journaldev.spring.service.GroupAccountServiceImpl">
        <beans:property name="groupAccountDAO" ref="groupAccountDAO"/>
    </beans:bean>

    <!--Group Members bean begin here -->
    <beans:bean id="groupMembersDAO"
                class="com.journaldev.spring.dao.GroupMembersDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="groupMembersService"
                class="com.journaldev.spring.service.GroupMembersServiceImpl">
        <beans:property name="groupMembersDAO" ref="groupMembersDAO"/>
    </beans:bean>

    <!-- Notes bean begin here -->
    <beans:bean id="notesDAO" class="com.journaldev.spring.dao.NotesDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="notesService"
                class="com.journaldev.spring.service.NotesServiceImpl">
        <beans:property name="notesDAO" ref="notesDAO"/>
    </beans:bean>

    <!--GroupNotes begin here -->

    <beans:bean id="groupNotesDAO" class="com.journaldev.spring.dao.GroupNotesDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="groupNotesService"
                class="com.journaldev.spring.service.GroupNotesServiceImpl">
        <beans:property name="groupNotesDAO" ref="groupNotesDAO"/>
    </beans:bean>


    <!-- Canvas Beans begin here -->

    <beans:bean id="canvasDAO" class="com.journaldev.spring.dao.CanvasDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="canvasService"
                class="com.journaldev.spring.service.CanvasServiceImpl">
        <beans:property name="canvasDAO" ref="canvasDAO"/>
    </beans:bean>

    <!--Group Canvas beans begin here -->
    <beans:bean id="groupCanvasDAO"
                class="com.journaldev.spring.dao.GroupCanvasDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="groupCanvasService"
                class="com.journaldev.spring.service.GroupCanvasServiceImpl">
        <beans:property name="groupCanvasDAO" ref="groupCanvasDAO"/>
    </beans:bean>

    <!-- Section beans begin here -->
    <beans:bean id="sectionDAO" class="com.journaldev.spring.dao.SectionDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="sectionService"
                class="com.journaldev.spring.service.SectionServiceImpl">
        <beans:property name="sectionDAO" ref="sectionDAO"/>
    </beans:bean>

    <!-- Group Section beans begin here -->
    <beans:bean id="groupSectionDAO"
                class="com.journaldev.spring.dao.GroupSectionDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="groupSectionService"
                class="com.journaldev.spring.service.GroupSectionServiceImpl">
        <beans:property name="groupSectionDAO" ref="groupSectionDAO"/>
    </beans:bean>


    <beans:bean id="tokenDAO" class="com.journaldev.spring.dao.TokenDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="tokenService"
                class="com.journaldev.spring.service.TokenServiceImpl">
        <beans:property name="tokenDAO" ref="tokenDAO"/>
    </beans:bean>


    <beans:bean id="attachDAO" class="com.journaldev.spring.dao.AttachmentDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="attachService"
                class="com.journaldev.spring.service.AttachmentServiceImpl">
        <beans:property name="attachmentDAO" ref="attachDAO"/>
    </beans:bean>


    <beans:bean id="mattachDAO"
                class="com.journaldev.spring.dao.GroupAttachmentsDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="mattachService"
                class="com.journaldev.spring.service.GroupAttachmentsServiceImpl">
        <beans:property name="groupAttachmentsDAO" ref="mattachDAO"/>
    </beans:bean>

    <beans:bean id="waitingDAO"
                class="com.journaldev.spring.dao.WaitingMembersDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="waitingService"
                class="com.journaldev.spring.service.WaitingMembersServiceImpl">
        <beans:property name="waitingMembersDAO" ref="waitingDAO"/>
    </beans:bean>

    <beans:bean id="historyDAO"
                class="com.journaldev.spring.dao.NoteHistoryDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="historyService"
                class="com.journaldev.spring.service.NoteHistoryServiceImpl">
        <beans:property name="noteHistoryDAO" ref="historyDAO"/>
    </beans:bean>

    <beans:bean id="mhistoryDAO"
                class="com.journaldev.spring.dao.GroupNoteHistoryDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="mhistoryService"
                class="com.journaldev.spring.service.GroupNoteHistoryServiceImpl">
        <beans:property name="groupNoteHistoryDAO" ref="mhistoryDAO"/>
    </beans:bean>


    <beans:bean id="feedbackDAO" class="com.journaldev.spring.dao.FeedbackDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="feedbackService"
                class="com.journaldev.spring.service.FeedbackServiceImpl">
        <beans:property name="feedbackDAO" ref="feedbackDAO"/>
    </beans:bean>


    <beans:bean id="unreadDAO"
                class="com.journaldev.spring.dao.UnreadNotesDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>


    <beans:bean id="unreadService"
                class="com.journaldev.spring.service.UnreadNotesServiceImpl">
        <beans:property name="unreadNotesDAO" ref="unreadDAO"/>
    </beans:bean>

    <beans:bean id="sessionStateDAO"
                class="com.journaldev.spring.dao.SessionStateDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="sessionService"
                class="com.journaldev.spring.service.SessionStateServiceImpl">
        <beans:property name="sessionStateDAO" ref="sessionStateDAO"/>
    </beans:bean>


    <beans:bean id="featuresDAO"
                class="com.journaldev.spring.dao.FeatureRequestDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="featuresService"
                class="com.journaldev.spring.service.FeatureRequestServiceImpl">
        <beans:property name="featureRequestDAO" ref="featuresDAO"/>
    </beans:bean>


    <beans:bean id="featureCommentDAO"
                class="com.journaldev.spring.dao.FeatureCommentDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="featureCommentService"
                class="com.journaldev.spring.service.FeatureCommentServiceImpl">
        <beans:property name="featureCommentDAO" ref="featureCommentDAO"/>
    </beans:bean>

    <beans:bean id="featureLikeDAO"
                class="com.journaldev.spring.dao.FeatureLikeDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="featureLikeService"
                class="com.journaldev.spring.service.FeatureLikeServiceImpl">
        <beans:property name="featureLikeDAO" ref="featureLikeDAO"/>
    </beans:bean>


    <beans:bean id="onlineUsersDAO"
                class="com.journaldev.spring.dao.OnlineUsersDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="onlineUsersService"
                class="com.journaldev.spring.service.OnlineUsersServiceImpl">
        <beans:property name="onlineUsersDAO" ref="onlineUsersDAO"/>
    </beans:bean>

    <beans:bean id="noteCountDAO" class="com.journaldev.spring.dao.NoteCountDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="noteCountService"
                class="com.journaldev.spring.service.NoteCountServiceImpl">
        <beans:property name="noteCountDAO" ref="noteCountDAO"/>
    </beans:bean>


    <beans:bean id="noteLockDAO" class="com.journaldev.spring.dao.NoteLockDAOImpl">
        <beans:property name="sessionFactory"
                        ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="noteLockService"
                class="com.journaldev.spring.service.NoteLockServiceImpl">
        <beans:property name="noteLockDAO" ref="noteLockDAO"/>
    </beans:bean>


    <beans:bean id="chatDAO" class="com.journaldev.spring.dao.ChatMessagesDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="chatService" class="com.journaldev.spring.service.ChatMessagesServiceImpl">
        <beans:property name="chatDAO" ref="chatDAO"/>
    </beans:bean>


    <beans:bean id="conversationDAO" class="com.journaldev.spring.dao.ConversationDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="conversationService" class="com.journaldev.spring.service.ConversationServiceImpl">
        <beans:property name="conversationDAO" ref="conversationDAO"/>
    </beans:bean>

    <beans:bean id="repliesDAO" class="com.journaldev.spring.dao.RepliesDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="repliesService" class="com.journaldev.spring.service.RepliesServiceImpl">
        <beans:property name="repliesDAO" ref="repliesDAO"/>
    </beans:bean>


    <beans:bean id="notificationDAO" class="com.journaldev.spring.dao.NotificationDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="notificationService" class="com.journaldev.spring.service.NotificationServiceImpl">
        <beans:property name="notificationDAO" ref="notificationDAO"/>
    </beans:bean>


    <beans:bean id="statisticsDAO" class="com.journaldev.spring.dao.StatisticsDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="statisticsService" class="com.journaldev.spring.service.StatisticsServiceImpl">
        <beans:property name="statisticsDAO" ref="statisticsDAO"/>
    </beans:bean>


    <beans:bean id="privateChannelDAO" class="com.journaldev.spring.dao.PrivateChannelDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="privateChannelService" class="com.journaldev.spring.service.PrivateChannelServiceImpl">
        <beans:property name="privateChannelDAO" ref="privateChannelDAO"/>
    </beans:bean>


   <beans:bean id="groupChannelsDAO" class="com.journaldev.spring.dao.GroupChannelsDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

    <beans:bean id="groupChannelsService" class="com.journaldev.spring.service.GroupChannelsServiceImpl">
        <beans:property name="groupChannelsDAO" ref="groupChannelsDAO"/>
    </beans:bean>

    <!--<beans:bean id="chatBean" class="com.journaldev.spring.chat.ChatServiceImpl"/>-->

    <!--Login bean -->
    <beans:bean id="LoginServiceImpl"
                class="com.journaldev.spring.service.LoginServiceImpl"/>

    <context:component-scan base-package="com.journaldev.spring"/>

    <!-- locale -->
    <beans:bean id="messageSource"
                class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename" value="classpath:/locale/messages"/>
        <beans:property name="defaultEncoding" value="UTF-8"/>
    </beans:bean>

    <context:property-placeholder location="classpath:application.properties"/>

    <!-- default locale -->
    <beans:bean id="localeResolver"
                class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <beans:property name="defaultLocale" value="de"/>
    </beans:bean>

    <!-- Change locale via url. -->
    <beans:bean id="localeChangeInterceptor"
                class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <beans:property name="paramName" value="lang"/>
    </beans:bean>

    <beans:bean id="handlerMapping"
                class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <beans:property name="interceptors">
            <beans:list>
                <beans:ref bean="localeChangeInterceptor"/>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean class="com.journaldev.spring.service.DoNotTruncateMyUrls"/>

    <beans:bean id="multipartResolver"
                class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <beans:property name="maxUploadSize" value="52428800"/>
    </beans:bean>

    <beans:bean
            class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <beans:property name="messageConverters" ref="jsonMessageConverter"/>
    </beans:bean>

    <beans:bean id="jsonMessageConverter"
                class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>

</beans:beans>

如前所述,here is the URL for web.xml and here 是安全应用程序。context.xml

在整个项目中,模型如下所示:

@Entity
@Table(name = "canvas")
public class Canvas {

    @Id
    @Column(name="canvasid")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "canvas_gen")
    @SequenceGenerator(name = "canvas_gen",sequenceName = "canvas_seq")
    @Index(name = "canvasid")
    private int canvasid;
//Other variables, mappings, getters, setters
}

DAO 在整个项目中看起来像这样:

@Transactional
@Repository
public class CanvasDAOImpl implements CanvasDAO{


    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sf){
        this.sessionFactory = sf;
    }

    private Session session;

    public void setSession(Session session){this.session = session;}

   @overrride
   public returnType methodName(params..){
        session = this.sessionFactory.getCurrentSession();

}
}

最后,我的服务层如下所示:

@Service
@Transactional
public class CanvasServiceImpl implements CanvasService {
 private CanvasDAO canvasDAO;

    public void setCanvasDAO(CanvasDAO canvasDAO) {
        this.canvasDAO = canvasDAO;
    }
//methods
}

我在整个 java 文件中保持了相同的结构。为什么我的配置加载了 4 次而不是 1 次。任何关于优化的总体建议。谢谢。

编辑

我的服务是这样的:

@Service
@Transactional
public class AttachmentServiceImpl implements AttachmentService{

    @Autowired
    private AttachmentDAO attachmentDAO;
// The guy below stays or not? why?
 public void setAttachmentDAO(AttachmentDAO attachmentDAO){
        this.attachmentDAO = attachmentDAO;
    }
}

使用注释的目的是消除对 xml 配置的需要。如果您正在使用 Spring @Service@Repository 注释,那么您可以从上面发布的 xml 中删除所有服务和 dao 定义,并将它们替换为一行。

<context:component-scan base-package="x.y.z.service, x.y.z.repository" />

然后您可以使用 @Autowired 注释将所有服务 类 更新为如下所示,以便 Spring 注入相关的 DAO:

@Service
@Transactional
public class CanvasServiceImpl implements CanvasService {

    @Autowired
    private CanvasDAO canvasDAO;
}

您还在 web.xml 中多次加载 Spring 安全上下文。一次通过 ContextLoaderListener 一次通过 RequestDispatcher 配置:

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml,/WEB-INF/spring/appServlet/security-applicationContext.xml</param-value>
    </context-param>

    <session-config>
        <session-timeout>1440</session-timeout>
    </session-config>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    ...

    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/security-applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

</web-app> 

然后,为了完成任务,您还需要在每次加载时在安全上下文中导入 Web 应用程序配置。

<import resource="servlet-context.xml" /> 

我通常会按照此处所述进行配置。我相信这被认为是最佳实践。本质上,您让 Dispatcher Servlet 仅初始化与 Web 相关的内容。您让监听器初始化非网络内容。

http://simone-folino.blogspot.co.uk/2012/05/dispatcherservlet-vs.html

您的代码和配置可以改进很多东西。让我们从你的 dao 开始,不要将 Session 存储在实例变量中,我强烈建议对所需的依赖项使用构造函数注入。考虑到这一点,您的 dao(s) 应该看起来像这样。

@Transactional
@Repository
public class CanvasDAOImpl implements CanvasDAO{

    private final SessionFactory sessionFactory;

    @Autowired
    public CanvasDAOImpl(SessionFactory sessionFactory) {
        this.sessionFactory=sessionFactory;
    }

   @overrride
   public returnType methodName(params..){
        Session session = this.sessionFactory.getCurrentSession();
        // Do stuff with the session.
    }
}

没有更多的二传手(尤其是 Session!)只是一个普通的 class。这同样适用于 @Service classes.

@Service
@Transactional
public class CanvasServiceImpl implements CanvasService {

    private final CanvasDAO canvasDAO;

    public CanvasServiceImpl(CanvasDAO canvasDAO) {
        this.canvasDAO=canvasDAO;
    }

    //methods
}

在您的配置中,您已经明确定义了所有 @Repository@Service beans。您还有一个 <context:component-scan />,它已经检测到所有 @Component。删除所有显式声明的 @Repository@Service beans。这将真正清理您的配置!

在你的休眠配置中,c3p0connection 属性是无用的,因为你正在注入一个 DataSource 并且休眠不管理它,但 Spring 是。删除那些行。此外,为了进一步清理此配置,而不是指定每个 class 它需要处理添加 packagesToScan 以便它会自动检测 @Entity 注释 bean。

<context:annotation-config /> 已经暗示了 <context:component-scan /> 的使用,所以你可以删除它,因为它基本上是重复的东西。

您已经明确定义了一个 RequestMappingHandlerMapping,它什么都不做,因为 <mvc:annotation-driven /> 已经注册了一个。它只占用内存,MappingJackson2HttpMessageConverter 是自动注册的 Jackson2 在 class 路径上检测到,所以不需要这样做。

机会 Locale 不适用于所有 URL,因为您忘记了使用 <mvc:annotation-driven /> 元素注册拦截器。

将所有建议应用于您的 classes 和配置时,剩余的配置如下所示。

    <context:component-scan base-package="com.journaldev.spring"/>
    <context:property-placeholder location="classpath:application.properties"/>

    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <beans:bean class="org.springframework.mobile.device.DeviceWebArgumentResolver"/>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>
    <mvc:interceptors>
        <beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor"/>
        <beans:ref bean="localeChangeInterceptor" />
    </mvc:interceptors>

    <mvc:default-servlet-handler/>

    <resources mapping="/resources/" location="/resources/"/>

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/"/>
        <beans:property name="suffix" value=".jsp"/>
    </beans:bean>

    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
                destroy-method="close">
        <beans:property name="driverClassName" value="org.postgresql.Driver"/>
        <beans:property name="url"
                        value="jdbc:postgresql://localhost:5432/dbname"/>
        <beans:property name="username" value="dbuser"/>
        <beans:property name="password" value="dbpass"/>
        <beans:property name="removeAbandoned" value="true"/>
        <beans:property name="removeAbandonedTimeout" value="20"/>
        <beans:property name="defaultAutoCommit" value="false"/>
    </beans:bean>

    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource"/>
        <beans:property name="packagesToScan" value="com.journaldev.spring.model" />       
        </beans:property>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
                <beans:prop key="hibernate.show_sql">false</beans:prop>
             <!--   <beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>
                <beans:prop key="hibernate.order_updates">true</beans:prop>-->
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

    <task:annotation-driven/>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>



    <!--  <beans:bean id="bayeux" class="org.cometd.server.BayeuxServerImpl" init-method="start" destroy-method="stop">
          <beans:property name="transports">
              <beans:list>
                  <beans:bean id="jsonTransport" class="org.cometd.server.transport.JSONTransport">
                      <beans:constructor-arg ref="bayeux"/>
                  </beans:bean>
                  <beans:bean id="jsonpTransport" class="org.cometd.server.transport.JSONPTransport">
                      <beans:constructor-arg ref="bayeux"/>
                  </beans:bean>
              </beans:list>
        </beans:property>
      </beans:bean>-->


    <!-- locale -->
    <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename" value="classpath:/locale/messages"/>
        <beans:property name="defaultEncoding" value="UTF-8"/>
    </beans:bean>


    <!-- default locale -->
    <beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <beans:property name="defaultLocale" value="de"/>
    </beans:bean>

    <!-- Change locale via url. -->
    <beans:bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <beans:property name="paramName" value="lang"/>
    </beans:bean>

    <beans:bean id="handlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <beans:property name="interceptors">
            <beans:list>
                <beans:ref bean="localeChangeInterceptor"/>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean class="com.journaldev.spring.service.DoNotTruncateMyUrls"/>

    <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <beans:property name="maxUploadSize" value="52428800"/>
    </beans:bean>
</beans:beans>

但是你真的应该把 ContextLoaderListener 加载的东西分开,基本上除了 @Controller 之外的所有东西和 DispatcherServlet 加载的东西只是 @Controllers和网络相关的bean。

所以 servlet-context.xml 应该看起来像这样。

    <context:component-scan base-package="com.journaldev.spring" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <context:property-placeholder location="classpath:application.properties"/>

    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <beans:bean class="org.springframework.mobile.device.DeviceWebArgumentResolver"/>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>
    <mvc:interceptors>
        <beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor"/>
        <beans:ref bean="localeChangeInterceptor" />
    </mvc:interceptors>

    <mvc:default-servlet-handler/>

    <resources mapping="/resources/" location="/resources/"/>

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/"/>
        <beans:property name="suffix" value=".jsp"/>
    </beans:bean>

    <!-- locale -->
    <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename" value="classpath:/locale/messages"/>
        <beans:property name="defaultEncoding" value="UTF-8"/>
    </beans:bean>


    <!-- default locale -->
    <beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <beans:property name="defaultLocale" value="de"/>
    </beans:bean>

    <!-- Change locale via url. -->
    <beans:bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <beans:property name="paramName" value="lang"/>
    </beans:bean>

    <beans:bean id="handlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <beans:property name="interceptors">
            <beans:list>
                <beans:ref bean="localeChangeInterceptor"/>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean class="com.journaldev.spring.service.DoNotTruncateMyUrls"/>

    <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <beans:property name="maxUploadSize" value="52428800"/>
    </beans:bean>

然后将删除的内容和 <context:component-scan />(或修改它)添加到 root-context.xml

<context:component-scan base-package="com.journaldev.spring">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

<context:property-placeholder location="classpath:application.properties"/>

<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
    <beans:property name="driverClassName" value="org.postgresql.Driver"/>
    <beans:property name="url"
                    value="jdbc:postgresql://localhost:5432/dbname"/>
    <beans:property name="username" value="dbuser"/>
    <beans:property name="password" value="dbpass"/>
    <beans:property name="removeAbandoned" value="true"/>
    <beans:property name="removeAbandonedTimeout" value="20"/>
    <beans:property name="defaultAutoCommit" value="false"/>
</beans:bean>

<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource"/>
    <beans:property name="packagesToScan" value="com.journaldev.spring.model" />       
    </beans:property>
    <beans:property name="hibernateProperties">
        <beans:props>
            <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
            <beans:prop key="hibernate.show_sql">false</beans:prop>
         <!--   <beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>
            <beans:prop key="hibernate.order_updates">true</beans:prop>-->
            <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
        </beans:props>
    </beans:property>
</beans:bean>

<task:annotation-driven/>

<tx:annotation-driven transaction-manager="transactionManager"/>

<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</beans:bean>

<!--  <beans:bean id="bayeux" class="org.cometd.server.BayeuxServerImpl" init-method="start" destroy-method="stop">
      <beans:property name="transports">
          <beans:list>
              <beans:bean id="jsonTransport" class="org.cometd.server.transport.JSONTransport">
                  <beans:constructor-arg ref="bayeux"/>
              </beans:bean>
              <beans:bean id="jsonpTransport" class="org.cometd.server.transport.JSONPTransport">
                  <beans:constructor-arg ref="bayeux"/>
              </beans:bean>
          </beans:list>
    </beans:property>
  </beans:bean>-->

从您的 security-context.xml 中删除 <import resource="servlet-context.xml" />

最后让 DispatcherServlet 加载 servlet-context.xml 而不是 security-context.xml

现在,因为您不再为每个上下文加载两次 bean,所以您应该减少内存占用,并且您不应该再有 4 个计划作业。此外,理想情况下,您的 Email class 也应该是一个 Spring 托管 bean,我建议使用 JavaMailSender API 来简化电子邮件发送。

所以基本上你前面的任务主要是删除东西,你最终会用更少的代码和更少的配置完成同样的事情。

要获得更多实际操作建议,我正在招聘 ;)...