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 虚拟路径映射内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 配置Servlet两种方法以及特点详解

    1. 传统web.xml文档中部署servlet <servlet> <servlet-name>LifeServlet</servlet-name>//创建的servlet名字 <servlet-class>servlet.LifeServlet</servlet-class>//完整的包名+类名 </servlet> <servlet-mapping>//映射配置 <servlet-name>LifeSer

  • 详解servlet配置load-on-startup的作用

    在servlet的配置当中,<load-on-startup>1</load-on-startup>的含义是:标记容器是否在启动的时候就加载这个servlet. 当值为0或者大于0时,表示容器在应用启动时就加载这个servlet:当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载. 正数的值越小,启动该servlet的优先级越高. 如果我们在web.xml中设置了多个servlet的时候,可以使用load-on-startup来指定servlet的加载顺序,服

  • quartz实现定时功能实例详解(servlet定时器配置方法)

    Quartz是一个完全由java编写的开源作业调度框架,具体的介绍可到http://www.opensymphony.com/quartz/官方网站查看. Quartz的几个核心的接口和类为: Job接口:自己写的"定时程序"实现此接口的void execute(JobExecutionContext arg0)方法,Job还有一类为有状态的StatefulJob接口,如果我们需要在上一个作业执行完后,根据其执行结果再进行下次作业的执行,则需要实现此接口.Trigger抽象类:调度类(

  • 配置DispatcherServlet的方法介绍

    DispatcherServlet是Spring MVC的前端控制器,要想在程序中使用DispatcherServlet,我们需要在web.xml中配置一个DispatcherServlet.配置的方法是,在web.xml文件中,配置一个<servlet>节点,它的子节点<servlet-name>可以自定义一个名字,例如sample,<servlet-class>指定为org.spring.springframework.web.servlet.DispatcherS

  • servlet配置方法及其生命周期详解

    servlet配置: 在web.xml中,首先向服务器注册一个servlet.在<servlet>标签下 给定一个servlet名字,这个servlet-name是我们自己用的,方便我们用它对servlet进行配置. 1 <servlet-name>AServlet</servlet-name>然后指定一个全类名,这个是给服务器使用,服务器用来创建全类名对象的实例 1 <servlet-class>com.servlet.AServlet</servl

  • SpringBoot初始教程之Servlet、Filter、Listener配置详解

    1.介绍 通过之前的文章来看,SpringBoot涵盖了很多配置,但是往往一些配置是采用原生的Servlet进行的,但是在SpringBoot中不需要配置web.xml的 因为有可能打包之后是一个jar包的形式,这种情况下如何解决?SpringBoot 提供了两种方案进行解决 2.快速开始 2.1 方案一 方案一采用原生Servlet3.0的注解进行配置.@WebServlet .@WebListener.@WebFilter是Servlet3.0 api中提供的注解 通过注解可以完全代替web

  • Servlet+MyBatis项目转Spring Cloud微服务,多数据源配置修改建议

    一.项目需求 在开发过程中,由于技术的不断迭代,为了提高开发效率,需要对原有项目的架构做出相应的调整. 二.存在的问题 为了不影响项目进度,架构调整初期只是把项目做了简单的maven管理,引入springboot并未做spring cloud微服务处理.但随着项目的进一步开发,急需拆分现有业务,做微服务处理.因此架构上的短板日益突出.spring cloud config 无法完全应用,每次项目部署需要修改大量配置文件.严重影响开发效率,因此便萌生了对项目架构再次调整的决心. 三.调整建议 为了

  • Servlet虚拟路径映射配置详解

    ​在上一篇中我们初识了Servlet,相信大家对Servlet也都有了些了解,知道了如何创建一个Servlet,并且为其添加虚拟映射,最终发布项目,并在浏览器上请求对应的Servlet. ​我们知道,只有给Servlet配置好虚拟路径,客户端才可以进行访问,但是对于Servlet的路径映射,真的只有现在所知的这么简单么? ​答案当时是No了,不然怎么会有这篇文章

  • Servlet映射路径匹配解析详解

    目录 开头 源码 精确匹配 通配符匹配 (路径匹配) 扩展名匹配(后缀匹配) 首页welcome资源匹配 默认匹配 开头 servlet是javaweb用来处理请求和响应的重要对象,本文将从源码的角度分析tomcat内部是如何根据请求路径匹配得到处理请求的servlet的 假设有一个request请求路径为/text/servlet/get,并且在web.xml中配置了4个servlet,代码如下,那么该请求调用的是哪一个servlet呢? <servlet> <servlet-name

  • Struts 2中的constant配置详解

    1.<constant name="struts.i18n.encoding" value="UTF-8" /> 指定Web应用的默认编码集,相当于调用 HttpServletRequest的setCharacterEncoding方法. 2.<constant name="struts.i18n.reload" value="false"/> 该属性设置是否每次HTTP请求到达时,系统都重新加载资源文

  • spring mvc路径匹配原则详解

    在Spring MVC中经常要用到拦截器,在配置需要要拦截的路径时经常用到<mvc:mapping/>子标签,其有一个path属性,它就是用来指定需要拦截的路径的.例如: <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="com.i360r.platform.webapp.runtime.view.interceptor.GenericInterceptor"

  • Servlet开发JavaWeb工程示例详解

    一.什么是Servlet? Servlet是在服务器上运行的小程序,也就是一个Java类,但比较特殊,不需要new,自动就可以运行.也有创建.垃圾回收和销毁过程.Servlet是JavaWeb的三大组件之一(Servlet.Filter.Listener),它属于动态资源.Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要: 接收请求数据: 处理请求: 完成响应. 例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完

  • MyBatis输入映射和输出映射实例详解

    什么是 MyBatis ? MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录. 我们知道,mapper.xml是我们配置操作数据库的sql语句的地方.其中每个sql语句对应着一个方法,每个方法都有自己的

  • Nginx配置详解(推荐)

    序言 Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发的.从2004年发布至今,凭借开源的力量,已经接近成熟与完善. Nginx功能丰富,可作为HTTP服务器,也可作为反向代理服务器,邮件服务器.支持FastCGI.SSL.Virtual Host.URL Rewrite.Gzip等功能.并且支持很多第三方的模块扩展. Nginx的稳定性.功能集.示例配置文件和低系统资源的消耗让他后来居上,在全球活跃的网站中有12.18%的使用比率,大约为2220万个网站.

  • Maven的安装配置详解

    下载maven 解压路径: 打开环境变量:右键此电脑-属性-高级系统设置-高级-环境变量 添加以下系统变量: 测试:win+r输入cmd 输入mvn -v,如果出现下面这些信息,就说明maven安装成功,环境变量设置成功. 修改本地仓库路径: 阿里云仓库的配置: <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus

  • Android studio 混淆配置详解

    混淆 studio 使用Proguard进行混淆,其是一个压缩.优化和混淆java字节码文件的一个工具. 功能:Shrinking(压缩).Optimization(优化).Obfuscattion(混淆).Preverification(预校验)四个操作. 优点: 1.删除项目无用的资源,有效减小apk大小: 2.删除无用的类.类成员.方法和属性,还可以删除无用的注释,最大限度的优化字节码文件: 3.使用简短无意义的名称重命名已存在的类.方法.属性等,增加逆向工程的难度. 配置 buildTy

  • java mybatis框架配置详解

    一个框架的使用,必然离不开其中的组件支持.我们在下载完mybatis框架后,因为大部分的内部结构还没有启动,就要手动的对其进行配置.在之前有提到,mybatis框架的作用就有数据库方面的,所以本篇文章带来了数据库和sql方面的配置方法,大家一起往下面看看具体操作. 1.配置数据库 创建mybatis的配置文件,配置数据库的信息.数据库我们可以配置多个,但是默认的只能用一个. <?xml version="1.0" encoding="UTF-8"?> &

随机推荐