#SpringMVC--理解web.xml中的 url-pattern标签及其使用范围

在web.xml中,我们通过下面的标签来匹配客户端发出的请求:

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

1、匹配顺序
该标签处理客户端请求的顺序为:
(1)完全匹配
<url-pattern>/test/userList.action</url-pattern>
完全匹配就是等值匹配,它是最先被匹配到的客户端请求。

(2)路径匹配
<url-pattern>/*</url-pattern> 匹配根路径下的全部请求
路径匹配类似于模糊匹配,对于/list、listInfo.do、checkInfo.action、index.jsp、abc.css、my.js等等url请求,都可以被匹配到。这种匹配的顺序排在完全匹配后面。
(3)扩展名匹配
<url-pattern>*.action</url-pattern>匹配全部action 结尾的请求
<url-pattern>*.css</url-pattern> 匹配全部 css结尾的请求
<url-pattern>*</url-pattern> 不能用 * ,否则报错
说明:这种匹配匹配在开发中用的比较多,但不能使用*代替,否则会报错。
结论:容器会首先查找完全匹配,如果找不到,再查找目录匹配,如果也找不到,就查找扩展名匹配。

2、“/” 与 “/*” 的区别
(1)<url-pattern>/</url-pattern>
会匹配到 /toIndex 这种类型的 url ,不会匹配到模式为 *.jsp 这样的后缀型 url。
(2)<url-pattern>/*</url-pattern>
会匹配所有路径型的和后缀型的url。

3、选用/还是.action作为请求路径匹配?
我个人认为,我们选用.action作为请求路径会比较好。为什么呢?我们先使用/来处理下面的问题,假设有两个controller层的方法,如下所示。

@ResponseBody
@RequestMapping(value = "/listUserInfos",method=RequestMethod.GET)
public DataMessage listUserInfos(Pagination<UserInfo> pageParams) throws Exception {
    userInfoService.queryPage(pageParams);
    return DataMessage.successData(pageParams);
}
@GetMapping(value = "/toIndex")
public String toIndex(){
    return "/index";
}

说明:这两个方法之间的关系是通过toIndex()来方法listUserInfos()这个方法,其中toIndex()来方法返回一个视图。启动程序,我们在浏览器中输入下面的请求路径:

http://localhost:8080/hBSpringMvcTestProSwagger/list/listUserInfos.action

我们发现。可以在浏览器上方显示出下面的信息:

{"type":"success","content":"操作成功","data":{"pageNo":1,"pageSize":15,"totalPage":1,"params":{},"total":3,"rows":[{"userName":"yzh","password":"123","age":23,"sex":"男","tel":"12345678","email":"123@qq.com"},{"userName":"lhy","password":"1257","age":20,"sex":"女","tel":"12345678","email":"1256@qq.com"},{"userName":"tom","password":"12312","age":21,"sex":"男","tel":"12345678","email":"1231@qq.com"}]}}

接着,我们输入下面的url请求路径:
http://localhost:8080/hBSpringMvcTestProSwagger/list/toIndex.action
这里写图片描述
这是什么原因呢?前面不是说/*可以任何请求吗?当匹配到客户端发出一个toIndex.action请求,会被*匹配到,因此会访问到toIndex这个controller方法,此时会一个视图,而返回jsp视图时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。那么可以采取什么办法解决这个问题呢?实际上,我们可以这样来解决这个问题:

  <servlet-mapping>
     <servlet-name>yzh_ssh</servlet-name>
     <url-pattern>/base/*</url-pattern>
  </servlet-mapping>

这个时候,请求路径就会匹配url中带base的请求,这样一来,我们将所有访问controller的请求都设置一个base基础目录,就像下面这样:

http://localhost:8080/hBSpringMvcTestProSwagger/base/test/toIndex.action

而对于返回的视图是index.jsp,因为该目录中并没有设置base基础目录,因此将无法匹配到controller方法,这时,如果发现是没有经过映射处理的请求,将该请求交由 WEB 应用服务器默认的Servlet处理。 如果不是静态资源的请求, 才由 DispatcherServlet 继续处理 一般 WEB 应用服务器默认的 Servlet 的名称都是 default。 若所使用的WEB 服务器默认的Servlet 名称不是default, 则需要通过default-servlet-name 属性显式指定,可以使用<mvc:default-servlet-handler/>并结合<mvc:annotation-driven></mvc:annotation-driven>处理这个静态资源的问题。使用这种方法的优点是能够支持第三方插件的类似/*的请求,例如Swagger中的http://localhost:8998/swagger-resources/configuration/ui这种请求,如果配置*.action是无法筛选到controller层的。

(2)*.action方式
*.action会筛选出后缀为action的请求,因此在返回的视图是index.jsp时,无法匹配到controller方法,这时,如果发现是没有经过映射处理的请求,将该请求交由 WEB 应用服务器默认的Servlet处理,从而展示出效果。但是这种方式也有一个缺点,并不支持Swagger中的http://localhost:8998/swagger-resources/configuration/ui这种请求(不是静态资源),如果配置*.action是无法筛选到controller层的,从而显示404的错误。但是我们也有办法解决这个问题,实际上,我们可以定义多个前端控制器来分发处理这些不同格式的请求,例如:

<!-- 配置DispatcherServlet -->
  <servlet>
    <servlet-name>yzh_ssh1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置springMVC的配置文件 -->
    <!-- 如果不配置下面选项,系统默认加载classpath下面名为[servlet-name]-servlet.xml的文件 springmvc01-servlet.xml -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <!-- 过滤controller层请求,只能通过*.action请求 -->
  <servlet-mapping>
     <servlet-name>yzh_ssh1</servlet-name>
     <url-pattern>*.action</url-pattern>
  </servlet-mapping>

   <servlet>
    <servlet-name>yzh_ssh2</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置springMVC的配置文件 -->
    <!-- 如果不配置下面选项,系统默认加载classpath下面名为[servlet-name]-servlet.xml的文件 springmvc01-servlet.xml -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
     <servlet-name>yzh_ssh2</servlet-name>
     <url-pattern>/base/*</url-pattern>
  </servlet-mapping>

说明:我们看到,在上面我们定义了两个前端控制器分别处理不同格式的请求,前端控制器yzh_ssh1用于处理后缀为action的请求,而前端控制器yzh_ssh2用于处理包含/base/*的请求,符合该请求的,会将*号后面的url与controller的映射url相匹配。

结论:如果只涉及到controller业务请求的,建议使用*.action的请求筛选方式,如果是既有\xxx这种第三方插件请求方式,又有controller业务请求方式,那么就可以考虑使用\*这种筛选方式。

  • 13
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值