Servlet—HttpServlet、Servlet线程安全

由HttpServletRequest的传值引发的线程安全性问题 最近看了下之前项目的代码,发现有同事写了类似如下的代码结构: 1、控制层 @RestController public class TestController { @Autowired private ITestBizc testBizc; @ModelAttribute public void init(HttpServletRequest reques... 阅读详情

1. HttpServlet

Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。

HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。

由于不会使用eclipse连接远程的TomCat服务器,所以在本地Windows系统中重新安装了一个TomCat服务器,现在使用eclipse建立一个Dynamic Web Project工程,命名day05,在com.oner包下建一个名为ServletDemo2的Servlet。

package com.oner;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo2 extends HttpServlet {

	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// 通过response得到一个用于写入二进制数据到response中的ServletOutputStream对象
		ServletOutputStream sout = response.getOutputStream();
		sout.write("hello HttpServlet".getBytes());
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

执行Run on Server,得到结果:



2. Servlet开发中的一些细节

2.1 由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

<servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如:

<web-app>
	<servlet>
		<servlet-name>AnyName</servlet-name>
		<servlet-class>HelloServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>AnyName</servlet-name>
		<url-pattern>/demo/hello.html</url-pattern>
	</servlet-mapping>
</web-app>


2.2 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。

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

	<servlet-mapping>
		<servlet-name>ServletDemo2</servlet-name>
		<url-pattern>/sd2</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>ServletDemo2</servlet-name>
		<url-pattern>/sd2.html</url-pattern>
	</servlet-mapping>


如果这样做的话,即在浏览器中输入http://localhost:8080/day05/sd2、http://localhost:8080/day05/ServletDemo2或者http://localhost:8080/day05/sd2.html都可以访问该web应用。

从这里也可以看出来并不是所有以.html结尾的url访问的都是静态web资源。

2.3 在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。例如:

	<servlet-mapping>
		<servlet-name>ServletDemo2</servlet-name>
		<url-pattern>/sd2/*</url-pattern>
	</servlet-mapping>
	
	<servlet-mapping>
		<servlet-name>ServletDemo2</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

这样在浏览器中输入http://localhost:8080/day05/sd2/xxx...或http://localhost:8080/day05/xxx...do都可以访问到该应用。

但是使用*通配符时有时会造成地址冲突,例如:

对于如下的一些映射关系:
Servlet1 映射到 /abc/*
Servlet2 映射到 /*
Servlet3 映射到 /abc
Servlet4 映射到 *.do
则:

当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应Servlet引擎将调用Servlet1。

当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应Servlet引擎将调用Servlet3。

当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应Servlet引擎将调用Servlet1。

当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应Servlet引擎将调用Servlet2。

当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应Servlet引擎将调用Servlet2。


2.4 Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

2.5 针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。

2.6 在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

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

	<servlet>
		<servlet-name>invoker</servlet-name>
		<servlet-class>
			org.apache.catalina.servlets.InvokerServlet
		</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>

<load-on-startup>元素的值为一个正整数,表示servlet应该被载入的顺序,数值越小,代表启动优先级越高。

用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。

2.8 如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。

    该怎么理解这些话呢?理解之前我们可以思考下这个问题:假如我们在day05这个web应用下创建一个1.html的静态资源,在浏览器中输入http://localhost:8080/day05/1.html后得到了1.html这个文件的内容,那么浏览器是如何得到的呢?首先我们要明白的是,浏览器不管是向服务器发送请求,也就是说不管是访问静态资源还是动态资源,其实都是服务器的servlet在处理。当服务器收到浏览器发来的请求后,会在web.xml中寻找有没有哪个servlet映射到1.html这个目录上,如果有,就让该servlet去处理,否则就让缺省servlet处理这个请求。在这里,由于1.html这个静态资源并没有哪个servlet映射到该目录,所以这时缺省servlet就会将该1.html的数据内容写入到response对象中,然后由response对象将1.html的内容传给浏览器。但是这儿又出现了一个问题,这个缺省servlet从哪来呢?在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。

    明白了上面的原理,这下再考虑之前的问题,如果将某个Servlet的映射路径设为"/",那么这个Servlet就成为当前Web应用程序的缺省Servlet,也就是说覆盖了系统默认的org.apache.catalina.servlets.DefaultServlet这个servlet。当在web.xml文件中找不到匹配的<servlet-mapping>元素的URL时,浏览器的访问这些访问请求就交给了现在咱们设置的这个servlet。

3. Servlet的线程安全问题

    当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
    在普通Java程序中,我们知道可以使用synchronized语句或者lock锁来解决,但是如果在Servlet中也这样做的话,会导致在一个客户端访问时,另一个客户端无法访问。

    在Servlet中提供的解决方法是:如果让某个Servlet实现SingleThreadModel这个标记接口,那么Servlet引擎将以单线程模式来调用其service方法。

    对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

servlet相关(流程、原理、生命周期、HttpServlet) 一、什么是servlet ? Servlet本质上就是一个Java语言定义的接口,广义的Servlet就是指实现了这个Servlet接口的类。一般指的就是后者。 Servlet实例的主要功能就是根据客户端的请求,找到并调用服务端相关java代码,完成对请求的处理和运算。 Servlet实例遵循了服务器能够识别的规则,服务器会根据请求调用对应的servlet进行请求处理。 (1)Servlet实例,由Servlet容器创建,通常这个容器就是tomcat。 (2)Servlet是一个接口:位于ja. 阅读详情

相关推荐

断点回归(regression discontinuity design)学习笔记

本篇博文主要是对断点回归的一些学习和总结~ 学习材料如下: 1 断点回归设计RDD分类与操作案例 2 RDD断点回归, Stata程序百科全书式的宝典 3 断点回归设计的前沿研究现状, RDD 4 让“跳跃”更有意义:断点回归设计(RDD) 5 Stata: 断点回归 (RDD) 教程 6 怎么用通俗的语言解释断点回归?它与DID的区别是什么 7 Watering Down Environmental Regulation in China,Guojun He, Shaoda Wang, Bing Zhan

Claire_chen_jia的博客 9万+

Servlet线程安全问题及解决

servlet线程安全问题及解决方式

qq_52146944的博客 605

图生文【学习中】

图生文:提供图像,把图像对应的信息用文本描述出来

qq_19072921的博客 1787

Servlet基础之HttpServletRequest详解

本文主要讲解了一个Http请求所经历的过程,以及Http请求的三部分内容,分别为请求行、请求头和请求体,以及如何通过HttpServletRequest获取对应的信息,通常来讲Servlet获取客户端数据的数据是第一步,因此HttpServletRequest对象是非常重要的,对其中的方法做到熟练掌握也可让我们在开发的过程中更加的得心应手。

丹丹的后花园 6万+

东方财富API隐藏技巧:这样获取分时均价线数据更稳定(避坑指南)

本文深入解析东方财富API获取股票分时数据,特别是分时均价线的实战技巧与避坑指南。针对高频调用中常见的请求失败、数据错位及IP限制等问题,提供了从接口参数深层解析、稳健请求与错误处理机制,到系统优化与数据校验的全流程解决方案,帮助开发者构建稳定可靠的数据采集系统。

rice5的博客 2521

Ubuntu 上 1Panel 的安装与高效运维实践

本文详细介绍了在Ubuntu系统上安装和高效运维1Panel面板的完整实践指南。内容涵盖了一键安装、Docker容器可视化部署、计划任务自动化以及网站数据库管理等核心功能,并提供了安全加固、资源监控与数据备份等进阶技巧,旨在帮助用户快速搭建并管理一个强大易用的服务器环境。

weixin_29210759的博客 142

Servlet的生命周期~

前两天面试被问到关于Servlet生命周期的问题~现在好好地将这个问题理一下: 首先如下图所示: Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示。 Servlet的生命周期包含了下面4个阶段: (1)加载和实例化 Se

Better2326的专栏 885

四参数与七参数坐标转换含义及区别

一.前言 不同坐标系,其椭球体的长半径,短半径和扁率是不同的。比如我们常用的四种坐标系北京54、西安80、WGS84、CGCS2000所对应的椭球体,它们的椭球体参数就各不相同。而不同空间直角坐标系之间的转换一般通过七参数或者四参数来实现坐标转换。 二.四参数转换 两个不同的二维平面直角坐标系之间转换通常使用四参数模型,四参数适合小范围测区的空间坐标转换,相对于七参数转换的优势在于只需要2个公共已知点就能进行转换,操作简单。 在该模型中有四个未知参数,即: (1)两个坐标平...

尘海折柳的博客 1万+

Servlet的线程安全

Servlet的多线程机制   1. 变量的线性安全:这里的变量指字段和共享数据(如表单参数值)。 将参数变量本地化。多线程并不共享局部变量,所以要尽可能地在servlet中使用局部变量。例如:String user=request.getParameter("user"); 使用同步块Synchronized,防止可能异步调用的代码块,这就意味着线程需要排队处理。但要注意在使用同步块...

java开发指南博客 【转载】 391

学习笔记【Day 20】鸿蒙PC应用在SD WAN MSTP场景用CodeArts test工具测试过程

多生成树协议(MSTP)作为二层网络高可靠、无环路的核心技术,其在鸿蒙 PC 上的兼容性与稳定性测试尤为重要。本文结合华为云 CodeArts TestPlan 全流程测试管理平台,详细拆解鸿蒙 PC 端 MSTP 功能的测试设计、环境搭建、执行验证。1.测试左移,保障迭代效率CodeArts TestPlan 将 MSTP 测试从后期集成阶段 “左移” 至开发早期,通过可复用用例库与自动化脚本,支持每次代码提交后的快速回归测试,避免网络功能稳定性因迭代被破坏。2.平台化工具破解复杂场景测试难题。

aiyijianghe的博客 1057

python 实现一个完整的基于Python的多视角三维重建系统,包含特征提取与匹配、相机位姿估计、三维重建、优化和可视化等功能

本文介绍了一个基于Python的多视角三维重建系统的实现,涵盖了特征提取与匹配、相机位姿估计、三维重建、优化和可视化等功能。首先,系统通过安装必要的库(如OpenCV、NumPy等)并加载图像数据,初始化相机参数。接着,系统使用SIFT、SURF或ORB算法提取图像特征点,并通过FLANN或BF方法进行特征匹配,应用Lowe's ratio test筛选优质匹配。该系统为后续的相机位姿估计和三维重建奠定了基础,能够从多视角图像中恢复三维场景结构。

huanghm88的专栏 614

HttpServlet基本学习和Servlet中的一些细节

一:HttpServlet概述:HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。二:HttpServlet覆盖了service()方法 HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,这个

a_lonely_dancer的博客 1229

Mybatis面试题(基础篇)

(1)mybatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。(2)mybatis避免了几乎所有的JDBC代码(说明了mybatis底层用的就是JDBC,只不过是封装了)和手动设置参数以及获取结果集。(3)mybatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的pojo映射成数据库中的记录。

qq_38196449的博客 1686

GenericServlet 与 HttpServlet

GenericServlet 与 HttpServlet

啊哈的博客 570

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Servlet的总结与解释(定义,生命周期,JSP,线程安全)

servlet是web三大组件之一.是最重要组件 servlet是什么? 可以干什么? Servlet接口与HttpServlet servlet的生命周期 servlet的常见配置 Servlet如何接收数据,响应数据? JSP是什么? 为什么要有JSP? servlet是线程安全的吗? 不是的话,解决方案是什么?   1.servlet是什么? 可以干什么? Servlet是...

学习真香 327

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【Servlet教科书】Servlet到底是什么?有什么作用?(详细记录知识)

文章目录@[toc]一、初识Servlet1.1 Servlet概念1.2 Servlet的核心作用1.3 Servlet核心目录结构1.3 IDEA工具内创建核心目录结构1.4 Servlet的开发步骤1.4.1 开发步骤1.4.2 web.xml配置文件添加配置信息1.4.3 我们的第一个Servlet(MyServlet代码)1.4.4 解决浏览器输出显示乱码问题1.4.5 解决idea控制...

奈何的人生 9176

JavaWeb 三大组件之 Servlet

Servlet概述 Servlet是JavaWeb三大组件之一,主要用于处理客户端请求。它由Web容器(如Tomcat)管理生命周期,具有以下特点: 生命周期方法: init():Servlet初始化时执行一次 service():每次处理请求时调用 destroy():Servlet销毁时执行一次 重要特性: 单例模式(一个Servlet类只有一个实例) 线程不安全但效率高 实现方式: 实现Servlet接口 继承GenericServlet类 继承HttpServlet类(最常用) Servlet需要开

py_1990_04_20的博客 1161

关于Servlet线程安全性和DispatcherServlet的线程安全性的解析

我们知道在Servlet第一次被调用的时候,Servlet容器会根据web.xml中配置的信息去实例化Servlet,而且这个Servlet只会被实例化一次。当多个请求同时到来时,可能会使用同一个Servlet进行处理,这时候就会涉及到线程安全的问题。 纠结!!! Servlet的线程安全性?...

chijunmei7041的博客 881

关于servlet的单例和线程安全问题的思考

转载:https://www.jianshu.com/p/82a2a4fcd0c9 我们知道在Servlet第一次被调用的时候,Servlet容器会根据web.xml中配置的信息去实例化Servlet,而且这个Servlet只会被实例化一次。当多个请求同时到来时,可能会使用同一个Servlet进行处理,这时候就会涉及到线程安全的问题。 纠结!!! Servlet的线程安全性?不确定 Ser...

whathellll的博客 395

SpringMvc的DispatcherServlet和Control的线程安全问题

Servlet的线程安全性?不确定 Servlet是单实例多线程的方式来处理请求,这应该就是造成线程安全的主要原因了。我们知道Servlet本身是无状态的,也就是说Servlet本身是线程安全的,但是为什么网上都说Servlet是线程不安全的呢?可能就是根据一句多个线程会同时访问一个Servlet实例来判断的把。 而Servlet是不是线程安全的,主要是由实现来决定的,如果一个Serv

IT匠人的博客 5350

面试题,Servlet 线程安全吗?

Servlet的工作原理:首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没doGet,doPost等等这些方法的,HttpServlet中定义了...

程序猿踩坑集锦 2184

Servlet入门篇

今天刚接触Servlet,并作了如下总结,如有哪里错误请指教!(PS:后面的知识还有持续更新,如有需要的朋友,请关注······)1. 如何创建一个你的第一个servlet?**在tomcat中新建一个web应用,然后在web应用中新建一个web-inf/classes目录。//**在classes目录中新建一个FirstServlet,例如: package com.Cecilia.servlet

Cecilia 894

学习Servlet

Servlet是sun公司提供的一门用于开发动态web资源的技术,可以实现和客户端的交互,接收客户端和给客户端返回。

secret010的博客 1264

Servlet的实现类

GenericServlet GenericServlet概述 GenericServlet是Servlet接口的实现类,我们可以通过继承GenericServlet来编写自己的Servlet。下面是GenericServlet类的源代码: GenericServlet.java public abstract class GenericServlet implemen

午-夜 2473

关于Servlet的一些知识

servlet的生命周期就是从servlet出现到销毁的全过程。主要分为以下几个阶段: 加载类—>实例化(为对象分配空间)—>初始化(为对象的属性赋值)—>请求处理(服务阶段)—>销毁 服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(Servl...

我是你庆歌的博客 245

Servlet的运行流程解析发简介

Servlet是sun公司提供的一门用于开发动态web资源的技术。Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:编写一个Java类,实现servlet接口。把开发好的Java类部署到web服务器中。

qq_73778722的博客 432
上一篇: Servlet—Servlet简介、Servlet调用过程
下一篇: Servlet—ServletConfig、ServletContext
Wang_AI
博客等级 码龄12年 988粉丝 162原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值