1、Servlet概述
1.1、什么是servlet
servlet是JavaWeb的三大组件之一,属于动态资源,用于处理请求。
通常需要完成以下三个步骤:接收请求数据、处理请求和完成响应
Servlet 执行以下主要任务:
- 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
- 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
- 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
- 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
- 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
1.2、实现servlet 的方式
- 实现javax.serlvet.Servlet接口
- 继承javax.serlvet.GenericServlet类
- 继承javax.serlvet.http.HttpServlet类**(一般使用这个)**
Servlet 本身不能独立运行,需要在一个web应用中运行的,而一个web应用是部署在tomcat中的
所以开发一个servlet需要如下几个步骤
- 创建web应用项目
- 编写servlet代码
- 部署到tomcat中,
1.3、Servlet 架构
下图显示了 Servlet 在 Web 应用程序中的位置。
2、Servlet 生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。有3个生命周期方法,以下是 Servlet 遵循的过程:
- Servlet 通过调用 init (ServletConfig servletConfig) 方法进行初始化,只执行一次,由Tomcat调用
- Servlet 调用 service(ServletRequest request,ServletResponse response) 方法来处理客户端的请求,每次请求都被调用
- Servlet 通过调用 destroy() 方法终止(结束),服务器关闭时执行一次
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
init(ServletConfig)方法在Tomcat调用时是带参的,覆写时要覆写的方法是不带参的init()方法
特点:
- 单例,一个类只有一个对象,可以有多个类
- 线程不安全
2.1、三个生命周期方法
init() 方法
init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。
当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
init 方法的定义如下:
public void init() throws ServletException {
// 初始化代码...
}
service() 方法
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。。
下面是该方法的特征:
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException{
}
destroy() 方法
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:
public void destroy() {
// 终止化代码...
}
2.2、HttpServlet接口
- service(ServletRequest request,ServletResponse response);
这个是生命周期方法 - service(HttpServletRequest request,HttpServletResponse response);
这个是HttpServlet内的方法,包含更多对Http协议的相关操作,
客户端启动时会调用第一个service方法即生命周期方法,然后对参数进行类型转换,转换成第二个service方法的参数类型,在第二个方法中获取请求方法,判断是Get请求还是Post请求,根据请求方式调用doGet()或doPost方法(),这两个方法需要我们覆写,如果没覆写,会出现405错误
service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法.
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。
doGet() 方法
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
doPost() 方法
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
在服务器启动时创建Servlet
在web-xml配置时,加入<load-on-startup>0</load-on-startup>,参数为非负整数,有多个Servlet时,创建顺序由参数从小到大排序。
<servlet>
<servlet-name>aa</servlet-name>
<servlet-class>com.test.AServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
2.3、ServletContext
一个项目只有一个ServletContext对象,常命名为application
通过getServletContext()方法获得
域对象的功能
JavaWeb有四个域对象
- PageContext
- ServletContext
- HttpSession
- ServletRequest
域对象具有存数据和取数据的功能,域对象内部有一个Map
操作域对象的方法
- void setAttribute(String name,Object value)
- servletContext. setAttribute(“name”,“vaule”)多次调用,值会被覆盖
- Object getAttribute(String name)取属性值
- void removeAttribute(String name)移除
- Enumeration getAttribute();获取所有域属性的名称
ServletContext获取公共初始化参数
web.xml中加入标签<context-param
<context-param>
<param-name>param</param-name>
<param-value>value</param-value>
</context-param>
获取真实路径
getRealPath();
String path = this.getServletContext().getRealPath("/index.jsp");
真实路径是指带盘符的本机路径
3、服务器请求流程
- 服务器每次收到请求,都会为这个请求开启一个新的线程
- 服务器将客户端的请求数据封装到request对象中,request是请求数据的载体
- 服务器创建response对象,这个对象和客户端连接到一起,它可以用来向客户端发送响应
3.1、Response
- 3.1.1、状态码
200表示成功、302表示重定向、4开头客户端出错、5开头服务器出错- sendError(int sc);发送错误状态码,
- sendError(int sc,String msg);发送错误状态码,带错误信息
- setStatus(int sc);发送成功状态码,或者发送302重定向
- 3.1.2、响应头
常见响应头:Content-Type、Refresh、Location等- setHeader(String name, String value);
- 302重定向需要设置location头:setHeader(“Location”,“项目名/AServlet”),另一种快捷重定向方法,response.sendRedirect("/项目路径/AServlet")
- 定时5秒刷新:setHeader(“Refresh”,“5;URL=/项目名/AServlet”)
- 禁用浏览器缓存:
- setHeader(“Cache-Control”,“no-cache”);
- setHeader(“pragma”,“no-cache”);
- setHeader(“expires”,-1)
- setHeader(String name, String value);
- 3.1.3、响应体
通常是html,也可以是图片
response有两个流- ServletOutputStream,向客户端发送字节数据
- PrintWriter,向客户端发送字符数据,需要设置编码
- 两个流不能同时使用
读取图片案例
String path = "图片路径";
FileInputStream in = new FileInputStream(path);
byte[] bytes =IOUtils.toByteArray(in);
Response.getOutputStream().write(bytes);
3.2、Request
封装了客户端所有的请求数据
-
3.2.1、获取常用信息
- 获取客户端IP:getRemoteAddr()
- 获取请求方式:getMethod()
-
3.2.2、获取HTTP请求头
getHeader(String name)
-
3.2.3、获取请求URL
- getScheme():获取协议
- getServerName():获取服务器名
- getServerPort():获取服务器端口
- getContextPath():获取项目名
- getServletPath():获取servlet路径
- getQueryString():获取参数部分,即问号后面部分
- getRequestURI():获取请求URI,即项目名+Servlet路径
- getRequestURL():获取请求URL,即不包含参数的整个路径名
-
3.2.4、获取请求参数
-geteParameter(String name)
:获取指定名称的请求参数值 -
3.2.5、请求转发和请求包含
一个请求需要多个Servlet协作完成,需完成Servlet间的跳转。
只有一个request请求和一个response响应
请求转发:下一个Servlet完成响应体,当前Servlet只可设置响应头(留头不留体)只保留http头,http响应体不保留request.getRequestDispatcher("/下一个Servlet").forward(request,response)
请求包含:Servlet设置的响应头和响应体都会被保留(留头留体)保留http协议头和响应体
request.getRequestDispatcher("/下一个Servlet").include(request,response)