深入理解Servlet(下)

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

在这一篇文章里,将会讨论ServletContext以及Servlet映射规则。这两个知识点非常重要,ServletContext直接关系到SpringIOC容器的初始化,而Servlet映射规则与SpringMVC关系密切。

可以说,作为初学者只要把这两点搞清楚,那么对Spring/SpringMVC的理解将会超过70%的程序员。我没开玩笑,你随便抓一个身边的同事问问,Tomcat和Spring什么关系?SpringMVC和Servlet什么关系?估计没几个能给你讲清楚的。

我会先把SpringMVC讲得很简单,等大家觉得它就是个Servlet的时候,我又会把SpringMVC慢慢展开,露出它的全貌。此时你又会发现:SpringMVC is not only a Servlet.

主要内容:

  • ServletContext是什么
  • 如何获取ServletContext
  • Filter拦截方式之:REQUEST/FORWARD/INCLUDE/ERROR
  • Servlet映射器
  • 自定义DispatcherServlet
  • DispatcherServlet与SpringMVC
  • conf/web.xml与应用的web.xml

ServletContext是什么

ServletContext,直译的话叫做“Servlet上下文”,听着挺别扭,但其实就是个大容器,是一个map。服务器会为每个应用创建一个ServletContext对象:

  • ServletContext对象的创建是在服务器启动时完成的
  • ServletContext对象的销毁是在服务器关闭时完成的

ServletContext对象的作用是在整个Web应用的动态资源(Servlet/JSP)之间共享数据。例如在AServlet中向ServletContext对象保存一个值,然后在BServlet中就可以获取这个值。

这种用来装载共享数据的对象,在JavaWeb中共有4个,而且更习惯被成为“域对象”:

  • ServletContext域(Servlet间共享数据)
  • Session域(一次会话间共享数据,也可以理解为多次请求间共享数据)
  • Request域(同一次请求共享数据)
  • Page域(JSP页面内共享数据)

它们都可以看做是map,都有getAttribute()/setAttribute()方法。来看一下物理磁盘中的配置文件与内存对象之间的映射关系:

每一个动态web工程,都应该在WEB-INF下创建一个web.xml,它代表当前整个应用。Tomcat会根据这个配置文件创建ServletContext对象

如何获取ServletContext

还记得GenericServlet吗?它在init方法中,将Tomcat传入的ServletConfig对象的作用域由局部变量(方法内使用)提升到成员变量。并且新建了一个getServletContext():

getServletContext()内部其实就是config.getServletContext()

也就是说ServletConfig对象可以得到ServletContext对象。但是这并不意味这ServletConfig对象包含着ServletContext对象,而是ServletConfig维系着ServletContext的引用。

其实这也很好理解:servletConfig是servletContext的一部分,就像他儿子。你问它父亲是谁,它当然能告诉你。

另外,Session域和Request域也可以得到ServletContext:

session.getServletContext();
request.getServletContext();

本质就是,用域对象获得域对象

最后,还有个冷门的,我在监听器那一篇讲过了:

事件对象就是对事件源(被监听对象)的简单包装

所以,获取ServletContext的方法共5种(page域这里不考虑,JSP太少用了):

  • ServletConfig#getServletContext()
  • GenericServlet#getServletContext()
  • HttpSession#getServletContext()
  • HttpServletRequest#getServletContext()
  • ServletContextEvent#getServletContext()

Filter拦截方式之:REQUEST/FORWARD/INCLUDE/ERROR

在很多人眼里,Filter只能拦截Request:

这样的理解还是太片面了。

其实配置Filter时可以设置4种拦截方式:

很多人要么不知道,要么理解得不够清晰。

这里,我先帮大家把这4种方式和重定向(Redirect)剥离开,免得有人搞混,它们是完全两类(前者和Request有关,后者通过Response发起),以FORWARD为例:

蓝色:重定向,橙色:转发

我们日常开发中,FORWARD用的最多的场景就是转发给JSP,然后模板输出HTML。

Redirect和REQUEST/FORWARD/INCLUDE/ERROR最大区别在于:

重定向会导致浏览器发送2次请求,FORWARD们是服务器内部的1次请求

了解这个区别之后,我提一个很奇怪的问题:为什么这4种只引发1次请求?

是不是听傻了?我接下来给的答案,属于意料之外情理之中的那种:

因为FORWARD/INCLUDE等请求的分发是服务器内部的流程,不涉及浏览器

还记得如何转发吗:

我们发现通过Request或者ServletContext都可以得到分发器Dispatcher,但由于ServletContext代表整个应用,我更倾向于认为:ServletContext拥有分发器,Request是找它借的。

分发器是干嘛的?分发请求:REQUEST/FORWARD/INCLUDE/ERROR。REQUEST是浏览器发起的,而ERROR是发生页面错误时发生的,稍微特殊些。

所以,所谓Filter更详细的拦截其实是这样:

灰色块:Filter

最外层那个圈,可以理解成ServletContext,FORWARD/INCLUDE这些都是内部请求。如果在web.xml中配置Filter时4种拦截方式全配上,那么服务器内部的分发跳转都会被过滤。

当然,这些都是可配置的,默认只拦截REQUEST,也就是浏览器来的那一次。

Servlet映射器

上一篇说了很多Servlet的源码,也介绍了Servlet的作用就是处理请求。但是对于每个请求具体由哪个Servlet处理,却只字未提。其实,每一个URL要交给哪个Servlet处理,具体的映射规则都由一个映射器决定:

这所谓的映射器,其实就是Tomcat中一个叫Mapper的类。

它里面有个internalMapWrapper方法:

定义了7种映射规则:

  • 1.精确匹配 2.前缀匹配

  • 3.扩展名匹配

  • 4.5.6 欢迎列表资源匹配?

  • 7.如果上面都不匹配,则交给DefaultServlet,就是简单地用IO流读取静态资源并响应给浏览器。如果资源找不到,报404错误

简单来说就是:

对于静态资源,Tomcat最后会交由一个叫做DefaultServlet的类来处理对于Servlet ,Tomcat最后会交由一个叫做 InvokerServlet的类来处理对于JSP,Tomcat最后会交由一个叫做JspServlet的类来处理

自定义DispatcherServlet

web.xml

DispatcherServlet

知道了映射器的映射规则后,我们来分析下上图中三种拦截方式会发生什么。

但在此之前,我必须再次强调,我从没说我现在写的是SpringMVC的DispatcherServlet,这是我自己自定义的一个普通Servlet,恰好名字叫DispatcherServlet而已。所以,下面的内容,请当做一个普通Servlet的映射分析。

  • *.do:拦截.do结尾

此时,各个Servlet和谐相处,没问题。

  • /*:拦截所有

拦截localhost:8080

拦截localhost:8080/index.html

拦截localhost:8080/index.jsp

也就是说,/*这种配置,相当于把DefaultServlet、JspServlet以及我们自己写的其他Servlet都“短路”了,它们都失效了。

这会导致两个问题

  • JSP无法被编译成Servlet输出HTML片段(JspServlet短路)
  • HTML/CSS/JS/PNG等资源无法获取(DefaultServlet短路)

  • /:拦截所有,但不包括JSP

拦截localhost:8080

拦截localhost:8080/index.html

不拦截JSP

虽然JSP不拦截了,但是DefaultServlet还是“短路”了。而DispatcherServlet把本属于DefaultServlet的工作也抢过来,却又不会处理(IO读取静态资源返回)。

怎么办?

DispatcherServlet与SpringMVC

SpringMVC的核心控制器叫DispatcherServlet,映射原理和我们上面山寨版的一样,因为本质还是个Servlet。但SpringMVC提供了一个标签,解决上面/无法读取静态资源的问题:

<!-- 静态资源处理  css js imgs -->
<mvc:resources location="/resources/**" mapping="/resources"/>

其他的我也不说了,一张图,大家体会一下DispatcherServlet与SpringMVC到底是什么关系:

DispatcherServlet确实是一个Servlet,但它只是入口,SpringMVC要比想象的庞大。

conf/web.xml与应用的web.xml

conf/web.xml指的是Tomcat全局配置web.xml。

它里面配置了两个Servlet:

也就是JspServlet和DefaultServlet的映射路径。

我们可以按Java中“继承”的思维理解conf/web.xml:

conf/web.xml中的配置相当于写在了每一个应用的web.xml中。

相当于每个应用默认都配置了JSPServlet和DefaultServlet处理JSP和静态资源。

如果我们在应用的web.xml中为DispatcherServlet配置/,会和DefaultServlet产生路径冲突,从而覆盖DefaultServlet。此时,所有对静态资源的请求,映射器都会分发给我们自己写的DispatcherServlet处理。遗憾的是,它只写了业务代码,并不能IO读取并返回静态资源。JspServlet的映射路径没有被覆盖,所以动态资源照常响应。

如果我们在应用的web.xml中为DispatcherServlet配置/*,虽然JspServlet和DefaultServlet拦截路径还是.jsp和/,没有被覆盖,但无奈的是在到达它们之前,请求已经被DispatcherServlet抢去,所以最终不仅无法处理JSP,也无法处理静态资源。

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

进群,大家一起学习,一起进步,一起对抗互联网寒冬

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hive里如何高效生成唯一ID

常见的方式&#xff1a; hive里最常用的方式生成唯一id&#xff0c;就是直接使用 row_number() 来进行&#xff0c;这个对于小数据量是ok的&#xff0c;但是当数据量大的时候会导致&#xff0c;数据倾斜&#xff0c;因为最后生成全局唯一id的时候&#xff0c;这个任务是放在一个…

工业机器视觉megauging(向光有光)使用说明书(十二,轻量级的visionpro)

关于最后一个工具的介绍&#xff1a;就是这个“相机图像” 我们可以鼠标双击点进去看一看&#xff1a; 在图像上点击&#xff0c;就可以截取一块图像&#xff0c;是可以放大缩小的&#xff0c;这个放大很low&#xff0c;是我以前研究缩放入门时的版本&#xff0c;本想删除&…

SELinux refpolicy详解(8)

接前一篇文章&#xff1a;SELinux refpolicy详解&#xff08;7&#xff09; 三、refpolicy内容详解 上一回&#xff08;上几回&#xff09;讲解完了refpolicy源码根目录下的README文件。本回继续讲解源码根目录下的其它文件。先来讲解在README文件中提到的build.conf文件。 2…

网站优化如何做?SEO怎么做?

网站刚上线肯定没有收录&#xff0c;没有排名&#xff0c;这是一个积累内容的阶段。这个阶段的seo优化该怎么做呢&#xff1f;小马识途营销顾问建议从以下几方面展开。 一、网站代码优化 1、设置Robot.txt文件&#xff0c;告诉搜索引擎哪些目录文件可以抓取&#xff0c;哪些目录…

机器学习笔记 - 异常检测之OneClass SVM算法简述

一、异常检测是什么? 如下图,理想中我们可以找到一个框住大部分正常样本的决策边界,而在边界外部的数据点(蓝点)即视为异常。 但实际情况下数据都没有标签,因此很难定义正常还是不正常。异常检测的主要挑战如下:正常与异常行为之间的界限往往并不明确、不同的应…

数字媒体技术基础之:常见字体类型

字体 Font在数字设计和排版中起着至关重要的作用&#xff0c;不同的字体类型为文本呈现和创意表达提供了丰富多样的可能性。 .fon 字体 .fon 文件是 Windows 早期系统中使用的一种字体文件格式。 特点&#xff1a; 1、基于像素的位图字体。 2、不支持无损缩放&#xff0c;主要用…

web前端之TypeScript

MENU typescript类型别名、限制值的大小typescript使用class关键字定义一个类、static、readonlytypescript中class的constructor(构造函数)typescript中abstractClass(抽象类)、extends、abstracttypescript中的接口、type、interfacetypescript封装属性、public、private、pr…

LeetCode刷题笔记第80题:删除有序数组中的重复项 II

LeetCode刷题笔记第80题&#xff1a;删除有序数组中的重复项 II 题目&#xff1a; 删除升序数组中超过两次的元素后的数组长度 想法&#xff1a; 使用快慢指针的方法完成&#xff0c;使用快指针遍历整个数组&#xff0c;使用慢指针完成相同元素最多保留两个。在快指针遍历到…

MATLAB实战 | S函数的设计与应用

S函数用于开发新的Simulink通用功能模块&#xff0c;是一种对模块库进行扩展的工具。S函数可以采用MATLAB语言、C、C、FORTRAN、Ada等语言编写。在S函数中使用文本方式输入公式、方程&#xff0c;非常适合复杂动态系统的数学描述&#xff0c;并且在仿真过程中可以对仿真进行更精…

a-table:表格组件常用功能记录——基础积累

antdvue是我目前项目的主流&#xff0c;在工作过程中&#xff0c;经常用到table组件。下面就记录一下工作中经常用到的部分知识点。 table组件 <a-table :dataSource"tableData":rowKey"(row) > row.id":scroll"{ y: 550 }"bordered:pag…

已解决AttributeError: module ‘gradio‘ has no attribute ‘outputs‘

问题描述 Traceback (most recent call last): File "/media/visionx/monica/project/ResShift/app.py", line 118, in <module> gr.outputs.File(label"Download the output")AttributeError: module gradio has no attribute outputs 解决办…

[英语学习][5][Word Power Made Easy]的精读与翻译优化

[序言] 今日完成第18页的阅读, 发现大量的翻译错误以及不准确. 需要分两篇文章进行讲解. [英文学习的目标] 提升自身的英语水平, 对日后编程技能的提升有很大帮助. 希望大家这次能学到东西, 同时加入我的社区讨论与交流英语相关的内容. [原著英文与翻译版对照][第18页] Wh…

Mininet学习记录(常用命令+创建网络拓扑+OpenDaylight显示拓扑结构)

目录 1.Mininet简介2.Mininet常用命令2.1创建网络拓扑常用参数2.2常用的内部交换命令 3.创建网络拓扑的三种方式3.1通过命令行创建3.2通过miniedit可视化界面创建3.3通过python脚本创建 4.问题总结 1.Mininet简介 Mininet 是由一些虚拟的终端节点 (end-hosts) 、交换机、路由器…

【计算机网络笔记】802.11无线局域网

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

检查您的手机浏览器是否支持WebRTC技术

要检查您的手机浏览器是否支持WebRTC技术&#xff0c;可以通过以下方法&#xff1a; 方法1&#xff1a;使用WebRTC测试网站 访问测试网站&#xff1a; 在手机浏览器中&#xff0c;访问一个专门用于检测WebRTC支持的网站&#xff0c;例如Test WebRTC或WebRTC Troubleshooter.这…

富文本编辑器(wangEditor 5)

一、链接 wangEditor 二、基础 import wangeditor/editor/dist/css/style.css; // 引入 cssimport React, { useState, useEffect } from react; import { Editor, Toolbar } from wangeditor/editor-for-react; import { IDomEditor, IEditorConfig, IToolbarConfig } fro…

【每日OJ —— 572. 另一棵树的子树】

每日OJ —— 572. 另一棵树的子树 1.题目&#xff1a;572. 另一棵树的子树2.解法2.1.算法讲解2.2.代码实现2.3.提交通过展示 1.题目&#xff1a;572. 另一棵树的子树 2.解法 2.1.算法讲解 通过深度优先遍历&#xff0c;来判断二叉树root的每个节点的值是否和subRoot的每个节点…

nodejs微信小程序+python+PHP贵州旅游系统的设计与实现-计算机毕业设计推荐MySQL

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Android 13 - Media框架(22)- MediaCodec(三)

这一节开始我们将重新回到 MediaCodec 这一层来学习 buffer 的流转 status_t MediaCodec::dequeueOutputBuffer(size_t *index,size_t *offset,size_t *size,int64_t *presentationTimeUs,uint32_t *flags,int64_t timeoutUs) {sp<AMessage> msg new AMessage(kWhatDequ…

线面积分公式整理

文章目录 线面积分公式整理第一类曲线积分第二类曲线积分第一类曲面积分第二类曲面积分两类曲线积分的联系两类曲面积分的联系格林公式高斯公式斯托克斯公式 公式的应用 线面积分公式整理 这部分内容用于回顾和查阅,许多写法和表达式记号默认使用了惯例含义其中曲线积分可以从…