文档章节

SpringMVC,3种不同的URL路由配置方法(这根本不是一个小问题)

FansUnion
 FansUnion
发布于 2015/05/03 01:30
字数 1191
阅读 30
收藏 0
SpringMVC中配置URL拦截,非常简单。网上找个示例,就能通过。但是,在我做了好几个Web项目,又参与了别人主导的Web项目时,发现URL配置也非常有学问。

1. 先说说一种比较常见的:

   
<servlet>
    <servlet-name>theDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-mvc-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>theDispatcher</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>
   让SpringMVC指拦截 动态请求,js、css、img等静态资源不经过Spring,直接让Web容器处理。

   如果配置了拦截器,也只会拦截.html动态请求。

   静态资源不走Spring,也不走拦截器,性能当然是比较好的。

   如果使用了Nginx,配置静态资源拦截,让Nginx处理静态资源的访问。因为Nginx在处理静态资源方面,比Tomcat等Web容器要强。

   缺点:这种拦截动态请求的方法,比较死板。

2.  我自己经常有一种需求,http://FansUnion.cn/news 这种不指定.html后缀的其实也是 动态请求,所以我在配置url-pattern喜欢用“/”,即拦截所有的请求。URL是可以灵活配置了,问题又来了,静态资源不再由Tomcat处理,所以必须在SpringMVC中再次配置,
<mvc:resources mapping="/static/**" location="/static/" />
  让SpringMVC把static静态资源也处理了。显然,让SpringMVC处理静态资源的性能没有Tomcat直接处理比较高。
理论上,请求中转的次数越多, 性能越差。
  
  本以为万事大吉,虽然静态资源的性能较低,至少程序可以正常运行了,“反正是混过去了”。

   进一步的需求,如果在Spring中配置了登录等拦截器,这个时候也会把 静态资源给拦截进来。
<mvc:resources mapping="/static/**" location="/static/" /> 这种URL映射,也无法逃脱拦截器的魔爪。

  我是怎么发现这个问题的呢?
public class BaseLoginInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
LoginUtil.setCurrentUser(null);
initCurrentUser(request, response);
HandlerMethod handlerMethod = (HandlerMethod) handler;
} 

公司的项目,Boss的登录拦截器配置如上,“
HandlerMethod handlerMethod = (HandlerMethod) handler; ”。但是我在自己的项目中,发现这行代码是有问题的。如果静态资源被拦截到,会报错:
java.lang.ClassCastException: org.springframework.web.servlet.resource.ResourceHttpRequestHandler cannot be cast to org.springframework.web.method.HandlerMethod
通过异常可以发现,  Object handler是 ResourceHttpRequestHandler  ,而不是 HandlerMethod。
因为 
mvc:resources把静态资源请求交给了 ResourceHttpRequestHandler  处理,因此强制转换是有问题的。

公司项目中Boss的配置之所以没有出现问题,是因为他配置的是只拦截“.html” 动态请求,所以强制转换总是成立的。
---------------------------------------------
我们分析了上述两种情况, 发现“根本矛盾”“根本需求”是啥?
1.动态请求的URL应该非常灵活,/news /news.html都应该算作动态请求。
2.SpringMVC的url-pattern可以配置 / , *.html,或者正则表达式,但是我不太喜欢用正则表达式。
3.如果可能,SpringMVC最好不要拦截静态资源,让Tomcat容器直接处理更好。
     <mvc:resources mapping="/static/**" location="/static/" />
   这是为了性能考虑。
4.如果线上服务器配置了Nginx,我可以选择让Nginx拦截静态请求,因为比Tomcat处理性能更高。
   本地是否配置Nginx,都不需要改动任何代码。

-------------------------------------------------
上面说的 第一种方法的缺陷是,url配置不够灵活。
第二种方法的缺陷是,SpringMVC要拦截静态资源,而且登录拦截器 也会拦截 静态资源,不但性能差,程序还得再次修改,判断HandlerMethod的实际类型。

3.终极解决方案: 
  以我习惯用的第2种方法为基础,进一步改进:
  去掉
<mvc:resources mapping="/static/**" location="/static/" />,不做静态资源请求的映射。
  
在web.xml里增加如下配置:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>

上述配置,
激活Tomcat的defaultServlet来处理静态文件。

千万要注意,上述配置,要在 SpringMVC的拦截器DispatchServlet之前。 
   
参考了: http://blog.chinaunix.net/uid-20586655-id-3000946.html 第七部分
网友提问: http://www.iteye.com/problems/66915http://www.iteye.com/problems/69983

这样 SpringMVC不再响应静态资源,登录拦截器也没有问题了。

------------------------------------------------------------------------
详细讨论了上诉3种情况,我的结论是:URL配置根本不是一个简单的问题。

搞IT这门高科技技术的Coder,真心需要研究啊。今天搞点小功能,遇到各种问题,探究了好久,才理清了脉络,单单是解决问题,而不能找到根本原因,在遇到下一个问题的时候,会再次束手无策。  

原文首发:
http://fansunion.cn/article/detail/61.html  

© 著作权归作者所有

FansUnion
粉丝 60
博文 858
码字总数 825464
作品 0
丰台
高级程序员
私信 提问
Spring Cloud Zuul 过滤器

---title: Spring Cloud Zuul 过滤器id: spring-cloud-zuul-filtersdate: 2019-05-16 10:51:43categories: Spring Cloud tags: Spring Cloud Zuul 服务网关 微服务 description: Spring Clou......

TurboSanil
05/17
0
0
springCloud笔记系列(4)-网关配置Zuul

1.SpringCloudZuul是基于Netflix Zuul实现的API网关组件,它实现了请求路由、负载均衡、校验过滤、与服务治理框架的结合、请求转发是的熔断机制和服务的聚合等功能 2.引入依赖 <dependencie...

快乐的小火柴
2018/11/15
0
0
springboot快速开发(二)

springboot的快速上手 1. 建立目录 controller service domain Application.java 启动类 2. 支持web org.springframework.boot spring-boot-starter-web 3. 编写第一个controller @RestContr......

u011402896
2018/04/16
0
0
阿里Sentinel支持Spring Cloud Gateway啦

1. 前言 4月25号,Sentinel 1.6.0 正式发布,带来 Spring Cloud Gateway 支持、控制台登录功能、改进的热点限流和注解 fallback 等多项新特性,该出手时就出手,紧跟时代潮流,昨天刚发布,今...

尹吉欢
04/26
0
0
springcloud(十):服务网关zuul初级篇

为什么需要API Gateway 1、简化客户端调用复杂度 在微服务架构模式下后端服务的实例数一般是动态的,对于客户端而言很难发现动态改变的服务实例的访问地址信息。因此在基于微服务的项目中为了...

itcloud
2018/11/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Hystrix 资料简单梳理

Hystrix 资料简单梳理 状态 Hystrix不再处于活动开发阶段,目前处于维护模式。 Hystrix(版本1.5.18)足够稳定,可以满足Netflix对现有应用程序的需求。与此同时,我们的重点已转向更具适应性...

晨猫
11分钟前
1
0
黑群晖部署

mark 下有空在玩 U盘安装 将U盘id写入到启动配置文件中(syslinux.cfg) https://www.douban.com/note/518491129/ https://www.nas2x.com/threads/dsm-6-2-1-20190221.29/...

以谁为师
15分钟前
1
0
页面性能优化办法有哪些?

摘要: 性能是最重要的用户体验之一。 作者:浪里行舟 Fundebug经授权转载,版权归原作者所有。 引子 互联网有一项著名的8秒原则。用户在访问Web网页时,如果时间超过8秒就会感到不耐烦,如果...

Fundebug
16分钟前
0
0
arcgis api for js加载天地图

天地图有经纬度和墨卡托两种坐标系的切片 arcgis默认为墨卡托坐标系,可以切换二维/三维,加载经纬度切片时view需要设置wkid:4326

单线程生物
17分钟前
1
0
常用正则(含小程序验证)

小程序常用正则 使用样例 let roomNumber = that.data.roomNumber; if (roomNumber.length == 0) { wx.showToast({ title: '房间号不能为空', icon:......

whatwhowhy
18分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部