在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