request.getServletPath()返回为空的问题

分类: WEB开发 0人评论 selfly 1年前发布

昨天配置了一下Dexcoder的404,500等错误页面,但是配置好项目发到服务器之后,不经意间发现session拦截器居然失效了,连后台都可以不用登录就进去了,这绝对是致命bug啊,赶紧排查。

一般我们实现的session拦截器,都是通过ServletPath来判断访问的路径是否需要session,典型的代码如下:

String servletPath = request.getServletPath();
if (StringUtils.startsWith(servletPath, "/admin")) {
    //...
}

但是这些代码我并没有做过任何改动,那到底是什么原因导致了这个问题呢?

最后发现,居然是web.xml是的servlet-mapping配置引起的,不同的url-pattern配置会使request.getServletPath()的返回值不同。

一开始我的spring mvc配置如下:

<servlet-mapping>
     <servlet-name>springmvc</servlet-name>
     <url-pattern>*.shtml</url-pattern>
 </servlet-mapping>

使用了*.shtml,用如下测试代码:

System.out.println("ServletPath:" + request.getServletPath());
System.out.println("ContextPath:" + request.getContextPath());
System.out.println("RequestURI:" + request.getRequestURI());
System.out.println("PathInfo:" + request.getPathInfo());
System.out.println("RequestURL:" + request.getRequestURL());

在浏览器中访问http://localhost:8080/dexcoder/blog/article/1479.shtml,发布到服务器上时因为直接绑定域名,一般都是没有项目名的,这里为了看的清晰,设置了项目名为dexcoder

输出如下:

ServletPath:/blog/article/1479.shtml

ContextPath:/dexcoder

RequestURI:/dexcoder/blog/article/1479.shtml

PathInfo:null

RequestURL:http://localhost:8080/dexcoder/blog/article/1479.shtml

无疑/blog/article/1479.shtml是我们所需要的,没有问题。

ps:当没有项目名时,ServletPathRequestURI会一样。

因为有时候不光要用到页面访问的后缀,还会用到譬如.json.xml等,因此我们把spring mvc的servlet-mapping改成:

<servlet-mapping>
     <servlet-name>springmvc</servlet-name>
     <url-pattern>/*</url-pattern>
 </servlet-mapping>

还是上面的测试代码,输出如下:

ServletPath:

ContextPath:/dexcoder

RequestURI:/dexcoder/blog/article/1479.shtml

PathInfo:/blog/article/1479.shtml

RequestURL:http://localhost:8080/dexcoder/blog/article/1479.shtml

ServletPath为空了,相反PathInfo却有值了,这就是导致我们上面问题的根本原因,看来对servlet还是不够了解啊,做一笔糊涂账了。

怎么样来保证每次获取的都是我们想要的,不会随着web.xml是的配置变化受到影响呢?

有了上面的实例,实现起来也很简单,可以使用如下代码:

String servletPath = request.getServletPath();
String pathInfo = request.getPathInfo();
if (StringUtils.length(pathInfo) > 0) {
    servletPath = servletPath + pathInfo;
}

或者下面的代码,效果都是一样的:

String uri = request.getRequestURI();
String contextPath = request.getContextPath();
if (StringUtils.length(contextPath) > 0) {
    uri = StringUtils.substring(uri, contextPath.length());
}