未读代码 未读代码
首页
  • Java 18 新功能介绍
  • Java 17 新功能介绍
  • Java 16 新功能介绍
  • Java 15 新功能介绍
  • Java 14 新功能介绍
  • Java 8 新特性

    • Java 8 Lambda 表达式
    • Java 8 Stream 流式操作
    • Java 8 时间处理介绍
    • Java 8 Optional 介绍
  • Java 开发工具
Java 源码分析
Spring Boot 系列
  • Arthas 问题定位
  • JMH 基准测试
GitHub (opens new window)
首页
  • Java 18 新功能介绍
  • Java 17 新功能介绍
  • Java 16 新功能介绍
  • Java 15 新功能介绍
  • Java 14 新功能介绍
  • Java 8 新特性

    • Java 8 Lambda 表达式
    • Java 8 Stream 流式操作
    • Java 8 时间处理介绍
    • Java 8 Optional 介绍
  • Java 开发工具
Java 源码分析
Spring Boot 系列
  • Arthas 问题定位
  • JMH 基准测试
GitHub (opens new window)
  • Java web 开发

    • Web笔记(一) Web 简介与开发环境搭建
    • Web笔记(二)Tomcat 使用总结
    • Web笔记(三)Servlet 的类与接口API
      • Web笔记(四)Servlet 程序开发
      • Web笔记(五)Servlet 的生命周期
    • Java web 开发
    • Java web 开发
    程序猿阿朗
    2018-09-01

    Web笔记(三)Servlet 的类与接口API

    # Servlet 介绍

    Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。 使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。 Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

    • 性能明显更好。
    • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
    • Servlet 是独立于平台的,因为它们是用 Java 编写的。
    • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
    • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

    # Servlet API

    Servlet API 包含两个包,分别是:javax.servlet 与javax.servlet.http包。具体的类与接口结构如下图:

    Servlet 的运行需要Web 服务器的支持,Web服务器可以通过调用Servlet对象提提供的标准API ,对客户端请求做出处理。 官方API (opens new window)

    # Servlet 接口

    定义所有 servlet 都必须实现的方法。 servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。 要实现此接口,可以编写一个扩展 javax.servlet.GenericServlet 的一般 servlet,或者编写一个扩展 javax.servlet.http.HttpServlet 的 HTTP servlet。 此接口定义了初始化 servlet 的方法、为请求提供服务的方法和从服务器移除 servlet 的方法。这些方法称为生命周期方法,它们是按以下顺序调用的:

    1. 构造 servlet,然后使用 init 方法将其初始化。
    2. 处理来自客户端的对 service 方法的所有调用。
    3. 从服务中取出 servlet,然后使用 destroy 方法销毁它,最后进行垃圾回收并终止它。

    除了生命周期方法之外,此接口还提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一种方法获得任何启动信息,而后一种方法允许 servlet 返回有关其自身的基本信息,比如作者、版本和版权。

    Servlet 接口中定义的方法如下:

    //当Servlet将要卸载时由Servlet引擎调用,用于是释放资源 
    void  destroy()  
    
    //由 servlet 容器调用,指示将该 servlet 放入服务。servlet 容器
    //仅在实例化 servlet 之后调用 init 方法一次。在 servlet 可以接
    //收任何请求之前,init 方法必须成功完成。
    void  init(ServletConfig config) throws ServletException
    
    //由 servlet 容器调用,以允许 servlet 响应某个请求。此方法仅在 
    //servlet 的 init() 方法成功完成之后调用。  
    void  service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException 
    
    //返回 ServletConfig 对象,该对象包含此 servlet 的初始化和启动
    //参数。返回的 ServletConfig 对象是传递给 init 方法的对象。此接
    //口的实现负责存储 ServletConfig 对象,以便此方法可以返回该对象。
    //实现此接口的 GenericServlet 类已经这样做了。
    ServletConfig  getServletConfig()
    
    // 返回有关 servlet 的信息,比如作者、版本和版权。。
    String	getServletInfo()
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    # ServletConfig 接口

    由Servlet接口中的Init方法我们可以发现,init方法在做初始化工作的时候会传入ServletConfig类型的参数进行初始化工作, Servlet 容器使用的 ServletConfig配置对象,该对象在初始化期间将信息传递给 Servlet。

    ServletConfig 接口中定义的方法如下:

    //返回包含指定初始化参数的值的 String,如果参数不存在,则返回 null。
    String getInitParameter(String name) 
    
    //返回一个存储所有初始化变量的枚举函数,如果Servlet没有初始化变量,
    //返回一个空的枚举函数 
    java.util.Enumeration<E> getInitParameterNames() 
    
    //返回一个ServletConfig 对象的引用 
    ServletContext getServletContext() 
    
    //返回此 servlet 实例的名称。该名称可能是通过服务器管理提供的
    //在 Web 应用程序部署描述符中分配,或者对于未注册(和未命名)
    //的 servlet 实例,该名称将是该 servlet 的类名称。
    String getServletName() 
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    # GenericServlet 接口

    定义一般的、与协议无关的 Servlet。要编写用于 Web 上的 HTTP Servlet,请改为扩展 javax.servlet.http.HttpServlet。GenericServlet 实现 Servlet 和 ServletConfig 接口。**实现了Servlet 接口中除service()方法之外的所有抽象方法,但是是默认实现。**Servlet可以直接扩展 GenericServlet,GenericServlet 使编写 Servlet变得更容易。它提供生命周期方法 init 和 destroy 的简单版本,以及 ServletConfig 接口中的方法的简单版本。GenericServlet 还实现 log 方法,在 ServletContext 接口中对此进行了声明。

    要编写一般的 servlet,只需重写抽象 service 方法即可。在开发中很少使用,不再说明。

    # HttpServlet 接口

    HttpServlet 类继承GenericServlet 类,是一个抽象类。在Java Web 开发中自定义Servlet 通常都是直接集成HttpServlet 类,此类实现了Servlet 接口中的service(ServletRequest request,ServletResponse response) 方法,用来处理客户端请求,根据request中的getMethod方法来调用不同的处理方法,例如,get方法,则调用doGet方法进行处理,也因此HttpServlet定义了处理不同请求的不同方法。

    # ServletRequest 和 ServletResponse 接口

    定义将客户端请求信息提供给某个 servlet 的对象。servlet 容器创建 ServletRequest 对象,并将该对象作为参数传递给该 servlet 的 service 方法。 ServletRequest 对象提供包括参数名称、参数值、属性和输入流的数据。扩展 ServletRequest 的接口可提供其他特定于协议的数据,例如 javax.servlet.http.HttpServletRequest 提供的 HTTP 数据。

    ServletRequest中有很多有用的方法:

    //返回指定servlet上下文(web应用)的URL的前缀。 
    String getContextPath()  
    
    //返回请求URI上下文后的子串 
    String getServletPath() 
    
    //返回指定的HTTP头标指。如果其由请求给出,则名字应为大小写不敏感。 
    String getHeader(String name) 
    
    //返回具有指定名字的请求属性,如果不存在则返回null。属性可由servlet
    //引擎设置或使用setAttribute()显式加入。
    Object getAttribute(String name) 
    
    //以指定名称保存请求中指定对象的引用。 
    void setAttribute(String name,Object obj) 
    
    //返回指定输入参数,如果不存在,返回null。 
    String getParameter(String name) 
    
    //返回请求所用的字符编码。 
    String getCharacteEncoding()
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    具体可以参考官方API ServletRequest API (opens new window)

    ServletResponse 中有很多有用的方法:

    //返回响应使用字符解码的名字。除非显式设置,否则为ISO-8859-1 
    String getCharacterEncoding() 
    
    //返回用于将返回的二进制输出写入客户端的流,此方法和getWrite()
    //方法二者只能调用其一。 
    OutputStream getOutputStream()throws IOException 
    
    //返回用于将返回的文本输出写入客户端的一个字符写入器,此方法和
    //getOutputStream()二者只能调用其一。 
    Writer getWriter()throws IOException
    
    //设置内容类型。在HTTP servlet中即设置Content-Type头标。 
    void setContentType(String type) 
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    具体可以参考官方API ServletResponse API (opens new window)

    # HttpServletRequest 和 HttpServletResponse 接口

    HttpServletRequest 是专用于HTTP的ServletRequest 子接口,客户端浏览器的请求被封装成一个HttpServletRequest 对象,请求信息请求的地址,参数,数据,上传的文件,IP地址,甚至操作系统信息都包含在内。 主要处理:

    1. 读取和写入HTTP头标
    2. 取得和设置cookies
    3. 取得路径信息
    4. 标识HTTP会话。

    HttpServletRequest 常用方法:

    //返回与请求相关cookie的一个数组。
    Cookie[] getCookies()  
    
    //返回HTTP请求方法(例如GET、POST等等) 
    String getMethod() 
    
     //返回客户端的会话ID 
    String getRequestedSessionId()
    
     //调用getSession(true)的简化版。 
    HttpSession getSession()
    
    //返回当前HTTP会话,如果不存在,则创建一个新的会话,create参数为true。
    HttpSession getSession(boolean create) 
    
    //返回URL中一部分,从“/”开始,包括上下文,但不包括任意查询字符串。 
    String getRequestURI() 
    
    //返回查询字符串,即URL中?后面的部份。 
    String getQueryString() 
    
    //返回指定servlet上下文(web应用)的URL的前缀。 
    String getContextPath() 
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    HttpServletResponse 则继承了ServletResponse 接口。都提供了与HTTP有关的方法,主要是对HTTP状态码和Cookie的管理。

    //将一个Set-Cookie头标加入到响应。
    void addCookie(Cookie cookie) 
    
    //设置响应状态码为指定值(可选的状态信息)
    void sendError(int status)
    
    //重定向到某一个Web组件
    void sendRedirect(String location) 
    
    1
    2
    3
    4
    5
    6
    7
    8

    # ServletContext 接口

    一个ServletContext 接口对象表示一个Web应用程序的上下文,运行在Java虚拟机中每个Web应用程序都有一个与之香瓜你的Servlet上下文,Sevetl API提供了一个ServletContext 接口老表示上下文,它提供了一些方法可以让Servlet 通过这些方法与Servlet 容器进行通信。 常用方法:

    //将对象绑定到此 servlet 上下文中的给定属性名称。若存在,则替换之
    void setAttribute(String name, Object object)
    
    //返回Servlet 上下文中名字为name的对象,名字是name的对象是全局对象
    //因此可以被同一个Servlet 在任意时候访问,或者上下文中任意其他的Servlet访问
    Object getAttribute(String name) 
    
    // 返回包含指定上下文范围初始化参数值的 String,如果参数不存在,则返回 null
    String getInitParameter(String name) 
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    ServletContext 接口官方API (opens new window)

    # HttpSession 接口

    提供一种方式,跨多个页面请求或对 Web 站点的多次访问标识用户并存储有关该用户的信息。 HttpSession 接口用于记录HTTP客户端和HTTP会话之间的关联,且可以在多个连接和请求中持续一段时间,Session则可以让无状态的HTTP请求在多个请求时识别用户记录状态。

    此接口允许 servlet 查看和操作有关某个会话的信息,比如会话标识符、创建时间和最后一次访问时间 将对象绑定到会话,允许跨多个用户连接保留用户信息。

    常用方法:

    
    //使此会话无效,然后取消对任何绑定到它的对象的绑定。
    void invalidate()  
    
    //从此会话中移除与指定名称绑定在一起的对象。如果会话没有与
    //指定名称绑定在一起的对象,则此方法不执行任何操作。
    void removeAttribute(String name)
    
    //使用指定名称将对象绑定到此会话。如果具有同样名称的对象已
    //经绑定到该会话,则替换该对象。
     void setAttribute(String name, Object value)
     
    //返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑
    //定在该名称下,则返回 null。
     Object getAttribute(String name)
     
    //返回创建此会话的时间,该时间是用自格林威治标准时间 1970
    //年 1 月 1 日午夜起经过的毫秒数来测量的。
    long getCreationTime() 
    
    //返回包含分配给此会话的唯一标识符的字符串。
    String getId() 
    
    //超时时间以秒为单位。负数则永不超时。
    void setMaxInactiveInterval(int interval) 
    
    //返回 servlet 容器在客户端访问之间将使此会话保持打开状态
    //的最大时间间隔,以秒为单位。
    int getMaxInactiveInterval()
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    # 附录:HttpServletRequest的请求信息获取

    /**
     * HttpServletRequest请求参数获取测试
     * @author niumoo 
     */
    @WebServlet("/dispense")
    public class DispenseServlet extends HttpServlet {
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
    		throws ServletException, IOException {
    		// 获取请求方式:GET
    		System.out.println("req.getMethod():" + req.getMethod());
    
    		// 获取项目名称:/dispense
    		System.out.println("req.getContextPath():" + req.getContextPath());
    
    		// 获取完整请求路径:http://localhost:8888/dispense/dispense
    		System.out.println("req.getRequestURL():" + req.getRequestURL());
    
    		// 获取除了域名外的请求数据:/dispense/dispense
    		System.out.println("req.getRequestURI():" + req.getRequestURI());
    
    		// 获取请求参数:name=codingme.net
    		System.out.println("req.getQueryString():" + req.getQueryString());
    		// 获取请求头:
    		System.out.println("req.getHeader(\"user-Agent\"):" + req.getHeader("user-Agent"));
    
    		System.out.println("-------------------------------------------------");
    		// 获取所有的消息头名称
    		Enumeration<String> headerNames = req.getHeaderNames();
    		// 获取获取的消息头名称,获取对应的值,并输出
    		while (headerNames.hasMoreElements()) {
    			String nextElement = headerNames.nextElement();
    			System.out.println(nextElement + ":" + req.getHeader(nextElement));
    		}
    
    		System.out.println("---------------------------------------------------");
    		// 根据名称获取此重名的所有数据
    		System.out.println("req.getHeader(\"accept\"):" + req.getHeader("accept"));
    
    		// 获取请求主机名
    		System.out.println("req.getHeader(\"host\"):" + req.getHeader("host"));
    
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
    		throws ServletException, IOException {
    		doGet(req, resp);
    	}
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    请求:http://localhost:8888/dispense/dispense?name=codingme.net 输出:

    req.getMethod():GET
    req.getContextPath():/dispense
    req.getRequestURL():http://localhost:8888/dispense/dispense
    req.getRequestURI():/dispense/dispense
    req.getQueryString():name=codingme.net
    req.getHeader("user-Agent"):Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36
    --------------------------------------------------------
    host:localhost:8888
    connection:keep-alive
    cache-control:max-age=0
    upgrade-insecure-requests:1
    user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36
    accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    accept-encoding:gzip, deflate, br
    accept-language:zh-CN,zh;q=0.8
    cookie:_ga=GA1.1.1003706294.1499565784; Hm_lvt_57ccbd5c600ed4e6bdb9458e666b6409=1499849256,1499853602,1499950574; Hm_lvt_1b51c3ea9a3e7b1a2bc55df97ab4efd3=1499952403
    ----------------------------------------------------------
    req.getHeader("accept"):text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    req.getHeader("host"):localhost:8888
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    订阅

    文章持续更新,订阅可以关注「 程序猿阿朗 」公众号或者未读代码博客。

    文章作者: 程序猿阿朗
    文章链接:https://www.wdbyte.com/2018/09/develop/web/web/base-03/
    版权声明:本网站当前文章采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 未读代码!
    #Servlet
    上次更新: 2022/12/05, 08:18:32
    Web笔记(二)Tomcat 使用总结
    Web笔记(四)Servlet 程序开发

    ← Web笔记(二)Tomcat 使用总结 Web笔记(四)Servlet 程序开发→

    最近更新
    01
    如何搭建一个自己的音乐服务器
    12-04
    02
    JUnit 5 单元测试教程
    11-17
    03
    使用 StringUtils.split 的坑
    11-02
    更多文章>

    提示:评论前请刷新页面,否则评论的可能不是当前文章。

    Theme by Vdoing | Copyright © 2018-2022 程序猿阿朗 | MIT License | 皖ICP备20000567号-1
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式