第5章 处理GET请求参数

1 什么是GET请求参数

        表单GET请求参数是指在HTML表单中通过GET方法提交表单数据时所附带的参数信息。在HTML表单中,可以通过表单元素的name属性来指定表单字段的名称,通过表单元素的value属性来指定表单字段的值。当用户提交表单时,浏览器会将表单字段的名称和值以键值对的形式打包成查询字符串(query string),将查询字符串附加到表单的action URL中作为GET请求的参数信息。

        例如,假设一个简单的表单如下所示:

  <h1>用户注册</h1><form action="/accounts/register" ><label>姓名:<input type="text" name="name" placeholder="请输入您的姓名"></label><br><label>密码:<input type="password" name="password" placeholder="请输入密码"></label><br><label>邮箱:<input type="text" name="email" placeholder="请输入邮箱"></label><br><label>性别:<input type="text" name="gender" placeholder="输入性别"></label><br><input type="submit" value="提交"></form>

        其中,action属性指定表单提交的目标URL。当填写姓名为“Tom”,密码“1234”,邮箱“tom@demo.com”,性别“男”:

        并且点击"提交"按钮提交表单时,浏览器将发送一个GET请求到"http://localhost:8089/accounts/register "。

        在服务服务器端可以看到如下信息:

        显然请求参数信息包含在uri中。

        由于我们没有在服务端接收这些参数,并且没有进行适当的处理,所以客户端得到了404错误。

2 解析GET请求参数

        解析GET请求参数的过程主要涉及对查询字符串进行解析和处理。通常,服务器端的程序可以通过以下步骤来解析GET请求参数:

        1. 获取URL中的查询字符串部分:对于HTTP GET请求,查询字符串部分位于URL中的问号字符(?)之后,可以通过解析URI来获取该部分的内容。

        2. 解析查询字符串中的键值对:查询字符串中的键值对通常使用等号(=)连接,键值对之间使用和号(&)连接。可以通过字符串分割和循环遍历来解析键值对。

        3. 对键值对的值进行解码:由于URL中的查询字符串部分需要进行URL编码以确保参数值的正确性和安全性,因此在解析时需要对键值对的值进行解码。

        综合上述步骤,我们可以使用Java代码实现GET请求参数的解析。解析过程如下所示:

3 解析GET请求参数的方法

        首先,添加解析请求参数的方法。

        解析请求功能显然是HttpServletRequest对象的职责,重构HttpServletRequest对象,添加解析请求参数的方法:

/** 查询字符串 */
private String queryString;
/** 请求路径 */
private String requestURI;
/** 存储全部参数 */
private HashMap<String, String> parameters = new HashMap<>();
private void parseUri(){//使用?拆分请求路径和查询字符串. ?是正则特殊字符,需要使用转义字符String[] parts = uri.split("\\?");requestURI = parts[0];queryString = parts[1];//使用&拆分解析查询字符串parts = queryString.split("&");for (String part : parts) {//使用 = 拆分出 name 和 valueString[] param = part.split("=");String name = param[0];String value = param[1];parameters.put(name, value);}System.out.println("解析了参数:"+parameters);
}

        在这个解析方法中,假设请求 URI 为 /accounts/register?name=Tom&password=1234&email=tom%40demo.com&gender=%E7%94%B7,解析代码将分解成以下步骤达成目的:

        1、使用 split() 方法将 URI 拆分成两个部分,即请求路径和查询字符串。由于 ? 是一个正则特殊字符,因此需要使用转义字符 \\? 进行拆分。因此,parts 数组中将包含 "/accounts/register" 和 " name=Tom&password=1234&email=tom%40demo.com&gender=%E7%94%B7" 两个元素。

        2、将parts第一个元素存储到 requestURI 变量中。

        3、将parts第二个元素存储到 queryString 变量中。

        4、使用 split() 方法将查询字符串 queryString 拆分成多个参数。在这个示例中,使用 & 进行拆分,将得到一个包含四个元素的 parts 数组,分别是 "name=Tom"、" password=1234"、“email=tom%40demo.com”和gender=%E7%94%B7。

        5、对于每个参数,使用 split() 方法将参数名称和参数值拆分开。在这个示例中,使用 = 进行拆分。

        6、将每个参数名称和参数值存储到 parameters HashMap 中。

        7、输出map集合,检查解析是否成功了。

        然后,重构解析请求行方法 parseRequestLine:在uri中有?时候调用parseUri()方法对uri中的参数进行进一步的解析:

//解析请求行中的请求参数
if (uri.contains("?")){parseUri();
}else{requestURI = uri;
}

4 GET请求编码问题

        上述解析URL功能,接收到的中文和特殊字符会出现“乱码”,这个问题并不是乱码,而是HTTP协议通过URL传输数据时候,对特殊字符(中文)进行了编码。

        URL参数需要进行编码,是因为URL中只能包含特定的字符集,如字母、数字和一些特殊字符(中文),其他字符如果直接包含在URL中可能会导致URL无法正确解析或者出现意外的结果。因此,为了避免这种情况发生,需要对URL参数进行编码,以便在传输过程中对其进行安全的转换和传递。

        URL编码(也称百分号编码或URL转义):将URL参数中的非法字符转换成%xx的形式,其中xx是表示字符ASCII码值的16进制数字,例如空格的ASCII码值是32,因此用%20来表示空格。

        下面是一个URL参数编码的示例,假设要传递参数"Hello, World!",使用URL编码后的结果为:"Hello%2C%20World%21"。浏览器在发送数据时候,对数据进行了URL编码,服务端收到的就是这些“乱码”,只要进行对应的解码即可。

5 使用Java API对URL编码数据进行解码

        URL解码是将经过编码后的URL参数还原成原始数据的过程。URL解码的目的是为了恢复URL参数的原始含义,使得URL能够正确地被服务器解析和处理。

        URL解码(也称百分号解码或URL反转义):将URL参数中的%xx还原成对应的ASCII字符。例如,%20表示空格,将其解码后得到空格字符。

        Java API 提供了URLDecoder.decode()方法,对URL编码的数据进行解码:

  • 第一个参数为需要解码的URL参数
  • 第二个参数为字符编码方式:通常使用UTF-8
  • 输出解码后的结果

        下面是一个使用Java API对URL编码数据进行解码的示例,假设需要解码的URL参数为"Hello%2C%20World%21":

import java.net.URLDecoder;public class URLDecoderExample {public static void main(String[] args) {try {String encodedURL = "Hello%2C%20World%21";String decodedURL = URLDecoder.decode(encodedURL, "UTF-8");System.out.println("Encoded URL: " + encodedURL);System.out.println("Decoded URL: " + decodedURL);} catch (Exception e) {e.printStackTrace();}}
}

        输出结果为:

Encoded URL: Hello%2C%20World%21

Decoded URL: Hello, World!

        在示例中,首先使用URLDecoder.decode()方法对URL编码的数据进行解码。该方法的第一个参数为需要解码的URL参数,第二个参数为字符编码方式,通常使用UTF-8,最后输出解码后的结果。

6 HttpServletRequest添加参数解码功能

        继续重构HttpServletRequest的parseUri方法,将收到的请求数据进行URL解码,这样就可以解决特殊字符以及中文参数解码问题。

        代码示意如下:

private void parseUri() throws UnsupportedEncodingException {//使用?拆分请求路径和查询字符串. ?是正则特殊字符,需要使用转义字符String[] parts = uri.split("\\?");requestURI = parts[0];queryString = parts[1];//使用&拆分解析查询字符串parts = queryString.split("&");for (String part : parts) {//使用 = 拆分出 name 和 valueString[] param = part.split("=");String name = param[0];String value = URLDecoder.decode(param[1], "UTF-8");parameters.put(name, value);}System.out.println("解析了参数:"+parameters);
}

        在对接收参数进行URL解码后,在表单中添入中文,在服务端就能接收到正确结果了:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/697208.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

表征和基于结构的蛋白质工程:黄芪特异性皂苷乙酰转移酶-文献精读14

Characterization and structure-based protein engineering of a regiospecific saponin acetyltransferase from Astragalus membranaceus 表征和基于结构的蛋白质工程&#xff1a;黄芪特异性皂苷乙酰转移酶&#xff0c;一篇乙酰基转移酶文章精读分享~ 摘要 乙酰化有助于许…

92. 反转链表 II

Problem: 92. 反转链表 II 文章目录 思路复杂度Code 思路 遍历到left前一个结点&#xff0c;反转[left, right]这一段区间 当区间反转完毕后&#xff0c;p0&#xff08;反转区间left的前一个结点&#xff0c;因为当left是head结点的时候&#xff0c;并无前一个结点&#xff0…

Django 安全性与防御性编程:如何保护 Django Web 应用

title: Django 安全性与防御性编程&#xff1a;如何保护 Django Web 应用 date: 2024/5/13 20:26:58 updated: 2024/5/13 20:26:58 categories: 后端开发 tags: CSRFXSSSQLUploadHTTPOnlyPasswordSession 跨站请求伪造&#xff08;CSRF&#xff09; 跨站请求伪造&#xff0…

android app自动化测试工具有哪些?

尽管有多种Android自动化测试工具可供选择&#xff0c;但以下是一些最常用和受欢迎的工具。 Appium&#xff1a; Appium是一个开源的移动应用自动化测试工具&#xff0c;支持Android和iOS平台。它使用WebDriver协议来控制手机设备&#xff0c;可以使用多种编程语言编写测试脚本…

002.反应式编程的必要性

在实际应用程序中&#xff0c;您可以在许多情况下发现可能的时变变量—例如&#xff0c;GPS位置、温度、鼠标坐标&#xff0c;甚至文本框的内容。所有这些都有一个随时间变化的值应用程序会发生反应&#xff0c;因此是时变的。还有一点值得一提时间本身就是一个时变;它的值一直…

YOLOv8小白中的小白安装环境教程!没一个字废话,看一遍不踩坑!

文章目录 去哪里下代码?怎么下代码?怎么装环境?命令行界面(CLI)指令和Python脚本区别?附录1 conda常用指令附录2 git常用指令附录3 项目代码文件作用去哪里下代码? 下载代码请大家直接去 YOLOv8的官方仓库下载,名字叫 ultralytics,有些镜像网站和个人发的等来历不明的代…

使用LangChain和Neo4j快速创建RAG应用

大家好&#xff0c;Neo4j 通过集成原生的向量搜索功能&#xff0c;增强了其对检索增强生成&#xff08;RAG&#xff09;应用的支持&#xff0c;这标志着一个重要的里程碑。这项新功能通过向量索引搜索处理非结构化文本&#xff0c;增强了 Neo4j 在存储和分析结构化数据方面的现…

基于SSM的“基于协同过滤的在线通用旅游平台网站”的设计与实现(源码+数据库+文档)

基于SSM的“基于协同过滤的在线通用旅游平台网站”的设计与实现&#xff08;源码数据库文档) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统主界面 景点信息界面 后台界面 部分源码…

具身智能论文(一)

目录 1. PoSE: Suppressing Perceptual Noise in Embodied Agents for Enhanced Semantic Navigation2. Embodied Intelligence: Bionic Robot Controller Integrating Environment Perception, Autonomous Planning, and Motion Control3. Can an Embodied Agent Find Your “…

【cpp】并发多线程 Unique

1. unique_lock 何时锁定资源。 unique_lock lock1 时候&#xff0c;还没有锁住资源。 实际是后面&#xff0c;显式的出发&#xff1a; 比如&#xff0c; lock.lock, 或 std::lock(lk1,lk2), 或者条件变量CV.wait(mtx, []{!re})。 #include <iostream> #include <mu…

Redis-详解(基础)

文章目录 什么是Redis&#xff1f;用Redis的特点&#xff1f;用Redis可以实现哪些功能&#xff1f;Redis的常用数据类型有哪些?Redis的常用框架有哪些?本篇小结 更多相关内容可查看 什么是Redis&#xff1f; Redis&#xff08;Remote DictionaryServer&#xff09;是一个开源…

服务器端口怎么开,服务器端口的开放通常涉及的五个关键步骤

服务器端口的开放通常涉及五个关键步骤&#xff0c;包括修改防火墙规则、配置服务器软件以及验证端口是否开放。下面将详细介绍每个步骤。 一、您需要确定需要开放的端口。常见的服务器应用程序端口包括HTTP&#xff08;80端口&#xff09;、HTTPS&#xff08;443端口&#xff…