servlet 的存在就是为了客服服务, servlet的任务是得到一个客户的请求, 再发回一个响应.

由上图可知, web 容器会在启动后就加载所有的servlet类, 并为之创建实例和初始化

注意: init方法是在第一个用户调用此servlet时被触发

service() 方法属于servlet类, 容器创建的线程调用了 service() 方法. 并把 HttpRequest, HttpReponse 这两个对象传递给了这个新的线程.

容器首先根据配置文件找到对应的 servlet, 然后 自然而然的调用这个servlet 的 service 方法, 那么就不用再确认调用的doPost是否弄错了, 比如调用了别人的servlet.

servlet 的继承关系

3大生命周期

一般 servlet 都不会有很多实例, 从这来看, 就一个实例

容器运行多个线程来处理对一个 servlet 的多个请求

对应每个客户请求, 会生成一对新的请求和响应对象.

注意:是容器根据请求中的url找到正确的servlet, 为这个请求创建分配了一个线程, 然后由这个线程调用

servlet的service()方法, 把请求和响应作为参数传给它.

容器是如何处理用户请求的?

1)用户点击一个链接,指向一个servlet而不是一个静态页面。

2)web服务器接到这个请求后转发给容器。容器接着创建两个对象:HttpServletRequest和HttpServletResponse。

3)容器根据请求中的URL找到相应的servlet,为这个请求创建一个线程,并把请求对象HtttpServletRequest和响应对象HttpServletResponse传递给这个servlet线程。

4)线程接下来调用service()方法,根据请求的不同,service()方法调用doGet()和doPost()方法。

5)doGet()方法生成动态页面,并把这个页面塞到响应对象里。

6)service()方法结束,随之线程结束,容器把响应对象装换为一个HTTP相应,发送给客户,然后删除请求和响应对象。

Servlet的生命周期

注意他的一生都是由容器控制的。servlet一生中只有一个实例出现,但是有多个线程出现。

加载类 Servlet .class文件

实例化 构造函数运行

初始化 容器调用 init() 方法(一生只调一次)

service方法? servlet一生主要在这里度过

销 毁? 销毁实例之前调用 destroy() 方法

可回收? 等待垃圾回收等待垃圾回收

servlet 在运行过程中, 变量的安全性问题

(一)变量的安全性

错误实例:

public class test extends HttpServlet{

String user = "" ;

public void doGet(HttpServletRequest req , HttpServletResponse res) throws ServletException , IOException{

user = req.getParameter("user");

......

}

}

例如:a、b同时访问这个servlet,a提交的user=aaa,b提交的user=bbb。

首先,servlet容器分配一个线程T-a来处理请求a,获取其user的值aaa,并赋给变量user。此时T-a时间片到了,servlet容器分配另外一个线程T-b来处理请求b,

获取其user的值bbb,并覆盖变量user,当T-a线程重新获取执行权时,user已经“物是人非”了。

因为user 是一个实例变量, 而这个实例(servlet) 一直都是“一个”实例,没有再增加, 所以他们调用的是同一个实例变量, 所以会有以上问题.

这里可以类比:jdbc的事务管理,“丢失更新”和这个场景类似。

解决方案:

1)定义本地变量,将user在doGet方法中定义。

因为user是本地变量,每一个线程都有user变量的拷贝,彼此不受影响。

2)设置方法同步(或者同步块)

因为设置了同步,可以防止多个线程同时调用doGet方法。但是所有请求该servlet的“请求”将串行处理,影响效率。同步实际是”排队”

幂等的定义: 一次一次可以重复执行的内容, doGet() 是幂等的, 可以返回执行, 而doPost()不是幂等的, 因为它可能修改服务器上的内容.

如何判定使用GET还是POST

Get: 简单的超链接. 默认使用Get,

Post: method=”post”, submit,

从请求对象中可以得到什么?

客户的平台浏览器信息

string client = request.getHeader(“User-Agent”);

与请求相关的cookie

Cookie[] cookies = request.getCookies();

与客户相关会话(session)

HttpSession session = request.getSession();

请求的HTTP方法

String theMethod = request.getMethod();

请求的输入流

InputStream input = request.getInputStream();


响应

响应要返回给客户, 这是浏览器得到, 解析并呈现给用户的东西, 一般你会使用响应对象得到一个输出流(通常是一个writer), 并使用这个流写出HTML(或其他类型内容), 返回给客户. ( 也可以生成一个jsp返回给客户 )

响应会经常调用两个方法:

setContentType()   // 告诉浏览器你发回去的是什么

getWriter()        // 用于输出字符

例如你要从服务器请求一个jar文件, 服务器的返回代码是:

public class CodeReturn extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException {

response.setContentType(“application/jar”);   // 告诉服务器返回内容的类型

ServletContext ctx = getServletContext();

InputStream is = ctx.getResourceAsStream(“/bookCode.jar”);

int read = 0;

byte[] bytes = new byte[1024];

OutputStream os = response.getOutputStream();

while ((read = is.read(bytes)) != -1) {

os.write(bytes, 0, read);

}

os.flush();

os.close();

}

}

对于输出, 你只有两个选择, 字节或字符

ServletOutputStream 输出字节

ServletOutputStream out = response.getOutputSt();

out.write(aByteArray);

PrintWriter 输出字符

PrintWriter writer = response.getWriter();

writer.println(“some text and HTML”);

利用重定向来响应, 而非servlet自己处理响应

利用jsp 来处理响应

重定向使得 servlet完全卸下担子, servlet只是调用 sendRedirect()方法:

response.sendRedirect(“http://www.abc.com”);   // 地址直接重定向

原路径: http://abc.com/myApp/cool/bar.do

response.sendRedirect(“foo/stuff.html”);       // 相对路径 = http://abc.com/myApp/cool/foo/stuff.html

reponse.sendRedirect(“/foo/stuff.html”);       // 绝对路径, 从根目录开始, 注意这是以”/”开头的, = http://abc.com/foo/stuff.html

请求分派

重定向让客户端完成工作 重定向 = 客户端

请求分派要求服务器上某某来完成任务 请求分配 = 服务器

HeadFirst Jsp 04 (请求和响应作为servlet)的更多相关文章

  1. 简单的Servlet结合Jsp实现请求和响应以及对doGet和doPost的浅析

    1.新建jsp,创建表单 <body> <form action="/MyfirstWeb/login"> username:<input type= ...

  2. JavaWeb基础-Jsp的请求与响应

    JSP请求和相应 HTTP头信息 当浏览器请求一个网页时,它会向网络服务器发送一系列不能被直接读取的信息,因为这些信息是作为HTTP信息头的一部分来传送的. HttpServletRequest类 r ...

  3. JavaWeb之Servlet:请求 与 响应

    1 引入 浏览器和服务器的种类都有很多,要在它们之间通讯,必定要遵循一定的准则,而http协议就是这样的一个"准则". Http协议:规定了 浏览器 和 服务器 数据传输的一种格式 ...

  4. J2EE请求和响应—Servlet

    一.什么是Servlet? Servlet是执行Webserver上的一个特殊Java类.其特殊用途是响应client请求并做出处理.使得client与server端进行交互. 二.生命周期  Ser ...

  5. 【Servlet与JSP】请求转发与重定向

    假设一个登录系统,要求用户输入用户名和密码: 用户在上面表单当中输入了信息之后,点击登录按钮(type="submit")将表单作为请求参数进行提交. 这一提交就有两种形式:get ...

  6. JSP学习之请求和响应编码

    今天的学习涉及到了 jsp中的两大函数 request(请求) 和 response(响应),这应该是大家学习jsp时最先碰到的两个对象,具体有什么作用呢?应该怎么用呢?请继续往下面看. 一.requ ...

  7. Java Servlet (1) —— Filter过滤请求与响应

    Java Servlet (1) -- Filter过滤请求与响应 版本: Java EE 6 参考来源: Oracle:The Java EE 6 Tutorial: Filtering Reque ...

  8. 对Servlet请求或响应进行JMockit测试

    对Servlet请求及响应进行mock方法, 通过getMockInstance方法对servlet进行打桩,对servlet提供的方法进行mock,替代真正的servlet请求或响应. 参考链接: ...

  9. Servlet请求和响应

    在Java Web中Servlet.请求和响应是最基本的三个对象,在Web容器的管理下,这三者能够完成基本的HTTP请求处理. Servlet的作用是为客户提供服务.servlet的角色是接受一个客户 ...

随机推荐

  1. Rust: lifetime

    Rust的lifetime算是它最重要的特性之一,也不大好理解,特别是官方文档的介绍有些太过简略,容易让人误解. 这篇文章: Rust Lifetimes 应该可以解答很多人疑惑,特别是有关lifet ...

  2. Unity3D研究院之LZMA压缩文件与解压文件

    原地址:http://www.xuanyusong.com/archives/3095 前两天有朋友告诉我Unity的Assetbundle是LZMA压缩的,刚好今天有时间那么就研究研究LZMA.它是 ...

  3. Sqli-labs less 38

    Less-38 学习了关于stacked injection的相关知识,我们在本关可以得到直接的运用. 在执行select时的sql语句为:SELECT * FROM users WHERE id=' ...

  4. PHP 性能分析与实验——性能的宏观分析

    [编者按]此前,阅读过了很多关于 PHP 性能分析的文章,不过写的都是一条一条的规则,而且,这些规则并没有上下文,也没有明确的实验来体现出这些规则的优势,同时讨论的也侧重于一些语法要点.本文就改变 P ...

  5. iOS多线程的初步研究(四)-- NSTimer

    理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NSTimer *)timerWit ...

  6. java基础知识回顾之抽象类

    /* 抽象类: 抽象:笼统,模糊,看不懂!不具体. 特点: 1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰. 抽象方法必须定义在抽象类中.该类必须也被abstract修饰. ...

  7. 机器学习之多变量线性回归(Linear Regression with multiple variables)

    1. Multiple features(多维特征) 在机器学习之单变量线性回归(Linear Regression with One Variable)我们提到过的线性回归中,我们只有一个单一特征量 ...

  8. Good Bye 2014 D. New Year Santa Network 图论+期望

    D. New Year Santa Network   New Year is coming in Tree World! In this world, as the name implies, th ...

  9. 测试in和or的执行时间

    declare @d datetime set @d=getdate() /*你的SQL脚本开始*/ SELECT * FROM T_KNOWLEDGE WHERE KNOWLEDGE_TYPE_OI ...

  10. lintcode:寻找旋转排序数组中的最小值 II

    寻找旋转排序数组中的最小值 II 假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2). 你需要找到其中最小的元素. 数组中可能存在重复的元 ...