小心 Spring MVC 使用陷阱

Spring MVC, 你使用了多久呢? 在使用中有没有遇到一些让你困惑的问题呢? 

以下是我总结的在使用Spring MVC时需要注意的陷阱

(我使用她3年多了,但有时还是会犯错)


1. 固定特殊bean的id

Spring MVC上传文件时, 我们都需要配置一个MultipartResolver的实现, 常用的是Apache提供的CommonsMultipartResolver类, 配置如下:

  1. <!-- fileUpload Support -->  
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
  3.     <property name="defaultEncoding" value="UTF-8"/>  
  4.     <!--max size: 10M-->  
  5.     <property name="maxUploadSize" value="10485760"/>  
  6. </bean>  
    <!-- fileUpload Support -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <!--max size: 10M-->
        <property name="maxUploadSize" value="10485760"/>
    </bean>

简单吧, 但你是否想过这儿配置的id (multipartResolver) 没呢? 试试将id修改为其他的,如 myMultipartResolver, 这还会让上传文件正常工作吗? 本来id仅作为一个唯一的标识即可.但在这儿只能说 NO, 你必须保证id必须是multipartResolver,  其他的还有localeResolver, themeResolver等等. 

(有时候因为这点小问题导致抓狂), 为什么要固定bean的id啊? 此是陷阱一. 

原因是在Spring MVC的核心类DispatcherServlet中, 把这些bean的id固定了. 你必须保证bean的id相同, 才能正常工作. 对应的代码如下:

  1. public class DispatcherServlet extends FrameworkServlet {  
  2.   
  3.     /** Well-known name for the MultipartResolver object in the bean factory for this namespace. */  
  4.     public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";  
  5.   
  6.     /** Well-known name for the LocaleResolver object in the bean factory for this namespace. */  
  7.     public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";  
  8.   
  9.     /** Well-known name for the ThemeResolver object in the bean factory for this namespace. */  
  10.     public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";  
  11.   
  12.     /**  
  13.      * Well-known name for the HandlerMapping object in the bean factory for this namespace.  
  14.      * Only used when "detectAllHandlerMappings" is turned off.  
  15.      * @see #setDetectAllHandlerMappings  
  16.      */  
  17.     public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";  
public class DispatcherServlet extends FrameworkServlet {

	/** Well-known name for the MultipartResolver object in the bean factory for this namespace. */
	public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";

	/** Well-known name for the LocaleResolver object in the bean factory for this namespace. */
	public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";

	/** Well-known name for the ThemeResolver object in the bean factory for this namespace. */
	public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";

	/**
	 * Well-known name for the HandlerMapping object in the bean factory for this namespace.
	 * Only used when "detectAllHandlerMappings" is turned off.
	 * @see #setDetectAllHandlerMappings
	 */
	public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";

如果以后遇到配置是正常的, 但却不工作, 去DispatcherServlet看看bean的id是不是被 固定了.


2. DispatchServlet配置的路径

这个你肯定会配置吧

  1. <servlet>  
  2.     <servlet-name>wdcy</servlet-name>  
  3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.     <load-on-startup>2</load-on-startup>  
  5. </servlet>  
  6. <servlet-mapping>  
  7.     <servlet-name>wdcy</servlet-name>  
  8.     <url-pattern>/</url-pattern>  
  9. </servlet-mapping>  
    <servlet>
        <servlet-name>wdcy</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>wdcy</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

思考过这儿路径的配置吗? 一般都是"/", 即所有请求都让Spring MVC来处理, 当然也包括静态资源啦, 如js, jpg, css等. 

这种方式好吗? 在使用时要小心, 若使用这种配置, 

建议在Spring MVC 的配置文件中添加类似下面的配置

  1. <mvc:resources mapping="/js/**" location="/js/"/>  
  2. <mvc:resources mapping="/css/**" location="/css/"/>  
  3. <mvc:resources mapping="/images/**" location="/images/"/>  
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/images/**" location="/images/"/>
这告诉Spring MVC 静态资源到对应的目录下去直接访问而不处任何处理.


另一种方式就是使用后缀, 即不配置为"/", 而是配置为类似"*.htm"的方式 也是不错的.


3."两个Spring Context"

当一个项目中既使用 Spring Container, 又使用Spring MVC时, 你觉得项目中只有一个Spring容器还是两个呢?

在这种情况下, 我们都会在web.xml中配置一个container listener

  1. <!-- Spring context listener -->  
  2. <listener>  
  3.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  4. </listener>  
    <!-- Spring context listener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

与Spring MVC的DispatchServlet,

  1. <servlet>  
  2.     <servlet-name>zsfz</servlet-name>  
  3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.     <load-on-startup>2</load-on-startup>  
  5. </servlet>  
  6. <servlet-mapping>  
  7.     <servlet-name>zsfz</servlet-name>  
  8.     <url-pattern>*.zsfz</url-pattern>  
  9. </servlet-mapping>  
    <servlet>
        <servlet-name>zsfz</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>zsfz</servlet-name>
        <url-pattern>*.zsfz</url-pattern>
    </servlet-mapping>

考考你:  这两个东西在系统启动时如何加载? 执行顺序是如何的呢? 

如果第一个listener对应的容器先执行, 那它知道Spring MVC的容器吗,  但如何反转来呢?  很有意思的问题吧, 

仔细去研究下Spring的源码, 会发现更有趣.


换位思考下, 如果是你来实现这两者之间加载的容器, 你会如何实现呢.



还有更多更多的Spring MVC 使用陷阱, 你发现了吗.......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值