Servlet url-pattern 如何配置

一、url-pattern的匹配规则

1、精确路径匹配

例如:
Servlet01 的 url-pattern 配置的是 /*
Servlet02 的 url-pattern 配置的是 /hello
这个时候如果浏览器访问 http://localhost:8080/hello 时,虽然这两个路径都是可以匹配的
但是容器会先优先进行精确路径匹配,发现 /hello 正好被 Servlet02 精确匹配,那么就去调用 Servlet02 ,就不会去理会其他的 Servlet 了.

2、目录匹配(最长路径优先匹配原则,其实也可以认为是谁的路径相似度更高就匹配谁)

例如:
Servlet01 的 url-pattern 配置的是 /aaa/*
Servlet02 的 url-pattern 配置的是 /aaa/bbb/*
这个时候如果浏览器访问 http://localhost:8080/aaa/bbb/hello 时,虽然这两个路径都是可以匹配的
但是容器会进行最长路径匹配,即 Servlet02 的路径更长,描述的更具体,所以会优先匹配上 Servlet02 ,就不会再去匹配 Servlet01 了

3、扩展名匹配

例如:
某个 Servlet 的 url-pattern 配置的是 *.do ,如果我访问 http://localhost:8080/xxx.do 时,这个时候就会根据扩展名进行匹配

  

二、url-pattern 的匹配顺序

1、首先进行精确路径匹配,匹配上了调用相应的 Servlet

2、如果精确路径匹配不上,接着进行目录匹配,如果匹配上了多个,选择路径最长的 Servlet

3、如果目录匹配不上,接着进行扩展名匹配,如果还匹配不上则调用 tomcat 容器中默认的 Servlet

 

下面我们就结合 SpringMVC 中 DispatcherServlet 的配置案例来说

三、两个web.xml

web 应用需要放在 Tomcat 容器中才能启动,Tomcat 容器内有一个默认的 web.xml 文件(放置在 tomcat 安装目录 /conf/ 下),在自己项目中配置的 web.xml 配置文件都是继承自 Tomcat 中的全局 web.xml 文件并重写其中相应配置,这种继承且重写的关系和子类继承父类并重写相关方法一样,如果子类重写了父类的方法,那么就使用子类的方法,反之就使用父类的方法.像 XML 这种格式化的文件最终会被转换成一个类去保存配置信息,所以理解 Tomcat 中全局 web.xml 文件和项目中 web.xml 文件的关系也可以类比子类重写父类方法的模式.

1、全局 web.xml( tomcat 中的 web.xml)

<!--处理静态资源的Servlet-->
<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>

<!-- The mapping for the default servlet -->
<servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>/</url-pattern>
</servlet-mapping>

<!--处理jsp的Servlet-->
<servlet>
      <servlet-name>jsp</servlet-name>
      <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
      <init-param>
          <param-name>fork</param-name>
          <param-value>false</param-value>
      </init-param>
      <init-param>
          <param-name>xpoweredBy</param-name>
          <param-value>false</param-value>
      </init-param>
      <load-on-startup>3</load-on-startup>
 </servlet>

<!-- The mappings for the JSP servlet -->
 <servlet-mapping>
      <servlet-name>jsp</servlet-name>
      <url-pattern>*.jsp</url-pattern>
      <url-pattern>*.jspx</url-pattern>
 </servlet-mapping>

2、项目中 web.xml

<servlet>
	<servlet-name>SpringMVC</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:SpringMVC.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>SpringMVC</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping> 

根据就近原则,一个请求发送过来,找 web 应用服务器(tomcat)要资源时,首先会尝试和项目中的 web.xml 中进行匹配,如果匹配不上就会去全局的 web.xml 中进行匹配,如果某一个 Servlet 的  <url-pattern> 配置为 /,那么我们就称这个 Servlet 为缺省 Servlet ,凡是在 web.xml 文件中找不到有能和请求匹配的 <url-pattern> ,那么它们的访问请求都交给缺省的Servlet来处理(缺省的 Servlet 作用就是处理别的 Servlet 都不处理的请求).

 

四、SpringMVC 中 web.xml 前端处理器( DispatcherServelt )的常见配置 

不同配置的优先级  /*  >  *.xxx  >  / (缺省的 Servlet 排在最后的原因我的理解是:只有所有的 Servlet 都匹配不上时,才会去匹配 / ,所以它的优先级是最低的)

1、前端处理器配置 /* 

项目中 web.xml 的 DispatcherServlet 配置了 /* , 由于 /* 的优先级最高,那么所有的请求都会被 DispatcherServlet 处理,等于废弃了 tomcat 中的 web.xml 中的 DefaultServlet 和 JspServlet 的作用

// /* 的优先级最高,无论什么资源都会被 /* 拦截 
1、访问 http//localhost:8080/index.html 时,任何资源都被前端处理器拦截了,所以 html、css、js 等静态资源也被拦截进了前端处理器,但是在
处理器层(Controller)找不到相应的处理方法处理 index.html 请求,所以会在 Controller 中报错

2、访问 http//localhost:8080/handle01 时,前端处理器拦截了请求,并把请求传递给了控制器层的 handle01 ,但是返回页面 success.jsp 的请求
也被前端处理器拦截了,不能匹配到 JspServlet,匹配不到 JspServlet 就无法对 jsp 文件进行解析,输出,渲染.

2、前端处理器配置 /

项目中 web.xml 的 DispatcherServlet 配置了 / ,代表的是缺省的 Servlet ,其它 Servlet 不处理的请求都会交给缺省的 Servlet 来处理

访问 http://localhost:8080/index.html 时,由于我们项目中 DispatcherServlet 配置的是 / ,而 tomcat 中对静态资源进行处理的 
DefaultServlet 也是配置的 / ,那么根据就近原则,处理静态资源时会使用我们项目中的 DispatcherServlet ,静态资源被拦截进了 
Controller 层,在 Controller 层找不到对应的处理方法,会报错

访问 http://localhost:8080/index.jsp 时,由于我们项目中 DispatcherServlet 配置的是 / ,而 tomcat 中对 jsp 进行处理的 
JspServlet 配置的是 *.jsp 而 *.jsp 的优先级高于 / ,所以 jsp 的处理会交给 tomcat 中的 JspServlet,这个 Servlet 能对 
jsp 资源进行解析,输出,渲染

访问 http://localhost:8080/handle01 时,由于它的路径没有任何 Servlet 能匹配上,那么就交给缺省的 Servlet ,这里有两个缺省
的 Servlet ,分别是 项目中 DispatcherServlet 和 tomcat 中 DefaultServlet ,根据就近原则,会使用项目中 web.xml 中的 
DispatcherServlet ,请求被拦截进了前端处理器,前端处理器将请求传递给了控制层的 handle01 处理器,处理完后返回的 
success.jsp 被 tomcat的 JspServlet 处理,渲染到页面

3、前端处理器配置 *.do 或 *.action

对于 index.html ,页面正常访问,因为 index.html 没有拦截进前端处理器中,并且 tomcat 中全局 web.xml 中的 DefaultServlet 没有被覆盖,
可以正常的渲染.
对于 index.jsp ,页面正常访问,因为 index.jsp 没有拦截进前端处理器中,并且 tomcat 中的全局 web.xml 中的 JspServlet 没有被覆盖,
可以正常的渲染.

  

  

 

  

 

  

原文地址:https://www.cnblogs.com/xiaomaomao/p/11869540.html