servlet基础(组成与生命周期)
servlet基础
作用:servlet是运行在Web服务器或应用服务器上的程序;担当web浏览器或其他HTTP客户程序发出的请求与HTTP服务器上的数据库或应用程序之间的中间层。
1、读取客户程序发送的显式数据
2、读取浏览器发出的隐式HTTP请求数据
HTTP信息包括cookie、媒体信息和浏览器能够识别的压缩模式
3、生成结果
可能与数据库对方,调用web服务或者直接计算得到响应
4、向客户发送显式数据(即文档)
这种文档可以用各种不同的形式发送,包括文本、二进制、exce,甚至是其他压缩格式
5、发送隐式的HTTP响应数据
发送到用户的数据有两种:文档本身、以及后台的HTTP信息。两种类型的数据对开发工作都至关重要。发送HTTP响应数据时,需要告知浏览器或其他客户程序返回文档的类型(如HTML)、设置cookie并缓存参数、以及其他类似任务。
servlet的基本结构:
servlet一般扩展HttpServlet,并依据数据发送方式的不同(GET或POST),覆盖doGet或doPost方法。如果希望servlet对GET和POST请求采取同样的行动,只需要让doGet调用doPost,反之亦然。
doGet和doPost接受两个参数:HttpServletRequest和HttpServletResponse
生成HTML的servlet
大多数servlet生成HTML,而并非前面例子中的纯文本。要生成HTML,需要在刚才介绍的过程中加入下面3步:
1、告知浏览器,即将向他发送HTML
使用HTTP Content-Type响应报头设置为text/html来完成
必须在传送实际的文档之前设定内容的类型
2、修改println语句,构建合法的Web页面
3、验证生成的HTML语法
servlet的生命周期:
服务器只创建每个servlet的单一实例,每个用户请求都会引发新的线程。现在,更加详细的介绍servlet的创建和销毁方式,以及调用各种方法的方式和时间。
首次创建servlet时,它的init方法会得到调用。在这之后,针对每个用户请求,都会创建一个线程,该线程调用前面创建的实例的service方法。多个并发请求一般会导致多个线程共同调用service(尽管可以实现特殊的接口SingleThreadModel——规定任何时间只允许单个线程运行)。之后,由service方法依据收到的Http请求类型,调用对应的doGet等方法。最后,如果服务器决定卸载某个servlet,它会首先调用servlet的destory方法。
service方法:
服务器每次接受到对servlet的请求,都会产生一个新的线程,调用service方法。service方法检查HTTP请求的类型并相应地调用doGet等方法。
如果您需要在servlet中等同的处理POST和GET请求,您可能会倾向于不去实现doGet和doPost方法,而是直接覆盖service方法。这不是一个好思想。取而代之,只需让doGet调用doPost(或相反)即可。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
//Servlet code
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
虽然这种方式要多出几行代码,但相对于直接覆盖service,它有好几项优点。首先,之后您还可以加入doPut,doTrace等,支持其他HTTP请求方法。其次,您还可以通过添加getLastModified方法,加入对修改日期的支持。由于getLastModified由默认的service方法调用,所以覆盖service方法也失去了这个选项。
doGet、doPost、doXX方法:
这些方法才是servlet的主体
init方法:
大多时候,您的servlet只需要处理单个请求的数据,doGet或doPost是成名周期中唯一需要的方法。然而,有时候您希望在servlet首次载入的时候执行复杂的初始化任务,并且不想每个请求都重复这些任务。init方法就专门为这种情况设计,它在servlet初次创建时被调用,之后处理每个用户的请求时,则不再调用这个方法。
servlet一般在用户首次调用对应servlet的URL时创建,也可以制定和servlet在服务器启动后载入。
init方法的定义:
public void init() throws ServletException {
//Initialization code...
}
init方法执行两种类型的初始化:常规初始化,以及由初始化参数控制的初始化。
常规初始化:
第一种类型的初始化中,init只是创建或载入在servlet生命周期内用到的一些数据,或者执行某些一次性的计算。
getLastModified方法为HttpServlet的方法,如果服务器接受到条件get请求(制定客户只想要那些自特定日期依赖发生的页面),系统会将指定的日期与getLastModified返回的日期进行比较,只返回那写在指定的日期之后发生发生改变的页面。
/**
* The standard service method compares this date against any date specified in the If-Modified-Since request header.
* If the getLastModified date is later or if there is no
* If-Modified-Since header, the doGet method is called
* normally. But if the getLastModified date is the same or earlier, the service method sends back a 304 (Not Modified)
* response and does not call doGet. The browser should use it cached version of the page in such a case.
* @param req
* @return
*/
由初始化参数控制的初始化:
要理解init参数的动机,您需要了解什么样的人可能希望对servlet的行为进行定制。它们主要可以分为3组:
1、开发人员
2、最终用户
3、部署人员
开发人员改变代码改变servlet行为
用户表单提交数据改变servlet行为
部署人员怎么办?init参数就是为了使管理员无需修改servlet的源代码就可以将servlet在机器间移动以及改变特定的参数。
1、web.xml中的servlet元素可以为servlet赋予名称
2、web.xml中的servlet为servlet指定一个定制URL
3、web.xml的servlet元素添加init-param子元素,可以指定初始化参数的名称和值
4、servlet的init方法中,调用getServletConfig获取servletConfig对象的引用
5、以init参数的名称为参数,调用ServletConfig的getInitParameter方法
destory方法:
服务器在移除servlet的实例前,会调用servlet的destory方法,可以使得servlet有机会关闭数据库连接等活动。但要注意web服务器有可能崩溃,因此不要将destory机制作为向磁盘上保存状态的唯一机制。
SignleThreadModel接口:
通常,系统只生成servlet的单一实例,之后为每个用户请求创建新的线程。所以doGet和doPost方法必须小心地同步对字段和其他共享数据访问。注意,多个线程并不共享局部变量,因此不需要特别的保护。
实现SignleThreadModel接口,系统会保证不会有多个请求线程同时访问该servlet的单个实例。使用了队列。但是服务器也可以创建由多个实例组成的池,同一时间每个实例都能够处理请求。然而,您依旧必须同步对类变量或存储在servlet之外的共享数据的访问。
SignleThreadModel尽管能阻止并发访问,但是实际上是不好的选择,原因:
1、同步对servlet的性能造成极大等待。应该考虑只同步操作共享数据那部分代码。
2、SingleThreadModel规范允许服务器使用多个实例来处理请求来替代对单个实例的请求进行排队的方案。只要每个实例同一时间只处理一个请求,实例共享的方式就满足规范的要求。但这不是一个好方案。
原因:
1、加入使用非静态存储共享数据。SingleThreadModel会阻止并发的访问,相当于把孩子和洗澡水同时泼掉了;每个servlet实例都拥有实例变量的单独副本,因此数据也不能正确共享。
2、加入使用静态共享数据。SingleThreadModel的共享池方式没有优点,多个请求仍然会并发访问静态数据。
例子:
String id = "User-ID-" + nextID;
out.println("<H2>" + id + "</H2>");
nextID = nextID + 1;
并发可能出问题。
解决方案:
1、减少竞争
修改为:String id = "User-ID-" + nextID++;
降低了并发问题的可能性,但是没有消除。和怒道情况下,降低错误出现的可能性是一件坏事而不是一件好事。
2、使用SingleThreadModel
前面说过坏处。
3、明确同步
synchronized(this) {
String id = "User-ID-" + nextID;
out.println("<H2>" + id + "</H2>");
nextID = nextID + 1;
}
servlet的调试:
1、println语句。
2、debug
3、日志
4、单元测试
5、检查源码
6、检查请求
7、检查响应
8、重启服务
servlet基础(组成与生命周期)的更多相关文章
- JavaEE Servlet 核心方法及生命周期
做JavaWeb开发,免不了要和Servlet打交道.Servlet是Sun(Oracle)官方定义的一个Web开发规范,所有Servlet开发都必须遵守.自己以前也没有从头做过Web开发,所以这方面 ...
- JavaWeb之 Servlet执行过程 与 生命周期
Servlet的概念 什么是Servlet呢? Java中有一个叫Servlet的接口,如果一个普通的类实现了这个接口,这个类就是一个Servlet.Servlet下有一个实现类叫HttpServle ...
- HTTP协议 Servlet入门 Servlet工作原理和生命周期 Servlet细节 ServletConfig对象
1 HTTP协议特点 1)客户端->服务端(请求request)有三部份 a)请求行--请求行用于描述客户端的请求方式.请求的资源名称,以及使用的HTTP协议版本号 请求行中的GET ...
- [转]JavaWeb之 Servlet执行过程 与 生命周期
https://www.cnblogs.com/vmax-tam/p/4122105.html Servlet的概念 什么是Servlet呢? Java中有一个叫Servlet的接口,如果一个普通的类 ...
- 【servlet】Servlet的API和生命周期]
创建时间:6.15 一.Servlet的API(生命周期) (1)Servlet接口中的方法 1)init(ServletConfig config) 何时执行:servlet对象创建的时候执行 Se ...
- JavaEE基础(01):Servlet实现方式,生命周期执行过程
本文源码:GitHub·点这里 || GitEE·点这里 一.Servlet简介 Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容.使用S ...
- JavaEE基础(01):Servlet实现方式,生命周期执行...
一.Servlet简介Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容.使用Servlet,可以收集来自网页表单的用户输入,呈现来自数据库 ...
- Servlet执行流程和生命周期【慕课网搬】
Servlet执行流程(GET方式为例) 首先用户客户端浏览器发出Get方式(点击超链接方式)向浏览器发出请求. 服务器接收到客户端点击超链接,接收到GET请求之后,服务器到WEB.xml中<s ...
- servlet 和filter 的生命周期说明
servlet : 当客户端第一次访问servlet的时候,服务器就会创建servlet实例,servlet 就会执行init方法,每次请求,服务器会开一个新的线程访问servlet中得service ...
- [03] Servlet继承关系和生命周期
1.Servlet的继承关系 假如现有我们自定义的一个Servlet,继承HttpServlet,那么实际上它的继承链如下图: 可以看到,核心的部分在于: 两个顶级接口 Servlet Servl ...
随机推荐
- java对象在内存的大小
前言 一直以来,对java对象大小的概念停留在基础数据类型,比如byte占1字节,int占4字节,long占8字节等,但是一个对象包含的内存空间肯定不只有这些. 假设有类A和B,当new A()或者n ...
- 列举一些有所帮助的blog和文章
w3school hdoj imooc CSDN Github myGithub CmdMarkdown 一直在路上--记我从初中到本科近十年的学习成长历程 作者:周见智 C++中队列的建立与操作详细 ...
- C# 实现简单的 Heap 堆(二叉堆)
如题,C# 实现简单的二叉堆的 Push() 和 Pop(), 如有不足欢迎指正. 另外,在C#中使用 Heap 的相似功能可以考虑使用:Priority Queues,SortedDictiona ...
- HDU 6162 Ch's gift(树链剖分+线段树)
题意: 已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和. 思路: 用树链剖分将树映射到线段树上,线段树上维护3个值,max,mi ...
- python 线性查找
import random val= data=[,,,,] : find= val=int(input('请输入查找键值(1-9),输入-1离开:')) for i in data: if i==v ...
- 常见dos命令汇总
常用的内部命令有md.cd.rd.dir.path.copy.type.edit.ren.del.cls.ver.date.time.prompt.常用的外部命令有deltree.format.dis ...
- Android JNI学习(四)——JNI的常用方法的中文API
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- AtomicLong与LongAdder的区别
AtomicLong的原理 AtomicLong是通过依靠底层的CAS来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目的. LongAdder的 ...
- PWA小记
前言 中国有不一样的MobileFirst战略,重原生应用,轻移动网页: 移动网页的弱势:页面设计优化有限,用户体验受网络环境影响,网页开启不方便: web优势是产品分发 app优势是产品使用和交互 ...
- Unity + NGUI 实现人物头顶UI的信息展示
1.思路: (1)信息数据:需要展示属性信息 (2)信息的展示:负责显示UI属性信息 (3)UI的跟随:负责实现UI对人物的跟随 (4)UI的管理:负责对UI进行创建于回收,游戏中需要用到UI的地方都 ...