• 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"}]}}
    1
    接着,我们输入下面的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业务请求方式,那么就可以考虑使用*这种筛选方式。
    ————————————————

    静态资源无法访问的解决方法:

    方法一:使用 Tomcat 默认的 Servlet,配置 servlet-mapping
    使用 Tomcat 默认的 Servlet,在电脑的 Tomcat 安装目录下,tomcat/conf/web.xml 的 web.xml 文件中,有默认配置如下:

    <servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    <init-param>
    <param-name>debug</param-name>
    <param-value>0</param-value>
    </init-param>
    <init-param>
    <param-name>listings</param-name>
    <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>
    然后在项目的 web.xml 文件中,配置 servlet-mapping,使用此默认 Servlet:

    <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
    </servlet-mapping>

    然后就可以顺利加载 .html 后缀的静态资源了。其它如 .css、.js、.jpg 后缀的静态资源文件也可类似的设置。

    方法二:使用 mvc:default-servlet-handler/
    保证 springmvc.xml 中有 spring-mvc 的约束:
    xmlns:mvc="http://www.springframework.org/schema/mvc"

    xsi:schemaLocation="http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    在 springmvc.xml 中添加 <mvc:default-servlet-handler/> 标签即可;然后便可以访问所有静态资源了。

    执行原理分析:

    mvc:default-servlet-handler 会将对静态资源的访问请求通过 HandlerMapping 映射到默认 Servlet 请求处理器 DefaultServletHttpRequestHandler 对象。而该处理器调用了 Tomcat 的 DefaultServlet 来处理静态资源的访问请求。(方法一)

    方法三:使用 mvc:resources/
    参考方法二;

    然后将 <mvc:default-servlet-handler>标签改为 <mvc:resources location="/resouces-directory-name/" mapping="/resouces-directory-name/**"/>标签。其中 location 表示静态资源所在目录,mapping 表示对该资源的请求(注意后面有两个星号**)。

    该配置会该配置会把对该静态资源的访问请求经 HandlerMapping 直接映射到静态资源处理器对象 ResourceHttpRequestHandler。
    ————————————————
    版权声明:本文为CSDN博主「「已注销」」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Dawsson/java/article/details/86900054

    感谢大神整理,此处转发收藏
    版权声明:本文为CSDN博主「云里飞鸟轻轻摇摆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/yzh18373476791/java/article/details/82719848

  • 相关阅读:
    Activity的生命周期和启动模式
    网络基础1
    Jersey用户指南学习笔记1
    IntelliJ IDEA + Maven + Jetty + Jersey搭建RESTful服务
    Java并发编程实战笔记—— 并发编程4
    Java并发编程实战笔记—— 并发编程3
    Java并发编程实战笔记—— 并发编程2
    7.2.4
    7.2.4
    7.2.3
  • 原文地址:https://www.cnblogs.com/AbnerRao/p/12874214.html
Copyright © 2020-2023  润新知