Spring 3.0配置多个DispatcherServlet的方法及注意事项


项目中需要同时用到两个视图解析器,一个报表的,一个jsp的。这就产生了标题所述的需求。通过阅读Spring Framework参考手册以及示例,解决了这个问题,中间也走了不少弯路,碰到了不少问题,特记录下来。

配置多个DispatcherServlet有多种方法,一种是在DispatcherServlet中直接指定此DispatcherServlet对应的配置文件。例如:

<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>

但是这种配置方法存在一个问题:由于DispatcherServlet对应的Controller需要访问Service并且使用dataSource,而DispatcherServlet之间的上下文是分离的,势必会出现多个dataSource的情况,降低了数据库连接使用的效率。

后来找到了第二种方法,目前正在使用的:DispatcherServlet不指定具体的配置文件,并且DispatcherServlet只初始化自己需要使用到的Controller类,然后由org.springframework.web.context.ContextLoaderListener初始化除Controller以外的全部对象。这样子多个dataSource的问题解决了。配置如下:

web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/*-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>

由于没有指定名称,所以spring默认会在WEB-INF目录下寻找DispatcherServlet名称开头的-servlet.xml文件,上面这个配置寻找的app-servlet.xml文件。

app-servlet.xml:
<!– 扫描所有的业务Controller,加载json转换服务对象,排除所有的报表Controller –>
<context:component-scan base-package=”com.xieshaohu.**.action” >
<context:include-filter type=”regex” expression=”.*JacksonConversionServiceConfigurer$”/>                 <context:exclude-filter type=”aspectj” expression=”com.xiehshaohu.project.reports.action.**.*”/> </context:component-scan>

<!– 通过 @Controller 注解实例化Controller类 –>
<mvc:annotation-driven />
<!– JSP视图控制器 –>
<bean id=”jspViewResolver”>
<property name=”viewClass” value=”org.springframework.web.servlet.view.JstlView”/>
<property name=”prefix” value=”/WEB-INF/views/” />
<property name=”suffix” value=”.jsp” />
</bean>

另外还有一个report-servlet.xml配置,web.xml中的内容和app的配置类似。

report-servlet.xml:
<!– 扫描所有的报表Controller对象 –>
<context:component-scan base-package=”com.xieshaohu.project.reports.action” />
<!– Configures the @Controller programming model –>
<mvc:annotation-driven />
<bean id=”viewResolver” class=”org.springframework.web.servlet.view.ResourceBundleViewResolver”>   <property name=”basename” value=”views” />
</bean>

然后就是在org.springframework.web.context.ContextLoaderListener初始化的-config.xml配置文件中实例化Service和Dao了。

<!– 扫描Classpath下所有的@Compnents对象,排除Controller和json转换服务对象 –>
<context:component-scan base-package=”com.xieshaohu”>
<context:exclude-filter type=”regex” expression=”.*Controller$”/>
<context:exclude-filter type=”regex” expression=”.*JacksonConversionServiceConfigurer$”/> </context:component-scan>

通过以上配置,现在就可以实现多个DispatcherServlet了,并且共享了同一个dataSource。在配置的过程中碰到了以下问题。

  1. @Transactional不生效,导致连接泄露。
    按照约定,所有的@Transactional注解都是在@Service中,出现这个问题的原因是,我在app-servlet.xml中初始化了所有的对象,包括@Controller,@Service,@Repository。但是按照官方手册314页正上方的说明,DispatherServlet扫描的对象中使用了@Transactional注解,则只会扫描@Controller中的@Transctional注解。所以出现了连接泄露的问题。所以最后配置成了只在*-servlet.xml中初始化@Controller。
    英文原文:
    <tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services.
  2. DispatcherServlet间互相访问的问题。
    这个问题直接参考Application Context – three ways to get the context的第一种方法解决。实现ApplicationContextAware接口即可。
  3. Service没有使用接口编程,导致@Controller初始化时提示找不到对应的Service实例。
    上面这个问题通过修改程序解决,看来面向接口编程很重要,下面这点更加充分的说明了问题。
  4. Service实例化时提示无法访问通过@Repository注解声明的Dao
    出现这个问题的原因还是因为没有在Service中使用接口引用Dao,导致程序在初始化时就要寻找实例。
Advertisements

Spring 3.0配置多个DispatcherServlet的方法及注意事项》上有2条评论

  1. Pingback引用通告: Hongtium » Spring 3.0配置的两个相关文章

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s