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>");
}
}

浙公网安备 33010602011771号