Servlet虚拟路径映射配置详解

 更新时间:2020年02月24日 10:31:54   作者:李子树_  
这篇文章主要介绍了Servlet虚拟路径映射配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

​在上一篇中我们初识了Servlet,相信大家对Servlet也都有了些了解,知道了如何创建一个Servlet,并且为其添加虚拟映射,最终发布项目,并在浏览器上请求对应的Servlet。

​我们知道,只有给Servlet配置好虚拟路径,客户端才可以进行访问,但是对于Servlet的路径映射,真的只有现在所知的这么简单么?

​答案当时是No了,不然怎么会有这篇文章😝,下面让我们一起来探究其中的秘密吧!

Servlet虚拟路径映射

在web.xml文件中,一个<servlet-mapping>元素用于映射一个Servlet的对外访问路径,该路径也称为虚拟路径。例如<url-pattern>/TestServlet</url-pattern>,其中“/TestServlet”就是一个虚拟路径。

1.配置多个映射路径

​在上一文中,我们说到@WebServlet中的urlPatterns属性,其可以是一组匹配规则,也就是说一个Servlet是可以配置多个虚拟路径的,也就是Servlet和虚拟路径可以是一对多的一个关系(并不是多对多,一个虚拟路径只能映射一个Servlet),其具体实现如下,并修改doPost处的代码:

@WebServlet(
		description = "My First Servlet", 
		urlPatterns = { "/HelloServlet", "/StillMe" }, 
		initParams = { 
				@WebInitParam(name = "name", value = "lizishu")
		})
public class HelloServlet extends HttpServlet {
 //具体逻辑参看上篇文章
 //...
 
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//设置返回客户端的contentType
		//text/plain :纯文本格式 设置为text/html println的换行会失效
		response.setContentType("text/plain;charset=utf-8");
		//response.setCharacterEncoding("utf-8"); 
		PrintWriter out = response.getWriter();
		out.println("Served at: " + request.getContextPath());
		String name = this.getInitParameter("name");
		out.println("name: " + name);
		out.println("访问的Servle名为:" + HelloServlet.class);
	}
}

​可以看到,增加一个虚拟路径映射非常方便,只需在urlPatterns中新增一项即可(注意'/'不可省略),启动项目,在浏览器上输入url,可以看到,无论是输入http://localhost:8080/FirstProject/HelloServlet、还是http://localhost:8080/FirstProject/StillMe页面上得到的输出内容均一致。

​urlPatterns在Servlet 3.0版本之前,都是配置在web.xml中的,每个Servlet会有一个对应的<servlet-mapping>标签,其中可以配置多个<url-pattern>

2.urlPatterns匹配规则

​说到Servlet虚拟路劲的匹配规则,还需要说到urlPatterns的几种匹配规则,主要有以下四种:

  • 精确匹配:也就是我们在上面配置的匹配规则,需要完全相等才能匹配成功,这也是我们经常发生错误的地方,请求Servlet时的大小写拼写错误导致404;
  • 路径匹配:比如想匹配以rest开头的所有请求,可以写成"/rest/*",其格式为以'/‘字符开头,并以'/*'结尾;
  • 扩展名匹配:比如想匹配所有以.do结尾的请求,可以写成"*.do",其格式为以'*.',后面跟上扩展名;
  • 缺省匹配:映射路径为"/",那么这个Servlet就是当前应用的缺省Servlet,默认处理无法匹配到虚拟路径的请求。

​需要注意的是,路径匹配和扩展匹配无法混合使用,即urlPattern无法写成"/rest/*.do";这也是让部分同学感到困惑的地方,Servlet的虚拟路径匹配并不是完全的按照正则来匹配的,虽然路径匹配和扩展匹配是按照正则中的通配符(*)来匹配的,这也是部分同学可以会写出特定的正则,但是却不是一个合法的虚拟路径;Servlet容器收到请求后,会将请求从上下文路径(通过request.getContextPath()获取的)处截断,使用剩余的部分来进行路径匹配,比如请求url为http://localhost:8080/FirstProject/HelloServlet,那么Servlet容器就会使用"/HelloServlet"来匹配Servlet。

​最后需要注意的是,我们说了上面四种匹配规则,尤其是缺省匹配,可以匹配到任意请求,那么一个请求如果可以匹配多个Servlet的虚拟路径,那么该执行哪个Servlet?其实啊,这些匹配规则是有优先级的,具体的优先级为:精确匹配>路径匹配>扩展名匹配>缺省匹配,Servlet容器会从优先级高的虚拟路径开始匹配,匹配到后就会立刻将请求交给对应的Servlet来处理,不会再关心其他Servlet的虚拟路径是否会匹配成功。

​下面我们来一组Servlet及其对应的虚拟路径:

urlPatterns Servlet Name
/abc/* Servlet1
/ Servlet2
/abc Servlet3
*.do Servlet4

​当请求去除上下文路径后路径为:"/abc/a.html"时,根据上述规则,会调用Servlet1;

​请求为:"/abc",根据匹配优先级,会调用Servlet3;

​请求为:"/abc/a.do",会匹配到'/abc/*'、'*.do',但根据匹配优先级,会调用Servlet1;

​请求为:"/a.do",会匹配到'/'、'*.do',但根据匹配优先级,会调用Servlet4;

3.Tomcat提供的缺省Servlet

​为了测试缺省Servlet,我们来进行一个测试。我们新建个SelfDefaultServlet,其urlPatterns我们配置为"/",其中的方法我们不做任何修改。

@WebServlet(
		description = "Self create default Servlet", 
		urlPatterns = { "/" }
		)
public class SelfDefaultServlet extends HttpServlet {
 //...
}

我们启动项目后,在浏览器上输入http://localhost:8080/FirstProject/hahaha或者其他任意无法匹配到HelloServlet虚拟路径的请求,发现页面上的结果都如下所示,是不是这样也不错,不会报404错误了。

​但是,此时我们想访问WebContent目录下的静态页面(新建的一个welcome.html文件),浏览器上输入http://localhost:8080/FirstProject/welcome.html,猜猜会发生什么?我们来一起看下结果,如图所示,请求结果并没有按照我们的想法,根据请求路径找到welcome.htm页面,而是调用了SelfDefaultServlet,是不是很懵?

​其实,客户端的每个请求,都是由Servlet容器根据虚拟路径的匹配规则来进行处理的,包括静态资源。并且,如果路径输入错误(去除了自己配置的缺省Servlet后),我们常见的下面的错误,也是Servlet返回给我们,哈哈,还是很意外?

​我们能通过servlet方便简单的开发网站,是因为我们站在了巨人的肩膀上,下面我们一起来看下Sun公司都为我们开发者提前做了些什么工作。Tomcat会为项目配置一个缺省的Servlet(如果项目中自行配置,则不会生效),配置文件在tomcat安装目录下conf目录中的web.xml文件中,具体内容如下,缺省的Servlet名为DefaultServlet。

<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>
<servlet-mapping>
 <servlet-name>default</servlet-name>
 <url-pattern>/</url-pattern>
</servlet-mapping>

客户端请求静态资源文件时,也是由缺省的Servlet处理的(自己单独配置Servlet除外),如果请求文件能找到,就会将页面通过HttpServletResponse对象以流的方式返回给客户端,否则报404错误。

​不过讲到这里,大家可以自己试一试配置了缺省Servelt时,访问welcome.html的情况(会调用SelfDefaultServlet),但是,如果我们在浏览器中输入http://localhost:8080/FirstProject/index.jsp(index.jsp是创建的第一个jsp页面)呢?会是什么样一个结果?也是调用缺省的Servlet么?真是的运行结果如下:

​这是什么原因?为什么不是调用缺省的servlet了?这是因为tomcat除了缺省Serlvet外,还给我们提供一个处理jsp文件的Servlet,配置如下,因为后缀匹配的优先级高于缺省的Servlet,所以访问JSP的时候需要交由JspServlet来处理(JSP因为可能包含Java代码,所以第一次执行的时候需要先编译,这个工作由JspServlet完成)

<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>
<servlet-mapping>
 <servlet-name>jsp</servlet-name>
 <url-pattern>*.jsp</url-pattern>
 <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

4.总结

​本文具体讨论了urlPatterns属性的匹配规则,主要为四种,其优先级也各不相同,我们在使用时,也需要根据自己的需求自己设定urlPatterns,不过知道了匹配规则,使用起来也会方便很多,也能帮我们快速的定位错误。

到此这篇关于Servlet虚拟路径映射配置详解的文章就介绍到这了,更多相关Servlet 虚拟路径映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot Admin实践详解

    Spring Boot Admin实践详解

    在本篇文章里小编给大家整理了关于Spring Boot Admin实践的相关知识点,有需要的朋友们可以学习下。
    2019-12-12
  • Springboot实现添加本地模块依赖方式

    Springboot实现添加本地模块依赖方式

    这篇文章主要介绍了Springboot实现添加本地模块依赖方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • java基本教程之多线程基本概念 java多线程教程

    java基本教程之多线程基本概念 java多线程教程

    多线程是Java中不可避免的一个重要主体。下面是对“JDK中新增JUC包”之前的Java多线程内容的讲解,JUC包是由Java大师Doug Lea完成并在JDK1.5版本添加到Java中的
    2014-01-01
  • Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法

    Spring Boot报错:No session repository could be auto-configured

    这篇文章主要给大家介绍了关于Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法,文中给出了详细的解决方法,对遇到这个问题的朋友们具有一定参考价值,需要的朋友下面来一起看看吧。
    2017-07-07
  • SpringCloud中使用Sentinel实现限流的实战

    SpringCloud中使用Sentinel实现限流的实战

    限流在很多地方都可以使用的到,本篇博客将介绍如何使用SpringCloud中使用Sentinel实现限流,从而达到服务降级的目的,感兴趣的可以了解一下
    2022-01-01
  • 生成8位随机不重复的数字编号的方法

    生成8位随机不重复的数字编号的方法

    生成随机不重复的数字编号在某些情况下也会用到,本文以生成8位随机不重复的数字编号为例与大家分享下具体的实现过程,感兴趣的朋友可以参考下
    2013-09-09
  • Java 中使用Spring Security的实例详解

    Java 中使用Spring Security的实例详解

    Spring Security是一款强大的安全框架,可以帮助用户保护Web应用程序和REST API的安全性,这篇文章主要介绍了Java 中如何使用Spring Security,需要的朋友可以参考下
    2023-06-06
  • Java设计模式之迭代器模式

    Java设计模式之迭代器模式

    这篇文章介绍了Java设计模式之迭代器模式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • java 微信小程序code获取openid的操作

    java 微信小程序code获取openid的操作

    这篇文章主要介绍了java 微信小程序code获取openid的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 深入理解Java虚拟机_动力节点Java学院整理

    深入理解Java虚拟机_动力节点Java学院整理

    虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。下面通过本文给大家分享Java虚拟机相关知识,感兴趣的朋友一起看看吧
    2017-06-06

最新评论