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 ...
随机推荐
- label表单的关联性
<input type="checkbox" id="cr" /> <label for="cr">点击关联复选框& ...
- Unity3D学习笔记(十三):委托、考试复习
委托:比较什么时候用委托好 下课案例:不用下课铃 1.ClassManager需要拿到所有教室的引用,课堂管理者应该只负责计时并告知每间教室 2.每间教室应该是由当班老师负责是否需要下课,而课堂管 ...
- StringUtils类常用的方法讲解
StringUtils 方法的操作对象是 Java.lang.String 类型的对象,是 JDK 提供的 String 类型操作方法的补充,并且是 null 安全的(即如果输入参数 String 为 ...
- 如何解决Visual Studio2010 编译时提示系统找不到指定文件问题
前一段时间,开始使用vs2010编写程序,可是在编译的时候总是报错,提示系统找不到指定文件,导致无法正常运行程序,花了好久时间终于找到原因解决,是因为常规的输出目录 要与链接的常规的输出文件要相对应. ...
- 【Android实验】 UI设计-ListView
目录 实验目的 实验要求 实验内容 实现效果 实验代码 实验总结 实验目的 学习使用ListView 学习使用menu 实验要求 实现一个列表,其中显示班级学号姓名,提供添加功能,如需要删去某一项,长 ...
- HDU 1043 Eight(双向BFS+康托展开)
http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...
- java23种设计模式之一: 策略模式
由于最近在研究学习设计模式,我会用自己的理解方式来表述对设计模式的学习和认识,通过最常用.好记的案例来记住和使用设计模式,希望对设计代码方面有所提高和改进. 一.应用背景 在软件开发中常常遇到 ...
- Android移动应用界面的模板化设计
Android没有像苹果开发那样功能强大的界面开发工具,本身 ADT插件提供的界面编辑能力有限,没办法刻画所有的界面情况:Android的界面xml代码可以进行人工修改,而Iphone的全部在图形界面 ...
- GitHub 中国区前 100 名到底是什么样的人?
转一下CSDN的文章, 这里有些人挺厉害的. http://geek.csdn.net/news/detail/66000
- C#实现在应用程序间发送消息的方法示例
本文实例讲述了C#实现在应用程序间发送消息的方法.分享给大家供大家参考,具体如下: 首先建立两个C#应用程序项目. 第一个项目包含一个Windows Form(Form1),在Form1上有一个But ...