JavaWeb - Servlet:重定向和转发,状态管理

Servlet + JDBC 应用

在 Servlet 中可以使用 JDBC 技术访问数据库,常见功能如下:

  • 查询 DB 数据,然后生成显示页面,例如:列表显示功能。
  • 接收请求参数,然后对 DB 操作,例如:注册、登录、修改密码等功能。

为了方便重用和便于维护等目的,经常会采用 DAO(Data Access Object)模式对数据库操作进行独立封装。

DAO 工厂(工厂模式):工厂类封装了对象的创建细节,为调用者提供符合要求的对象。

重定向和转发

重定向的概述
概念

首先客户浏览器发送 http 请求,当 web 服务器接受后发送 302 状态码响应及对应新的 location 给客户浏览器,客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求 url 是新的 location 地址,服务器根据此请求寻找资源并发送给客户。

实现

实现重定向需要借助 javax.servlet.http.HttpServletResponse 接口中的方法:

void sendRedirect(String location) 使用指定的重定向位置 URL 向客户端发送临时重定向响应

原理

当执行添加页面功能时,浏览器发送 add.do 请求给 Tomcat 服务器;

Tomcat 服务器的 AddServlet 收到 add.do 请求后,先访问数据库 DB 执行插入新数据的操作,然后发送 302 状态码及重定向的新地址 Location: list.do 信息到浏览器;

浏览器根据新地址发送 list.do 请求给 Tomcat 服务器;

Tomcat 服务器的 ListServlet 收到 list.do 请求后,先访问数据库 DB 获取 list 数据,然后发送 200 状态码及 list 数据到浏览器;

浏览器根据 list 数据展示页面。

特点

重定向之后,浏览器地址栏的 URL 会发生改变。

重定向过程中会将前面 Request 对象销毁,然后创建一个新的 Request 对象。

重定向的 URL 可以是其它项目工程。

转发的概述
转发的概念

一个 Web 组件(Servlet/JSP)将未完成的处理通过容器转交给另外一个 Web 组件继续处理,转发的各个组件会共享 Request 和 Response 对象。

转发的实现
  • 绑定数据到 Request 对象

Object getAttribute(String name) 将指定属性值作为对象返回,若给定名称属性不存在,则返回空值

void setAttribute(String name,Object o) 在此请求中存储属性值

  • 获取转发器对象

RequestDispatcher getRequestDispatcher(String path) 返回一个 RequestDispatcher 对象,该对象充当位于给定路径上的资源的包装器

  • 转发操作

void forward(ServletRequest request, ServletResponse response) 将请求从一个 servlet 转发到服务器上的另一个资源(Servlet、JSP文件或HTML文件)

转发的特点

转发之后浏览器地址栏的 URL 不会发生改变。

转发过程中共享 Request 对象。

转发的 URL 不可以是其它项目工程。

重定向和转发的比较
  1. 重定向访问服务器两次,转发只访问服务器一次。
  2. 转发页面的 URL 不会改变,而重定向地址会改变。
  3. 转发只能转发到自己的 web 应用内,重定向可以重定义到任意资源路径。
  4. 转发过程中共享 request 对象;而重定向会产生一个新的 request,不能共享 request 域信息与请求参数。
  5. 转发相当于服务器内部方法调用,转发后面的代码仍然会执行;而重定向操作是方法执行完成之后才进行。
  6. 无论是 RequestDispatcher.forward 方法,还是 HttpServletResponse.sendRedirect 方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中移除。

Servlet 线程安全

服务器在收到请求之后,会启动一个线程来进行相应的请求处理。

默认情况下,服务器为每个 Servlet 只创建一个对象实例。当多个请求访问同一个 Servlet 时,会有多个线程访问同一个 Servlet 对象,此时就可能发生线程安全问题。

多线程并发逻辑,需要使用 synchronized 对代码加锁处理,但尽量避免使用。

状态管理

Web 程序基于 HTTP 协议通信,而 HTTP 协议是”无状态”的协议,一旦服务器响应完客户的请求之后,就断开连接,而同一个客户的下一次请求又会重新建立网络连接。

服务器程序有时是需要判断是否为同一个客户发出的请求,比如客户的多次选购商品。因此,有必要跟踪同一个客户发出的一系列请求。

把浏览器与服务器之间多次交互作为一个整体,将多次交互所涉及的数据保存下来,即状态管理。

多次交互的数据状态可以在客户端保存,也可以在服务器端保存。

状态管理主要分为两类:

  • 客户端管理 - 将状态保存在客户端。基于 Cookie 技术实现。
  • 服务器管理 - 将状态保存在服务器端。基于 Session 技术实现。

Cookie 技术

基本概念

Cookie 表示客户端以“名-值”形式进行保存的一种技术。

浏览器向服务器发送请求时,服务器将数据以 Set-Cookie 消息头的方式响应给浏览器,然后浏览器会将这些数据以文本文件的方式保存起来。

当浏览器再次访问服务器时,会将这些数据以 Cookie 消息头的方式发送给服务器。

相关的方法
  • 使用 javax.servlet.http.Cookie 类的构造方法实现 Cookie 的创建。

Cookie(String name, String value) 根据参数指定数值构造对象

  • 使用 javax.servlet.http.HttpServletResponse 接口的成员方法实现 Cookie 的添加。

void addCookie(Cookie cookie) 添加参数指定的对象到响应

  • 使用 javax.servlet.http.HttpServletRequest 接口的成员方法实现 Cookie 对象的获取。

Cookie[] getCookies() 返回此请求中包含的所有 Cookie 对象

  • 使用 javax.servlet.http.Cookie 类的构造方法实现 Cookie 对象中属性的获取和修改。

String getName() 返回此 Cookie 对象中的名字

String getValue() 返回此 Cookie 对象的数值

void setValue(String newValue) 设置 Cookie 的数值

Cookie 的生命周期
  • 默认情况下,浏览器会将 Cookie 信息保存在内存中,只要浏览器关闭,Cookie 信息就会消失。

  • 如果希望关闭浏览器后 Cookie 信息仍有效,可以通过 Cookie 类的成员方法实现。

int getMaxAge() 返回cookie的最长使用期限(以秒为单位)

void setMaxAge(int expiry) 设置cookie的最长保留时间(秒)

Cookie 的路径问题
  • 浏览器在访问服务器时,会比较 Cookie 的路径与请求路径是否匹配,只有匹配的 Cookie 才会发送给服务器。
  • Cookie 的默认路径等于添加这个 Cookie 信息时的组件路径,例如:/项目名/目录/add.do 请求添加了一个 Cookie 信息,则该 Cookie 的路径是 /项目名/目录
  • 访问的请求地址必须符合 Cookie 的路径或者其子路径时,浏览器才会发送 Cookie 信息。如果访问请求地址为 项目名/test.html,则路径为 项目名 的 Cookie 信息会被发送到服务器;如果访问请求地址为 项目名/目录/test.html,则路径为 项目名项目名/目录 的 Cookie 信息会被发送到服务器。

void setPath(String uri) 设置 Cookie 的路径信息

Cookie 的特点

Cookie 技术不适合存储所有数据,程序员只用于存储少量、非敏感信息,原因如下:

  • 将状态数据保存在浏览器端,不安全
  • 保存数据量有限制,大约 4 KB 左右
  • 只能保存字符串信息
  • 可以通过浏览器设置为禁止使用

Session 技术

基本概念

Session 是用来维护一个客户端和服务器关联的一种技术。

浏览器访问服务器时,服务器会为每一个浏览器都在服务器端的内存中分配一个空间,用于创建一个 Session 对象,该对象有一个 id 属性且该值唯一,我们称为 SessionId,并且服务器会将这个 SessionId 以 Cookie 方式发送给浏览器存储。

浏览器再次访问服务器时会将 SessionId 发送给服务器,服务器可以依据 SessionId 查找相对应的 Session 对象。

相关的方法
  • 使用 javax.servlet.http.HttpServletRequest 接口的成员方法实现 Session 的获取。

HttpSession getSession() 返回此请求关联的当前 Session,若此请求没有则创建一个

  • 使用 javax.servlet.http.HttpSession 接口的成员方法实现判断和获取。

boolean isNew() 判断是否为新创建的 Session

String getId() 获取 Session 的编号

  • 使用 javax.servlet.http.HttpSession 接口的成员方法实现属性的管理。

Object getAttribute(String name) 返回在此会话中用指定名称绑定的对象,如果没有对象在该名称下绑定,则返回空值

void setAttribute(String name, Object value) 使用指定的名称将对象绑定到此会话

void removeAttribute(String name) 从此会话中删除与指定名称绑定的对象

Session 的生命周期
  • 为了节省服务器内存空间资源,服务器会将空闲时间过长的 Session 对象自动清除掉,服务器默认的超时限制一般是 30 分钟。
  • 使用 javax.servlet.http.HttpSession 接口的成员方法实现失效实现的获取和设置。

int getMaxInactiveInterval() 获取失效时间

void setMaxInactiveInterval(int interval) 设置失效时间

  • 可以配置 web.xml 文件修改失效时间。
<session-config>
    <session-timeout>30session-timeout>
session-config>
Session 的特点

数据比较安全。

能够保存的数据类型丰富,而 Cookie 只能保存字符串。

能够保存更多的数据,而 Cookie 大约保存 4 KB。

数据保存在服务器端会占用服务器的内存空间,如果存储信息过多、用户量过大,会严重影响服务器的性能。

想了解更多,欢迎关注我的微信公众号:Renda_Zhang

你可能感兴趣的:(软件开发,java,servlet,tomcat)