Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】

Servlet的调用图

前面我们已经学过了Servlet的生命周期了,我们根据Servlet的生命周期画出Servlet的调用图加深理解

Servlet的细节

一个已经注册的Servlet可以被多次映射

同一个Servlet可以被映射到多个URL上。


        <servlet>
            <servlet-name>Demo1</servlet-name>
            <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>/Demo1</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>/ouzicheng</url-pattern>
        </servlet-mapping>

无论我访问的是http://localhost:8080/Demo1还是http://localhost:8080/ouzicheng。我访问的都是Demo1。

Servlet映射的URL可以使用通配符

通配符有两种格式:

  1. *.扩展名
  2. 正斜杠(/)开头并以“/*”结尾。

匹配所有

匹配扩展名为.jsp的

如果.扩展名和正斜杠(/)开头并以“/”结尾两种通配符同时出现,匹配的是哪一个呢?

  1. 看谁的匹配度高,谁就被选择
  2. *.扩展名的优先级最低

Servlet映射的URL可以使用通配符和Servlet可以被映射到多个URL上的作用:

  1. 隐藏网站是用什么编程语言写的【.php,.net,.asp实际上访问的都是同一个资源】
  2. 用特定的后缀声明版权【公司缩写】

         <servlet>
            <servlet-name>Demo1</servlet-name>
            <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.jsp</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.net</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.asp</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Demo1</servlet-name>
            <url-pattern>*.php</url-pattern>
        </servlet-mapping>



Servlet是单例的

为什么Servlet是单例的

浏览器多次对Servlet的请求,一般情况下,服务器只创建一个Servlet对象,也就是说,Servlet对象一旦创建了,就会驻留在内存中,为后续的请求做服务,直到服务器关闭。

每次访问请求对象和响应对象都是新的

对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

线程安全问题

当多个用户访问Servlet的时候,服务器会为每个用户创建一个线程。当多个用户并发访问Servlet共享资源的时候就会出现线程安全问题。

原则:

  1. 如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制synchronized (对象){}
  2. 如果一个变量不需要共享,则直接在 doGet() 或者 doPost()定义.这样不会存在线程安全问题

load-on-startup

如果在元素中配置了一个元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

作用:

  1. 为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据
  2. 完成一些定时的任务【定时写日志,定时备份数据】

在web访问任何资源都是在访问Servlet

当你启动Tomcat,你在网址上输入http://localhost:8080。为什么会出现Tomcat小猫的页面?

这是由缺省Servlet为你服务的!

  • 我们先看一下web.xml文件中的配置,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>


    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  • 什么叫做缺省Servlet?凡是在web.xml文件中找不到匹配的元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求
  • 既然我说了在web访问任何资源都是在访问Servlet,那么我访问静态资源【本地图片,本地HTML文件】也是在访问这个缺省Servlet【DefaultServlet】
  • 证实一下:当我没有手工配置缺省Servlet的时候,访问本地图片是可以访问得到的

  • 现在我自己配置一个缺省Servlet,Demo1就是我手工配置的缺省Servlet,覆盖掉web.xml配置的缺省Servlet

    <servlet>
        <servlet-name>Demo1</servlet-name>
        <servlet-class>zhongfucheng.web.Demo1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Demo1</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  • 下面我继续访问一下刚才的图片,此时输出的是Demo1这个Servlet写上的内容了

  • 总结:无论在web中访问什么资源【包括JSP】,都是在访问Servlet。没有手工配置缺省Servlet的时候,你访问静态图片,静态网页,缺省Servlet会在你web站点中寻找该图片或网页,如果有就返回给浏览器,没有就报404错误

ServletConfig对象

ServletConfig对象有什么用?

通过此对象可以读取web.xml中配置的初始化参数。

现在问题来了,为什么我们要把参数信息放到web.xml文件中呢?我们可以直接在程序中都可以定义参数信息,搞到web.xml文件中又有什么好处呢?

好处就是:能够让你的程序更加灵活【更换需求,更改配置文件web.xml即可,程序代码不用改】

获取web.xml文件配置的参数信息

  • 为Demo1这个Servlet配置一个参数,参数名是name,值是zhongfucheng

    <servlet>
        <servlet-name>Demo1</servlet-name>
        <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>zhongfucheng</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo1</servlet-name>
        <url-pattern>/Demo1</url-pattern>
    </servlet-mapping>
  • 在Servlet中获取ServletConfig对象,通过ServletConfig对象获取在web.xml文件配置的参数

ServletContext对象

什么是ServletContext对象?

当Tomcat启动的时候,就会创建一个ServletContext对象。它代表着当前web站点

ServletContext有什么用?

  1. ServletContext既然代表着当前web站点,那么所有Servlet都共享着一个ServletContext对象,所以Servlet之间可以通过ServletContext实现通讯。
  2. ServletConfig获取的是配置的是单个Servlet的参数信息,ServletContext可以获取的是配置整个web站点的参数信息
  3. 利用ServletContext读取web站点的资源文件
  4. 实现Servlet的转发【用ServletContext转发不多,主要用request转发】

Servlet之间实现通讯

ServletContext对象可以被称之为域对象

到这里可能有一个疑问,域对象是什么呢?其实域对象可以简单理解成一个容器【类似于Map集合】

实现Servlet之间通讯就要用到ServletContext的setAttribute(String name,Object obj)方法,
第一个参数是关键字,第二个参数是你要存储的对象

  • 这是Demo2的代码

        //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        String value = "zhongfucheng";

        //MyName作为关键字,value作为值存进   域对象【类型于Map集合】
        servletContext.setAttribute("MyName", value);

  • 这是Demo3的代码

        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //通过关键字获取存储在域对象的值
        String value = (String) servletContext.getAttribute("MyName");

        System.out.println(value);
  • 访问Demo3可以获取Demo2存储的信息,从而实现多个Servlet之间通讯


获取web站点配置的信息

如果我想要让所有的Servlet都能够获取到连接数据库的信息,不可能在web.xml文件中每个Servlet中都配置一下,这样代码量太大了!并且会显得非常啰嗦冗余。

  • web.xml文件支持对整个站点进行配置参数信息【所有Servlet都可以取到该参数信息】

    <context-param>
        <param-name>name</param-name>
        <param-value>zhongfucheng</param-value>
    </context-param>
  • Demo4代码

        //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //通过名称获取值
        String value = servletContext.getInitParameter("name");
        System.out.println(value);

  • 试一下Demo3是否能拿到,相同的代码

        //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //通过名称获取值
        String value = servletContext.getInitParameter("name");
        System.out.println(value);


读取资源文件

第一种方式:

  • 现在我要通过Servlet111读取1.png图片

  • 按我们以前的方式,代码应该是这样的。

        FileInputStream fileInputStream = new FileInputStream("1.png");
        System.out.println(fileInputStream);
  • 当我们访问的时候,却出错了!说找不到1.png文件

  • 这是为什么呢?我们以前读取文件的时候,如果程序和文件在同一包名,可以直接通过文件名称获取得到的!,原因很简单,以前我们写的程序都是通过JVM来运行的,而现在,我们是通过Tomcat来运行的
  • 根据web的目录规范,Servlet编译后的class文件是存放在WEB-INF\classes文件夹中的

  • 看到这里,我们知道了要进入classes目录中读取文件,所以我们将代码改成以下方式


        FileInputStream fileInputStream = new FileInputStream("D:\\zhongfucheng\\web\\WEB-INF\\classes\\zhongfucheng\\web\\1.png");
        System.out.println(fileInputStream);

  • 再去读取时,就发现可以获取到文件了。
  • 但是现在问题又来了,我读取文件的时候都要写上绝对路径,这样太不灵活了。试想一下,如果我将该读取文件的模块移到其他的web站点上,我的代码就又要修改了【因为web站点的名字不一样】。
  • 我们通过ServletContext读取就可以避免修改代码的情况,因为ServletContext对象是根据当前web站点而生成的
  • 代码如下所示:

        //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //调用ServletContext方法获取到读取文件的流
        InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/zhongfucheng/web/1.png");


第二种方式:

  • 如果我的文件放在web目录下,那么就简单得多了!,直接通过文件名称就能获取

  • 代码如下所示


        //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //调用ServletContext方法获取到读取文件的流
        InputStream inputStream = servletContext.getResourceAsStream("2.png");


第三种方式:

通过类装载器读取资源文件。

  • 我的文件放在了src目录下【也叫做类目录】

  • 代码如下所示

        //获取到类装载器
        ClassLoader classLoader = Servlet111.class.getClassLoader();

        //通过类装载器获取到读取文件流
        InputStream inputStream = classLoader.getResourceAsStream("3.png");


  • 我的文件放在了src目录下的包下

  • 代码如下,添加包名路径即可。

        //获取到类装载器
        ClassLoader classLoader = Servlet111.class.getClassLoader();

        //通过类装载器获取到读取文件流
        InputStream inputStream = classLoader.getResourceAsStream("/zhongfucheng/web/1.png");


原则:如果文件太大,就不能用类装载器的方式去读取,会导致内存溢出


<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
9篇3章3节:FAERS数据库公共仪表板搜索功能操作与解析 FAERS(FDA不良事件报告系统)公共仪表板是一个强大的工具,用于查询和分析药物及生物制品的不良事件数据。通过该仪表板,用户可以按药品或不良反应进行搜索,查看报告数量、事件类型及时间分布,从而辅助药物安全性分析和科研研究。本文重点介绍仪表板的搜索功能,包括按产品和按不良反应查询的操作步骤、筛选与多维数据分析方法,以及关键概念的解释,帮助用户科学、理性地使用FAERS数据,提升用药决策的准确性和安全性。 阅读详情

相关推荐

1.毫米波雷达心率、呼吸原理实现(一)实例

毫米波雷达心率、呼吸检测原理本项目分两到三篇文章写完,第一阶段借鉴TI开源项目以及根据自己的见解适当更改信号处理链通过AWR1843汽车雷达传感器和DCA1000采集卡采集数据完成人体呼吸和心跳检测算法的实现。第二阶段将仿真成功的代码搬移TIAWR1843传感器并通过串口数据实现生命体征的实时处理。本文即为第一阶段实现过程。本文首先概述毫米波雷达呼吸心跳检测的原理,紧接着概述本项目信号处理流程,另外本项目第一阶段通过matlab仿真验证算法的有效性,仿真源码可关注小编并私信可取。1.概述。

Poulen的博客 2万+

Servlet+Ajax+Echarts实现饼图动态数据可视化

在这追求美的时代,页面数据可视化可谓是一个很好的例子,它不仅可以带来用户更直观、更方便的认识,还能把冷冰冰的数据以一种美感活灵活现的表现出来。今天我想和大家聊聊如果用Ajax、百度的Echarts来实现一个简单的饼图动态数据可视化。

weixin_42572590的博客 2221

手机直连卫星上网,3GPP R17/R18到底做了哪些技术升级?(IoT/NR NTN详解)

本文深入解析了3GPP R17/R18标准中手机直连卫星上网的技术升级,重点介绍了IoT NTN与NR NTN两项关键技术。R17通过星历辅助补偿算法和多普勒频移控制,实现了智能手机直连卫星的突破;R18则进一步优化移动性、支持高频段和星上本地交换,提升用户体验。这些技术为物联网和5G/6G通信开辟了新可能。

weixin_33701251的博客 617

前端与Servlet交互 详解

浏览器不让从一个域名的网页去请求另一个域名网页的资源,这是浏览器的同源策略造成的, 是javaScript加的安全限制跨域的定义是: 只要协议 域名 端口 有任何一个不同 就是跨域 为什么要限制跨域访问万一是另外一个恶意网站响应的数据,会导致服务器出问题 为什么要跨域公司的不同子域需要相互调用资源时后端解决跨域后端可以实现过滤器接口,告诉浏览器此次的访问是安全的location.assign 并不会出现跨域问题, 他会重新开一个窗口,跟原服务器没关系如下图。

weixin_69252724的博客 3970

立创开源Link Hub多功能USB扩展坞:CH339F主控+4层板设计,实测网口/存储性能

本文深度评测了立创开源Link Hub多功能USB扩展坞,其采用CH339F主控芯片与4层PCB板设计,并严格进行阻抗匹配。实测表明,该扩展坞的USB接口与microSD读卡器性能均接近USB 2.0理论极限,百兆以太网口转换效率高,性能损失极小。设计上注重电源保护与信号完整性,是一个兼顾稳定性与成本的高完成度开源硬件项目。

weixin_36173034的博客 159

从Unitree B2W到四足机器人:用Isaac Lab构建强化学习奖励函数的5个实战技巧

本文分享了在Isaac Lab仿真环境中,为Unitree B2W等四足机器人设计强化学习奖励函数的5个核心实战技巧。内容涵盖奖励函数的结构化组合、轮腿混合机器人的适配策略、课程学习的动态调整、域随机化增强鲁棒性以及高效的调试可视化方法,旨在帮助开发者构建更稳定、高效的机器人运动策略。

lg888的博客 1066

Servlet超详解+流程图

1.servlet处理用户请求的完整流程 针对Servlet的每次请求,Web 服务器在调用 service() 方法之前,都会创建 HttpServletRequest 和 HttpServletResponse 对象。其中,HttpServletRequest 对象用于封装 HTTP 请求消息,简称 request 对象。HttpServletResponse 对象用于封装 HTTP 响应消息,简称 response 对象。浏览器访问 Servlet 的交互过程如图 1 所示。 图 1浏览器..

代码是程序员的语言,博客是思想的桥梁,连接你我,共享智慧之光。 9213

速腾Helios-16P使用Lego-loam实时构建点云地图(二)——Lego-loam的编译与运行

不兼容的问题,打开lego-loam的~/lego-loam_ws/src/LeGO-LOAM/LeGO-LOAM/src下的4个源码文件,搜索/camera_init,将所有/camera_init改成camera_init,也就是去掉斜杠,这样再回到工作空间重新编译lego-loam。3、速腾16线激光雷达RS-16 ----- 3D建图算法LeGO-LOAM的使用(Ubuntu18.04 + ROS Melodic)_速腾16线 lego loam_杰尼君的博客-优快云博客。

qq_59475883的博客 2568

servlet返回数据_Servlet(九)

Servlet之间的跳转Servlet之间可以实现跳转,从一个Servlet跳到另一个Servlet,利用Servlet的跳转技术可以很方便的把一块业务模块分开,比如使用后一个Servlet接收用户提交数据,使用另一个Servlet读取数据库,最后跳转到另一个Servlet把处理结果显示出来。这也就是MVC模式(model、view、controller)MVC:用一种业务逻辑、数据、界面显示分离...

weixin_39541189的博客 623

USLE模型(1.2):LS因子的计算

基于USLE的甘南川西北土壤侵蚀研究。准备好30米分辨率的dem。

所有专家都曾始于新手 3481

UI自动化控制PC端微信获取当前群聊的群友列表

在一个月前,某个群友在获取整个群的群友信息时遇到了一点问题: 对整个群进行群友数据获取经测试确实有点棘手,下面我将我的解决过程公布给大家。 基础教程详见: https://blog.csdn.net/as604049322/article/details/121391639 人工打开要抓取的群聊窗口后,首先获取微信窗口并点击聊天信息按钮: import uiautomation as auto auto.uiautomation.SetGlobalSearchTimeout(1) wechatWind

小小明-代码实体的专栏 3万+

关于Servlet

Servlet 1.是什么? 是运行在java服务器端的小程序,,用于接收和响应客户端的请求和响应,要想实现Servlet功能,可以实现Servlet接口或者继承HTTPserv let和GenericServlet,每次请求都会执行service()核心方法 Servlet的三种实现 (1)实现Servlet,实现所有抽象方法,最大程度支持了自定义 (2)继承GenericService抽象类,必须重写Service方法,其他方法可以选择重写 (3)继承HTTPService,重写doget和

撒哈拉奔跑的蜗牛~的博客 258

【Java开发者必看】LangChain4j实战指南:使用AIService轻松集成聊天记忆Chat Memory到SpringBoot应用,通过封装多轮复杂对话,使聊天记忆的实现变得简单

聊天记忆是指在与用户的多轮对话过程中,能够记住之前的交互内容,从而提供更加连贯和个性化的回复。LangChain4j支持通过ChatMemoryProvider接口实现聊天记忆功能。

Spring Boot-Common On With You 448

AI Agent微服务化架构设计与实战:AgentMesh平台解析

当AI Agent从原型走向生产环境,单体架构的扩展性、协作性和治理能力逐渐成为瓶颈。微服务架构通过拆分业务边界、独立部署和按需扩展,为智能体应用提供了工程化的解决思路。本文从微服务核心原理出发,探讨AI Agent与微服务结合的技术价值,并介绍AgentMesh这一开源平台如何将模型接入、Agent编排、工具调用、会话管理等能力服务化。内容覆盖架构组件、调用链路、Spring Cloud实践示例及生产环境常见问题排查,帮助开发者理解企业级AI Agent平台的设计方法论,并快速搭建最小可用系统。

weixin_34348174的博客 343

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

显示驱动板卡协议兼容性本质:不是转接头,而是翻译官

显示驱动板卡的接口兼容性,本质上是数字显示协议(如HDMI、LVDS、DP、VGA)在物理层之上的语义对齐问题。它涉及EDID解析、时序参数匹配、链路训练、色彩空间转换等多层协议栈协同,远超简单线缆连接。HDMI依赖DDC/EDID握手与InfoFrame协商,LVDS需严格遵循JEIDA/VESA时序规范,DP强调自适应链路训练,而VGA则靠硬编码时序实现‘信任制’适配。技术价值在于保障工业显示系统在复杂场景下的稳定点亮与精准成像;典型应用场景包括工控终端升级、车载显示器适配、医疗影像设备改造等。本文深入

weixin_34210740的博客 103

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】...
下一篇: Servlet第三篇【request和response简介、response的常见应用】
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值