般情况下,浏览器(客户端)通过 HTTP 协议来访问服务器的资源,Servlet 主要用来处理 HTTP 请求。

Servlet 处理 HTTP 请求的流程如下:

  1. Servlet 容器接收到来自客户端的 HTTP 请求后,容器会针对该请求分别创建一个 HttpServletRequest 对象和 HttpServletReponse 对象。
  2. 容器将 HttpServletRequest 对象和 HttpServletReponse 对象以参数的形式传入 service() 方法内,并调用该方法。
  3. 在 service() 方法中 Servlet 通过 HttpServletRequest 对象获取客户端信息以及请求的相关信息。
  4. 对 HTTP 请求进行处理。
  5. 请求处理完成后,将响应信息封装到 HttpServletReponse 对象中。
  6. Servlet 容器将响应信息返回给客户端。
  7. 当 Servlet 容器将响应信息返回给客户端后,HttpServletRequest 对象和 HttpServletReponse 对象被销毁。

通过以上流程可以看出, HttpServletRequest 和 HttpServletReponse 是 Servlet 处理 HTTP 请求流程中最重要的两个对象。HttpServletRequest 对象用于封装 HTTP 请求信息,HttpServletReponse 对象用于封装 HTTP 响应信息。

下面我们将对 HttpServletRequest 进行详细介绍。

HttpServletRequest 接口

在 Servlet API 中,定义了一个 HttpServletRequest 接口,它继承自 ServletRequest 接口。HttpServletRequest 对象专门用于封装 HTTP 请求消息,简称 request 对象。

HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,所以 HttpServletRequest 接口中定义了获取请求行、请求头和请求消息体的相关方法。

获取请求行信息

HTTP 请求的请求行中包含请求方法、请求资源名、请求路径等信息,HttpServletRequest 接口定义了一系列获取请求行信息的方法,如下表。

返回值类型 方法声明 描述
String getMethod() 该方法用于获取 HTTP 请求方式(如 GET、POST 等)。
String getRequestURI() 该方法用于获取请求行中的资源名称部分,即位于 URL 的主机和端口之后,参数部分之前的部分。
String getQueryString() 该方法用于获取请求行中的参数部分,也就是 URL 中“?”以后的所有内容。
String getContextPath() 返回当前 Servlet 所在的应用的名字(上下文)。对于默认(ROOT)上下文中的 Servlet,此方法返回空字符串""。
String getServletPath() 该方法用于获取 Servlet 所映射的路径。
String getRemoteAddr() 该方法用于获取客户端的 IP 地址。
String getRemoteHost() 该方法用于获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则该方法将会返回客户端的 IP 地址。

获取请求头信息

当浏览器发送请求时,需要通过请求头向服务器传递一些附加信息,例如客户端可以接收的数据类型、压缩方式、语言等。为了获取请求头中的信息, HttpServletRequest 接口定义了一系列用于获取 HTTP 请求头字段的方法,如下表所示。

返回值类型 方法声明 描述
String getHeader(String name) 该方法用于获取一个指定头字段的值。
如果请求消息中包含多个指定名称的头字段,则该方法返回其中第一个头字段的值。
Enumeration getHeaders(String name) 该方法返回指定头字段的所有值的枚举集合,
在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次。
Enumeration getHeaderNames() 该方法返回请求头中所有头字段的枚举集合。
String getContentType() 该方法用于获取 Content-Type 头字段的值。
int getContentLength() 该方法用于获取 Content-Length 头字段的值 。
String getCharacterEncoding() 该方法用于返回请求消息的字符集编码 。

获取 form 表单的数据

在实际开发中,我们经常需要获取用户提交的表单数据,例如用户名和密码等。为了方便获取表单中的请求参数,ServletRequest 定义了一系列获取请求参数的方法,如下表所示。

返回值类型 方法声明 功能描述
String  getParameter(String name) 返回指定参数名的参数值。
String [ ]  getParameterValues (String name) 以字符串数组的形式返回指定参数名的所有参数值(HTTP 请求中可以有多个相同参数名的参数)。
Enumeration  getParameterNames() 以枚举集合的形式返回请求中所有参数名。
Map  getParameterMap() 用于将请求中的所有参数名和参数值装入一个 Map 对象中返回。

根据请求方式的不同,请求一般可以被分为两种:GET 请求和 POST 请求。这两种请求方式都可能会产生中文乱码问题,下面我们分别对它们产生乱码的原因及其解决方案进行介绍。

POST 请求

乱码的原因:POST 提交的数据在请求体中,其所使用的编码格式时页面一致(即 utf-8)。request 对象接收到数据之后,会将数据放到 request 缓冲区,缓冲区的默认字符集是 ISO-8859-1(该字符集不支持中文),两者使用的字符集不一致导致乱码。

解决方案:在获取请求参数之前设置 request 缓冲区字符集为 utf-8 ,代码如下。

  1. //修改request缓冲区的字符集为UTF-8
  2. request.setCharacterEncoding("utf-8");
  3. // 获取用户名
  4. String username = request.getParameter("username");

GET 请求

乱码的原因:Get 请求将请求数据附加到 URL 后面作为参数,浏览器发送文字时采用的编码格式与页面编码保持一致(utf-8)。如果 Tomcat 没有设置字符集,接收 URL 时默认使用 ISO-8859-1 进行解码,ISO-8859-1 不兼容中文,无法正确解码,导致出现乱码。

需要注意的是,在 Tomcat 8 中已解决了 get 方式提交请求中文乱码的问题,使用 Tomcat 8 及以上版本的同学不必再考虑此问题了,如果您使用的是 Tomcat 7 或更早的版本,出现乱码问题可以使用如下的方案解决。

解决方案:解决 GET 请求中文乱码问题,有以下 3 种解决方案。

1. 修改 tomcat/conf/server.xml 中的配置,代码如下。

  1. <Connector port="80" protocol="HTTP/1.1"
  2. connectionTimeout="20000"
  3. redirectPort="8443" URIEncoding="UTF-8"/>

2. 使用 URLEncoder 和 URLDecoder 进行编码和解码的操作(逆向编解码)。

  1. //得到TOMCAT通过ISO8859-1解码的字符串
  2. String username = request.getParameter("username");
  3. //对字符串使用ISO8859-1进行编码,得到最初浏览器使用UTF-8编码的字符串
  4. username = URLEncoder.encode(username, "ISO8859-1");
  5. //将使用UTF-8编码的字符串使用UTF-8进行解码,得到正确的字符串
  6. username = URLDecoder.decode(username, "UTF-8");

3. 使用 String 的构造方法:String(byte[] bytes, String charset) ,对字节数组(bytes)按照指定的字符集(charset)进行解码,返回解码后的字符串,解决乱码问题(推荐使用)。

  1. //获取姓名
  2. String username = request.getParameter("username");
  3. //使用String的构造方法解决乱码的问题
  4. username = new String(username.getBytes("ISO-8859-1"),"UTF-8");

HttpServletRequest接口详解的更多相关文章

  1. JDBC常用接口详解

    JDBC中常用接口详解 ***DriverManager 第一.注册驱动 第一种方式:DriverManager.registerDriver(new com.mysql.jdbc.Driver()) ...

  2. Java6.0中Comparable接口与Comparator接口详解

    Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...

  3. socket接口详解

    1. socket概述 socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket起源于UNIX,在Unix一切 ...

  4. “全栈2019”Java第八十四章:接口中嵌套接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. “全栈2019”Java第八十三章:内部类与接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. Java接口 详解(二)

    上一篇Java接口 详解(一)讲到了接口的基本概念.接口的使用和接口的实际应用(标准定义).我们接着来讲. 一.接口的应用—工厂设计模式(Factory) 我们先看一个范例: package com. ...

  7. [转载]MII/MDIO接口详解

    原文地址:MII/MDIO接口详解作者:心田麦浪 本文主要分析MII/RMII/SMII,以及GMII/RGMII/SGMII接口的信号定义,及相关知识,同时本文也对RJ-45接口进行了总结,分析了在 ...

  8. map接口详解

    1.Map接口详解(1)映射(map)是一个存储键.键值对的对象,给定一个键,可以查询得到它的值,键和值都可以是对象(2)键必须是唯一的,值可以重复(Map接口映射唯一的键到值)(3)有些映射可以接收 ...

  9. ReadWriteLock 接口详解

    ReadWriteLock 接口详解 这是本人阅读ReadWriteLock接口源码的注释后,写出的一篇知识分享博客 读写锁的成分是什么? 读锁 Lock readLock(); 只要没有写锁,读锁可 ...

随机推荐

  1. 优雅的按键模块-----Multi-button

    优雅的按键模块-----Multi-button ​ 在我们日常开发和使用的过程中常常使用了一些按键,利用按键实现不同的功能,比如长按,短按,双击等等.但是每次都是采用标志等等来实现信息的读取,是否有 ...

  2. Mybatis-Plus一键生成代码

    Mybatis-Plus一键生成代码 一.闲言碎语 闲来无事看了看了MP的官网看到一键生成的代码更新了! 整个Ui风格都变了,遂决定瞅一眼新的代码生成器 官网地址~~ 二.引入依赖 新的代码生成只有在 ...

  3. JAVA结合WebSocket实现简单客服聊天功能

    说明:该示例只简单的实现了客服聊天功能. 1.聊天记录没有保存到数据库中,一旦服务重启,消息记录将会没有,如果需要保存到数据库中,可以扩展 2.页面样式用的网上模板,样式可以自己进行修改 3.只能由用 ...

  4. cmake之生成动态库

    演示源码下载地址: https://github.com/mohistH/demo_cmake_dylib 把文仅为参考. 以实际情况为准 1.目录结构 │ CMakeLists.txt │ inde ...

  5. 【LeetCode】5083. Occurrences After Bigram 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字符串分割遍历 日期 题目地址:https://le ...

  6. 【LeetCode】575. Distribute Candies 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Java解法 Python解法 日期 题目地址:ht ...

  7. 【LeetCode】883. Projection Area of 3D Shapes 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 数学计算 日期 题目地址:https://leetc ...

  8. 理解Android的四种启动模式

    一:前言 四种模式分别为standard, singleTop, singleTask, singleInstance.自己应该明确一个概念先,single到底要single什么.每一个应用app都有 ...

  9. MLP-Mixer: An all-MLP Architecture for Vision

    目录 概 主要内容 代码 Tolstlkhin I., Houlsby N., Kolesnikov A., Beyer L., Zhai X., Unterthiner T., Yung J., S ...

  10. matplotlib 进阶之Customizing Figure Layouts Using GridSpec and Other Functions

    目录 对Gridspec的一些精细的调整 利用SubplotSpec fig.add_grdispec; gs.subgridspec 一个利用Subplotspec的复杂例子 函数链接 matplo ...