本篇文章将会介绍Servlet组件与她的工作流程、生命周期、Request/Response等核心对象。
首先用自己的大白话说说自己对Servlet的理解,Servlet是存在于Web服务器中的组件,可以处理用户在自己浏览器上发往服务器的请求,然后处理请求返回用户需要的结果数据,从数据库查询来的数据显示到页面上,而这类显示动态数据的页面称为jsp页面,jsp页面与Servlet配合使用,满足用户的一切需求。
下图是客户端与服务器交互的流程:
Servlet的三种创建方式
- 创建类实现Servlet接口
- 创建类,继承HttpServlet类
- 使用IDE直接创建servlet,并注册servlet
servlet两种注册方式
- 在项目版本3.0+ 可以使用@WebServlet("/×××")注解注册
- 在项目版本3.0- 可以在web.xml中配置< servlet >注册
servlet生命周期
- 实例化Servlet—初始化操作—服务—返回结果数据—销毁—回收
- servlet实例化(servlet为单例模式)
情况1:第一次请求Servlet时 ,进行实例化操作
情况2:服务器启动时,进行实例化操作
在配置文件web.xml中为servlet添加<load-on-startup>
可设置servlet实例化优先级,数值越小优先级越高,形如:
<servlet>
<servlet-name>LifeServlet</servlet-name>
<servlet-class>cn.hp.servlet.LifeServlet</servlet-class>
<init-param>
<param-name>password</param-name>
<param-value>123</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
-
servlet初始化
初始化紧随实例化操作,只执行一次,自动调用init()方法 -
servlet处理请求
自动回调service方法,传递两个对象HttpServletRequest与HttpServletRespose,service()方法接受用户请求,处理响应结果
方式一:重写service()
方式二:重写doGet()/doPost()方法 -
servlet销毁
自动回调destroy()方法,自动释放当前Servlet所占用的资源,当前应用被终止、被从服务器移除、服务器停止时触发destroy()
Servlet中的核心接口
1. HTTPServletRequest
Request对象封装了请求数据包中的所有数据,一般用于获取从客户端传来的数据。生命周期为一次请求,请求转发的情况也认定为是一次请求,因为请求转发是将request与response对象传给另一个servlet去处理。
获取请求数据方法:
- String value = request.getParameter(String key);
- String[] value = request.getParameterValues(String key);
- Map<String,String[]> map = request.getParameterMap();
常用方法:
方法 | 作用 |
---|---|
Cookie[] getCookies() | 请求的所有的 Cookie 对象,返回一个cookie数组 |
HttpSession getSession() | 返回与该请求关联的当前 session 会话 |
String getContextPath() | 返回指示请求上下文的请求 URI 部分 |
String getMethod() | 返回请求的 HTTP 方法,get或post方法 |
String getQueryString() | 返回包含在路径后的请求 URL 中的查询字符串 |
String getRemoteAddr() | 返回发送请求客户端的IP地址 |
请求转发:
- 获取请求转发器对象
RequestDispatcher rd = getRequestDispathcher(String path);
- 调用转发方法
rd.forward(HttpServletRequest,HttpServletResponse);
或者直接request.getRequestDispatcher("path").forward(request, response);
2. HttpServletResponse
response对象用于封装响应结果数据包中的内容,可以封装cookie对象,设置响应码,添加响应头、响应体;单纯进行servlet开发不用jsp页面的话,response也可以输出并拼接页面,jsp的底层就是用servlet拼接页面;可以进行页面的重定向,下文会介绍请求转发与重定向的流程与区别。
常用方法:
方法 | 作用 |
---|---|
void addCookie(Cookie cookie) | 把指定的 cookie 添加到响应 |
void setStatus(int statu) | 为该响应设置状态码 |
void setHeader(String name, String value) | 设置一个带有给定的名称和值的响应报头 |
void addHeader(String name, String value) | 添加一个带有给定的名称和值的响应报头 |
void sendRedirect(String location) | 使用指定的重定向位置 URL 发送临时重定向响应到客户端 |
printWriter getWriter() | 获取字符数据输出流 |
ServletOutputStream getOutputStream() | 获取字节数据输出流 |
请求的重定向:
一般使用response.sendRedirect("新的Servlet地址");
,重定向与转发不一样,转发是将request与response俩对象传给另一个servlet去处理,客户端中的url不会改变;而重定向顾名思义,重新给定一个方向去让客户端访问,不存在带着request中set的任何参数传递的情况,客户端会访问服务器多次,url也会随之改变;下面用图来说明:
3. HttpSession
session对象的作用范围是一个会话,可以理解为用户从打开浏览器访问一个服务器开始,到关闭浏览器结束,一个会话可能包含多次请求,针对一个用户,session中set的参数可以在会话范围内使用,作用范围比request对象大;在实际中,session可以记录用户登录的数据,例如一个用户未登录就想访问主页面,在servlet中可以判断session信息,让用户重定向去登录页面。
常用方法:
方法 | 作用 |
---|---|
public Object getAttribute(String name) | 返回在 session 会话中具有指定名称的对象,没有就返回null |
public void setAttribute(String name, Object value) | 该方法使用指定的名称绑定一个对象到该 session 会话 |
public boolean isNew() | 判断该 session 是否为新的 |
以下是登录成功进入主页面失败再次登录的小案例:
//该方法属于登录servlet类
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
HttpSession session = request.getSession();
Map<String, String[]> map = request.getParameterMap();
String userName = map.get("userName")[0];
String password = map.get("password")[0];
if (dao.login(userName, password) < 0) {
//登录失败
request.getRequestDispatcher("/page/login.jsp").forward(request, response);
} else {
//登录成功
session.setAttribute("userName", userName);
response.sendRedirect("/DynamicWebProject_AnimalManager_v3/animals?type=list");
}
}
//该方法属于主页面的servlet类
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
HttpSession session = request.getSession();
if (session.getAttribute("userName") == null) {
response.sendRedirect("/DynamicWebProject_AnimalManager_v3/page/login.jsp");
} else {
//业务代码
}
}
4. ServletContext
该对象是当前web项目的环境对象(上下文对象),一个web项目对应一个上下文对象,可以理解为是一个全局对象,作用范围从服务器启动、项目部署开始,到项目被移除或是服务器关闭,该对象可以储存全局变量,例如可以统计一个网站的访问量。
获取ServletContext
ServletContext context = this.getServletContext() //this表示某个servlet实例;
ServletContext context = config.getServletContext();
功能
- 获取web应用的全局初始化参数
String username = context.getInitParameter("username");
<context-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</context-param>
-
存储全局数据
getAttribute()
setAttribute() -
获取web应用中任何资源的绝对路径(针对当前项目的部署环境)
String realPath = context.getRealPath("/");
5. ServletConfig
该对象描述当前Servlet本身的相关配置信息、
获取
ServletConfig config = this.getServletConfig();
String value = config.getInitParameter(String key);
功能
获取当前Servlet再web.xml中的初始化数据:
<servlet>
<init-param>
<param-name>name</param-name>
<param-value>zhangsan</param-value>
</init-param>
</servlet>
Get/Post请求方式和乱码处理
-
请求数据乱码:
页面编码:<meta charset="utf-8">
get请求:String username = new String(username.getBytes("iso-8859-1"),"utf-8");
post请求:request.setCharacterEncoding("utf-8");
-
响应结果数据乱码:
html页面数据:response.setContentType(type);
纯文本数据:response.setCharacterEncoding(charset);