Servlet

概念

Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广 义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

  • Servlet 对象是由 Tomcat 来进行实例化的,并且在实例化完毕之后调用 init 方法(只调用一次
  • Tomcat 对于收到的请求,都会通过对应的 Servlet 的 service 方法来进行处理(可以调用多次
  • Tomcat 在结束之前,会调用 Servlet 的 destory 方法来进行回收资源(最多调用一次

HttpServletRequest

方法 描述
String getProtocol() 返回协议的名称和版本号
String getMethod() 返回请求的 HTTP 方法的名称
String getRequestURL() 返回请求的 URL,不带查询字符串
String getRequestURI() 返回该请求的 URL 的一部分,不带协议名、端口号、查询字符串
String getContextPath() 返回指示请求 URL 中 Context Path 部分
String getServletPath() 返回指示请求 URL 中 ServletPath 部分
String getQueryString() 返回请求首行中 URL 后面的查询字符串
Enumeration getParameterNames() 返回一个 String 对象的枚举,包括在该请求中的参数的名称
String getParameter(String name) 以字符串形式返回请求参数的值,如果参数不存在则返回 null
String[] getParameterValues(String name) 返回一个字符串对象的数组,包括所有给定的请求的参数,如果参数不存在则返回 null
Enumeration getHeaderNames() 返回一个枚举,包括该请求中所有的头名
String getHeader(String name) 以字符串形式返回指定的请求头的值
String getCharacterEncoding() 返回请求正文中使用的字符编码的名称
String getContentType() 返回请求正文的 MIME 类型,如果不知道类型则返回 null
int getContentLength() 以字节为单位返回请求正文的长度,并提供输入流,如果长度未知则返回-1
InputStream getInputStream() 用于读取请求的正文内容,返回一个 InputStream 对象

HttpServletResponse

方法 描述
void setStatus(int sc) 为该响应设置状态码
void setHeader(String name, String value) 设置一个带有给定的名称和值的 header,如果 name 已经存在,则覆盖旧的值
void addHeader(String name, String value) 添加一个带有给定的名称和值的 header,如果 name
void setContentType(String type) 设置被发送到客户端的响应的内容类型
void setCharacterEncoding(String charset) 设置被发送到客户端的响应的字符编码,例如 utf-8
void sendRedirect(String location) 设置 Location 字段,实现重定向
PrintWriter getWriter() 用于往 body 中写入文本格式数据
OutputStream getOutputStream() 用于往 body 中写入二进制格式数据

Cookie

  • Cookie 是浏览器提供的在客户端存储数据的一种机制(由于浏览器禁止了网页中的代码直接访问本地磁盘的文件,因此想要在网页中实现持久化存储,就可以通过 Cookie 这样的机制)
  • Cookie 存储的数据都是程序员自定义的,存储的数据是一个字符串,是键值对结构的,键值对之间使用 ; 分割,键和值之间使用 = 分割
  • 服务器返回响应的时候,可以把要在客户端保存的数据以 Set-Cookie 这个 header 的方式返回给浏览器
  • 客户端下次访问服务器的时候,就会把之前保存好的 Cookie 再发送给服务器

注意:在了解 Cookie 以后,我们发现 Cookie 是不能够用于存储和用户相关的直接信息的,一是 Cookie 的存储容量有限,二是发送请求时占用带宽很多,三是不太安全。即这些数据不适合保存在客户端,保存在服务器是更合适的,通过会话(Session)的方式就能够保存这些数据。

方法

方法 描述
HttpServletRequest 类中的相关方法
HttpSession getSession(参数) 在服务器中获取会话,参数如果为 true,当不存在会话时会新建会话(包括生成一个新的 sessionId 和 HttpSession 对象),并通过 Set-Cookies 将 sessionId 返回给客户端;参数如果为 false,当不存在会话时会返回 null。如果存在 sessionId 且合法,就会根据这个 sessionId 找到对应的 HttpSession 对象并返回
Cookie[] getCookies() 返回一个数组,包含客户端发送请求时的所有 Cookie 对象,会自动把 Cookie 中的格式解析成键值对
HttpServletResponse 类中的相关方法
void addCookie(Cookie cookie) 把指定的 cookie 添加到响应中
Cookie 类中的相关方法
String getName() 该方法返回 cookie 的名称(这个值是 Set-Cookie 字段设置给浏览器的,创建之后不能改变)
String getValue() 该方法获取与 Cookie 关联的值
void setValue(String newValue) 该方法设置与 Cookie 关联的值

Session

在计算机中,尤其是在网络应用中,Session 称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。注意会话状态仅在支持 Cookie 的浏览器中保留。

本质

  • 会话的本质就是一个哈希表,其中存储了一些键值对结构,key 叫做 sessionId,是一个不随机的、不重复的、唯一的字符串,value 就是要保存的身份信息,通过 HttpSession 对象来保存。key 和 value 都是 Servlet 自动创建的。
  • 每个用户登录都会生成一个会话,服务器会以哈希表的方式将这些会话管理起来
  • 一个会话的详细数据通过一个 HttpSession 对象来存储,并且 HttpSession 对象中存储的数据也是键值对结构,key 和 value 都是程序员自定义的

好处

  • 使得客户端很轻量,不用保存太多数据
  • 客户端和服务器之间传输的数据量小,节省带宽
  • 数据都在服务器存储,即使客户端出现问题,数据也不会丢失
    注意: Servlet 的 Session 默认是保存在内存中的,如果重启服务器 Session 数据将会丢失

HttpSession 类中的相关方法

方法 描述
Object getAttribute(String name) 该方法返回在 Session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null
void setAttribute(String name, Object value) 该方法使用指定的名称绑定一个对象到该 Session 会话中
boolean isNew() 判定当前的会话是否是新创建的

案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" value="登录">
    </form>
</body>
</html>
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        // 1. 从请求中获取到用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 2. 对用户密码进行校验
        if(username == null || "".equals(username) || password == null || "".equals(password)){
            resp.getWriter().write("<h3>账号或密码不能为空!</h3>");
            return;
        }
        // 3. 判断是否登录成功(假设用户名为 admin,密码为 1234。不过账号密码应该用数据库存储,这里只是用来测试)
        if(!username.equals("admin") || !password.equals("1234")){
            resp.getWriter().write("<h3>账号或密码错误!</h3>");
            return;
        }
        // 4. 登录成功,创建一个会话,用来记录当前用户的信息
        HttpSession session = req.getSession(true);
        //    通过这个操作,就给会话中新增了一个程序员自定义的信息,访问次数
        session.setAttribute("visitCount", 0);
        // 5. 把登录成功的结果反馈给客户端(这里的反馈不是简单的提示“登录成功”,而是直接跳转到指定页面)
        resp.sendRedirect("index");
    }
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        // 只有登录成功参数才能是 true,这里是拿参数,所以要填 false
        HttpSession session = req.getSession(false);
        // 判断当前用户是否登录
        if(session == null){
            // 可以提示未登录,也可以重定向到登录页面
            // resp.getWriter().write("<h3>登录为空!</h3>");
            resp.sendRedirect("login2.html");
            return;
        }
        // 表示用户登录过,获取会话中的访问次数
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        visitCount += 1;
        session.setAttribute("visitCount", visitCount);
        resp.getWriter().write("<h3>visitCount = " + visitCount + "</h3>");
    }
}
posted @ 2025-03-19 22:24  LuoboWang  阅读(40)  评论(0)    收藏  举报