Servlet 基本概念

一、基本概念

Web客户(浏览器):允许用户请求服务器上的某个资源,并向用户显示请求结果

Web服务器:接收客户请求,然后向客户返回一些结果

HTML:告诉浏览器怎样把内容呈现给用户

HTTP:Web客户与服务器通信所用的协议


二、HTTP 请求

1. GETPOST 的区别

GET:从服务器拿些东西回来

  • 总字符数是有限的
  • 发送的数据会追加到 URL 的后面,在浏览器地址栏中显示出来,所以你发送的数据会完全暴露
  • 使用 ? 将路径和参数分隔,各个参数之间用 & 分隔
  • 资源的路径以及增加到URL的所有参数都会包含在请求行中
    ,不安全
  • 幂等
请求行:
GET /select/selectColor.jsp?color=black HTTP/1.1
请求首部:
...

POST:可以请求某些东西,与此同时向服务器发送一些表单数据
这些数据称为 消息体 或 负载

  • POST有一个体
  • 非幂等
请求行:
POST /advisor/selectColer.do HTTP/1.1
请求首部:
...
Accept: text/html,text/xml
...
消息体/负载:
color=black

2. 幂等与非幂等

幂等:同一个请求可以做两次,而不会对服务器产生负面作用

幂等方法GETPUTDELETEHEADOPTIONS

非幂等方法POST(重复提交同一个 POST 请求,可能会创建多个资源。例如,重复提交订单会生成多个订单)


三、HTTP 响应

HTTP响应首部:告诉浏览器使用了什么协议,请求是否成功,以及体中包括何种类型的内容

:包含了让浏览器显示的具体内容

响应首部:
web服务器使用的协议版本 响应的HTTP状态码 状态码的相应文本
HTTP/1.1 200 OK
...
Content-Type: text/html
...
体:
<html>
...
</html>
  • content-type(内容类型)响应首部的值称为 MIME 类型

  • MIME 类型告诉浏览器要接收的数据是什么类型,这样浏览器才能知道如何显示这些数据

  • MIME 类型值与 HTTP 请求首部中 Accept 所列的值有关


四、执行流程

1. Web服务器主机中的三个应用

  • Web 服务器应用(Nginx、Apache):只提供静态页面
  • 辅助应用(Servlet):生成非静态的及时页面,Web 服务器会把参数移交给 Servlet,由Servlet 为客户生成一个响应
  • Web容器应用(Tomcat、Jetty):服务器不是把请求交给 servlet 本身,而是交给部署该 servlet 的容器,要这个容器向 servlet 提供 HTTP 请求和响应,而且要由容器调用 servlet 的方法
web浏览器->web服务器主机[web服务器应用->web容器应用->servlet]

2. Web 容器应用

Web容器应用:管理和运行 servlet

  • 通信支持:无需自己实现连接
  • 生命周期管理:控制servlet的生命周期,不用太多地考虑资源管理
  • 多线程支持:容器会自动地为它接收的每个servlet请求创建一个新的Java线程

3. 请求的执行流程:

  1. 用户点击一个连接,其 URL 指向一个 servlet 而不是一个静态页面
  2. 容器发现这个请求要的是一个 servlet,会创建两个对象:
    • HttpServletRequest
      • 可以得到首部、cookie、会话等
    • HttpServletResponse
      • 可以设置contentType、得到输出流、设置首部、cookie、状态等
  3. 容器根据请求中的 URL 找到正确的 servlet,为这个请求创建或分配一个线程(每个客户的每个请求都在单独的线程中运行,任何时刻有多少客户请求就至少有多少并发的线程,线程的数量受容器的约束,当客户请求数量超过上限时,有些客户就必须等待),并把请求对象和响应对象(每个客户的每个请求都有自己的)传递给这个 servlet 线程
  4. 容器调用 servlet 的 service() 方法。service() 方法会根据请求的不同类型调用 doGet() 或 doPost() 方法
  5. doGet() 方法生成动态页面,并把这个页面填入响应对象
  6. 线程结束,容器把响应对象转换为一个 HTTP 响应,把它返回给客户,然后删除请求对象和响应对象

五、会话管理

1. HttpSession

[相同的客户、相同的 servlet、不同的请求、不同的线程]->相同的会话

HTTP 协议使用的是无状态连接,对于容器而言,每个请求都来自于一个新用户

对客户的第一个请求,容器会生成一个唯一的会话 ID,并通过响应把它返回给客户。

客户再以后的每一个请求中发回这个会话 ID。容器看到 ID 后,就会找到匹配的会话,并把这个会话与请求关联

2. Cookie

ID -> cookie
HTTP响应
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=0AAB6C8DE415
...

HTTP请求
POST /select/selectColor.do HTTP/1.1
Cookie: JSESSIONID=0AAB6C8DE415
...

容器几乎会做 cookie 的所有工作

  • 在响应中发送一个会话 cookie:HttpSession session = request.getSession();
    • 即在服务方法中请求一个会话,余下的所有事情都会自动完成
    • 你不用自己建立新的HttpSession对象
    • 你不必生成唯一的会话ID
    • 你不用自己建立新的Cookie对象
    • 你不用把会话ID与cookie关联
    • 你不用在响应中设置Cookie
  • 从请求得到会话ID:HttpSession session = request.getSession()
IF(请求包含一个会话ID cookie)
  找到与该ID匹配的会话
ELSE IF(没有会话ID cookie OR 没有与此会话 ID 匹配的当前会话)
  创建一个新的会话

如果只想要一个已经有的会话呢?

  • 可以调用getSession(false),调用这个方法要么得到null,要么得到一个已经有的HttpSession

如果客户禁用cookie怎么办?

  • 禁用cookie的客户会忽略 Set-Cookie 响应首部
  • 可以进行URL重写:URL + ;jsessionid=1234567

cookie实际上就是在客户端和服务器之间的一小段数据(一个名/值String对)

  • 可以通过Servlet API 定制Cookie
    • HttpServletRequest
    • HttpServletResponse
    • Cookie
// 创建和设置cookie
Cookie cookie = new Cookie("username", name)
cookie.setMaxAge(30*60); // 在客户端上存活30分钟
response.addCookie(cookie);

五、会话迁移

在一个集群环境中,容器可能会完成负载平衡,取得客户的请求,把请求发送到多个JVM上,这就意味者每次客户请求时,最后有可能到达一个servlet的不同实例

每个VM中有一个ServletContext,每个VM上的每个servlet有一个ServletConfig。但是对于每个Web应用的一个给定的会话ID,只有一个HttpSession对象,而不论应用分布在多少个VM上

在任何时刻,会话只存在于一个位置,对于一个给定的Web应用,相同的会话ID不会出现在两个VM中

[VM1 钝化] -- 迁移 --> [VM2 激活]
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐