1.Serlvet概述
- Servlet 是一种独立于平台和协议的服务器端的 Java 应用,可以生成动态的 web页面。与传统的 CGI (计算机图形接口)和许多其他类似 CGI 技术相比,具有更好的可移植性、更强大的功能、更节省资源、效率更高、安全性更好及代码结构化等特点。
- Servlet 是使用 Java Servlet 应用程序设计按口(API) 及相关类和方法的 Java程序:除JavaServlet Api, 它还可以用于扩展和添加 API 的Java 类软件包。Java 语言能够实现的功能,Servlet基本上都能实现(除了图形界面外)。Servlet 主要用于处理客户端传来的 HTTP 请求,并返回一个响应。通常所说的 Servlet 就是指 HtDServlet, 用于处理 HTTP 请求,能够处理的请求有doGet()、doPost()和 service()等方法。在开发 Servlet 时,可以直接继承 iavax.servlet.http.HttpServlet.
2.Servlet的生命周期
- Servlet部署在容器(Tomcat等),生命周期由容器管理。
- Servlet的生命周期可概括为以下几个阶段:
(1)当Web客户请求Socket时或当Web应用启动时,容器环境加载一个Java Servlet类。
(2)容器环境将根据客服请求创建一个或多个Servlet对象实例时,并把这些实例加入到Servlet实例池中。
(3)容器环境调用 Servlet 的初始化方法 HttpServlet. initO完成初始化,这需要为 inito方法传入一个 ServletConfig 对象。其中包含初始化参数和容器环境的信息,并负责向 Servlet 传递数据。如果传递失败,则会发生 ServlerException 异常,Servlet 将不能正常工作。
(4)容器环境利用一个 HttpServletRequest 和 HttpServletResponse 对象封装从 Web 客户接收到的 HTTP 请求和由 Servlet 生成的响应
(5)容器环境把 HtpServletRequest 和 HttpServlet Response 对象传递给 HttpServlet.service()方法,这样一个定制的 Java Servlet 即可访问这种 HTTP 请求和响应接口。service0方法可被多次调用,各调用过程运行在不同的线程中互不干扰。
(6)定制的Java Servlet 从 HttpServletRequest 对象读取Http 请求数据,访问来自 HttpSession 或 Cookie 对象的状态信息,执行特定应用的处理并且用 HtpServletResponse 对象生成 HTTP 响应数据。
(7)当Web服务器和容器关闭时会自动调用 HttpServlet.destroy0方法关闭所有打开的资源,并执行些关闭前的处理。
Servlet 生命周期图示:
Servlet生命周期代码测试
package com.aqiang.serlvet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "userServlet")
public class UserServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
this.config = servletConfig;
ServletContext servletContext = servletConfig.getServletContext();
System.out.println("userServlet正在初始化");
}
@Override
public ServletConfig getServletConfig() {
return this.config;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("userServlet正在服务中");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<h1>你真棒,居然来看我的文章</h1>");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("userServlet正在销毁");
}
}
3.Servlet接口方法详解
(1)Servlet接口的方法声明及其说明
(2)进一步详解Servlet接口方法
- 首先我们先要了解上面代码的ServletConfig接口。
该接口的方法如下:
- 想要了解ServletConfig方法的作用前先要了解Servlet的配置。Servlet的配置可通过web工程的web.xml或注解 @WebServlet进行配置。
- 解析 web.xml配置
<servlet> <!--servlet的名字(标识此Servlet)--> <servlet-name>userServlet</servlet-name> <!--servlet的类路径--> <servlet-class>com.aqiang.serlvet.UserServlet</servlet-class> <!--单个servlet作用域--> <!--servlet初始化的参数--> <init-param> <param-name>technology</param-name> <param-value>webApplication</param-value> </init-param> </servlet> <!--与一个个的标签<servlet>对应--> <servlet-mapping> <!--与上面的servlet-name对应--> <servlet-name>userServlet</servlet-name> <!--配置servlet请求路径(可有多个,表示客服端请求多个url中的一个都映射到此servlet)--> <url-pattern>/userServlet1</url-pattern> <url-pattern>/userServlet</url-pattern> </servlet-mapping>
- 解析@WebServlet配置
(1)name() —><servlet-name>名称</servlet-name>
(2)initParams() —>多个<init-param></init-param>
(3)urlPatterns() —>多个<init-param> <param-name>technology</param-name> <param-value>webApplication</param-value> </init-param>
<urlpattern></urlpattern>
- 解析 web.xml配置
ServletConfig方法代码测试
package com.aqiang.serlvet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
@WebServlet(name = "userServlet")
public class UserServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
this.config = servletConfig;
ServletContext servletContext = servletConfig.getServletContext();
System.out.println("userServlet正在初始化");
String name = servletConfig.getServletName()
System.out.println("name = " + name);
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
String technology = servletConfig.getInitParameter("technology");
System.out.println("initParameterNames:" +Collections.list(initParameterNames));
System.out.println("technology = " + technology);
}
@Override
public ServletConfig getServletConfig() {
return this.config;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("userServlet正在服务中");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<h1>你真棒,居然来看我的文章</h1>");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("userServlet正在销毁");
}
}
运行结果:
4.Servlet的实现类GenericServlet和HttpServlet
- Servlet 和 ServletConfig是javax.servlet 包中定义的接口,这两个接口定义了 Servlet 的基本方法并封装了 Servlet 的相关配置信息。GenericServlet 是一个抽象类,分别实现上述的 3 个接口。此接口为 Servlet及 ServletConfig 接口提供了部分实现,但并没有实现 Http 请求处理。这一操作由其子类HttpServlet 实现,这个类为 Htp 请求中 POST、GET 等类型提供了具体的操作方法。
- 通常情况下,我们编写的 Servlet 类都继承于 HttpServlet,在开发中使用的具体的Servlet 对象就是 HttpServlet 对象。这是因为 HttpServlet 为 Servlet 做出实现,并提供了 Http 请求处理方法。
5.与HttpServlet相关的接口HttpServletRequest和HttpServletResponse
(1) 首先我们先来看看HttpServletRequest继承的接口ServletRequest
以上方法就不一一概述啦,以下是ServletRequest的常用方法。
- 编码方式有关方法
(1)getCharacterEncoding方法获取请求的编码方式
(2)setCharacterEncoding方法设置请求的编码方式(解决Post请求方式的请求参数乱码方式) - 请求参数有关方法
(3)getContentLength方法获取请求参数的长度
(4)getInputStream方法获取请求参数字节输入流
(5)getReader方法获取请求参数字符输入流
(6)getParameter方法根据参数名获取参数值
(7)getParameterMap方法根据参数名获取多个参数值(复选框)
(8)getParameterNames方法获取所有请求参数的名字 - 服务器和客服端ip和端口号的获取
(9)getRemoteAddr方法返回发出请求的客户机的IP地址。 (10)getRemoteHost方法返回发出请求的客户机的完整主机名。 (11)getRemotePort方法返回客户机所使用的网络端口号。 (12)getLocalAddr方法返回WEB服务器的IP地址。
(13)getLocalName方法返回WEB服务器的主机名。 - 作用域信息的获取以及存储信息的方法
(14)getAttribute方法在request作用域根据信息名获取对应的值
(15)setAttribute方法把信息名和对应的值放入request作用域
(16)getAttributesrNames方法获取所有作用域信息的名字 - web工程对象的获取
(17)getServletContext方法获取唯一的web工程对象
注:在启动个Web 应用时会为其创建一个 ServletContext 对象;当 Servlet 容器终止
Web 应用时,该对象也会被销毁。所以它与 web 应用程序有同样的生命周期,即整个Web 应用的组件可以共享 ServletContext对象中存放的共享数据。
再来查看HttpServletRequest接口定义的方法
以上方法就不一一概述啦,HttpServletRequest继承于ServletRequest接口,所以以上方法HttpServletRequest可调用。
以下是HttpServletRequest的常用方法。
- 请求状态信息的获取
(1)getMethod方法获取请求方式(Get,Post,Put)
(2)getHeader方法根据请求头名字获取请求头的值
(3)getHeaders方法根据请求头名字获取多个请求头的值(有些请求头含有多个值)
(4)getHeaderNames方法获取所有请求头的名字
(5)getCookies方法获取所有cookies - 请求地址的获取
(6)getRequestURL方法返回客户端发出请求时的完整URL。
(7)getRequestURI方法返回请求行中的资源名部分。
(8)getQueryString 方法返回请求行中的参数部分。
(9)getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
(10)getContextPath方法 获取应用程序包路径
例:请求地址:http://localhost:8084/api/getGoodsByType?typeId=1
String getServletPath(): 获取 Servlet 路径,/getGoodsByType
String getQueryString(): 获取请求地址携带的参数 typeId=1
String getRequestURI():获取请求资源路径 api/getGoodsByType
String getRequestURL():获取不带参数的全请求地址(浏览器输入的)
String getPathInfo():/getGoodsByType?typeId=1 - Session的获取
getSession方法获取当前会话,若不存在则创建一个
getSession(boolean create)方法获取当前会话,若为true和getSession作用一样,否则若不存在返回null
(2) 首先我们先来看看HttpServletResponse继承的接口ServletResponse
以下是ServletRequest的常用方法。
- 编码方式有关方法
(1)getCharacterEncoding方法获取响应的编码方式
(2)setCharacterEncoding方法设置响应的编码方式 - 响应体有关方法
(3)setContentLength方法设置响应体的长度
(4)setContentType方法设置响应体的格式
(5)getOutputStream方法获取响应体字节输出流
(6)getWriter方法获取响应体字符输出流
注:Content-Type 的常见 5 种类型(格式:Type/SubType;parameter)- text/html;charset=utf-8;
- application/www-form-urlencoding
解释: 请求参数用 key1=val1&key2=val2 的方式进行组织,并放到请求实体里面,注意如果是中文或特殊字符如 “/”、“,”、“:" 等会自动进行 URL 转码 - applicatino/json
解释: 参数 (数据) 会被直接放到请求实体里,不进行任何处理 - application/xml 和 text/xml
解释: application/xml 用的是 xml 编码格式的数据,text/xml 的话,将忽略 xml 数据里的编码格式 - mutipart/form-data
解释: 文件表单上传的格式
如果是文件导出,Content-Type 设置为 multipart/form-data,并且添加一个 Content-Disposition 设置为 attachment;fileName= 文件名。
注:Content-Disposition 是 Content-Type 的扩展,告诉浏览器弹窗下载框,而不是直接在浏览器里展示文件。因为一般浏览器对于它能够处理的文件类型,如 txt,pdf 等,它都是直接打开展示,而不是弹窗下载框。
再来查看HttpServletResponse接口定义的方法
HttpServletResponse继承于ServletResponse接口,所以以上方法HttpServletResponse可调用。
以下是HttpServletRequest的常用方法。
- 响应头的设置
(1)addHeader方法添加响应头信息
(2)setStatus方法添加响应码
(3)getHeader方法根据响应头名称获取响应头的值
(4)getHeaders方法根据响应头名称获取多个响应头的值(有些响应头含有多个值)
(5)getHeaderNames方法获取所有响应头的名字
(6)addCookie方法响应体中添加cookies - 重定向到其他页面
(7)sendRedirect方法跳转指定的url页面上
(8)sendError方法跳转带状态码和内容的错误页面上
6.再来看一下浏览器请求和服务器响应的过程吧
小结:
Servlet处理流程:当客户端(浏览器)发送一个请求时,web 容器将创建与客户端相对应的处理ServletRequest 与 ServletResponse 对象。在创建之后,Web 容器调用与请求相关的 HtpServlet 处理请求,HtpServlet 判断Http请求类型。若客户端发送的是一个GET (Post)类型的请求,所以 HttpServlet将调用doGet方法(doPost方法)处理请求。在处理过程中,HttpServlet 会调用 ServletRequest 对象获取客户端中的请求参数,处理完成后调用 Servle Response 对象通知 Web 容器回应客户端。并且 Web 容器将销毁 ServletRequest 与ServletResponse 对象,然后回应客户端,这就是 Servelet 处理 一次请求的流程