HTTP Server?也是我们常说的Web服务器
在网络中传递的信息都是以【二进制】形式存在的,接收方在接收信息后需要把二进制数据编译为原数据。
弊端:HTTP协议无法实现服务器主动向客户端发起消息。
http服务器需要
1、可以接收来自浏览器发送的Http请求协议包,并自动对Http请求协议包内容解析
2、并将定位的文件内容给写入到Http写入到HTTP响应协议包
在基于B/S结构下,互联网通信过程中,所有在网络中传递信息都是保存在HTTP网络协议包
浏览器 向 WEB服务器发送数据的时候,这个发送的数据需要遵循一套标准,这套标准中规定了发送的数据具体格式。
HTTP请求协议包自上而下划分为4个空间
请求行主要提供:请求地址和请求方式
get方式参数存放在请求数据包的请求行的URI字段中,以?开始以param=value¶me2=value2的形式附加在URI字段之后
如果请求方式是get,那么请求参数信息会保存到请求头中
x-forwarded-for:是一个 HTTP 扩展头部,主要是为了让 Web 服务器获取访问用户的真实 IP 地址
X-Forwarded-For 请求头格式
X-Forwarded-For: client, proxy1, proxy2
可以看到,XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP(用户真实 IP),然后是每一级代理设备的 IP。
public static String getIpAddr(HttpServletRequest request) { if (request == null) { return "unknown"; } String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; }
CONTENT_TYPE
没有任何内容。是用来区分"请求头"和"请求体"的
如果请求方式是post,那么请求参数信息会保存到请求体中
WEB服务器 向 浏览器发送数据的时候,这个发送的数据需要遵循一套标准,这套标准中规定了发送的数据具体格式。
HTTP状态码
Content-Type:指定浏览器采用对应编译器对响应体二进制数据进行解析
区分"响应头"和"响应体"
可能是被访问静态资源文件内容,可能是动态资源文件的运行结果
HTTP 请求可以使用多种请求方法。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
HttpClient 是Apache HttpComponents 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
创建HttpClient对象。
创建请求方式的实例。创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
添加请求参数。如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
发送Http请求。调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
获取返回的内容。调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
释放资源。无论执行方法是否成功,都必须释放资源;
spring boot集成HttpClient
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
如果是maven工程,引入如下maven依赖
<!-- 此处使用的是 5.x 版本,可以根据自身情况引入版本 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1.1</version>
</dependency>
在 HttpClient 中把响应封装成了?CloseableHttpResponse
?对象,在此对象中可以获取如下数据:
HttpClient 提供了?EntityUtils
工具类,可以很好的把 响应的 HttpEntity 转换为 字节数组或者字符串
// 转换为字符串
EntityUtils.toString(response.getEntity());
// 转换为字节数组
EntityUtils.toByteArray(response.getEntity());
1
GET请求的所有参数是直接拼接在 URL 后面的,在浏览器地址栏中可见。
GET请求url编码
使用GET请求时会将参数附加到URL的查询字符串中,以便将其发送给服务器。但是GET请求只接受ASCII字符作为参数值。
解决办法:
GET请求会把参数进行URL编码(也称为百分号编码或URL转义),以确保特殊字符不会干扰URL结构。
public static void main(String[] args) throws Exception {
//获取默认配置的 HttpClient
CloseableHttpClient httpclient = HttpClients.createDefault();
//设置单个请求的配置信息
RequestConfig requestConfig = RequestConfig.custom()
// 设置连接超时时间
.setConnectTimeout(Timeout.of(3000, TimeUnit.MILLISECONDS))
// 设置响应超时时间
.setResponseTimeout(3000, TimeUnit.MILLISECONDS)
// 设置从连接池获取链接的超时时间
.setConnectionRequestTimeout(3000, TimeUnit.MILLISECONDS)
.build();
// 请求路径及参数
String name = URLEncoder.encode("张三", "utf-8");
String url = "http://localhost:10010/user/params?age=20&name=" + name;
HttpGet httpget = new HttpGet(url);
httpget.setConfig(requestConfig);
// 调用 HttpClient 的 execute 方法执行请求
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
EntityUtils.consume(entity);
System.out.println(result);
} finally {
response.close();
}
}
通过 URIBuilder 构建请求路径
使用POST请求时,参数通过HTTP消息体进行传输,并不会直接显示在URL上。
POST支持多种编码方式。
熟悉常见的 Content-Type 类型对于处理 POST 请求至关重要,它可以帮助我们更好地使用和解决问题。
请求头字段有?
Content-Type
具体的数据格式和编码方式由?
Content-Type
?字段确定。服务端会根据 Content-Type 字段使用不同的方式对请求体进行解析。1、最常用的POST数据编码方式是?application/x-www-form-urlencoded?,它与GET相似,也会对非ASCII字符和特殊字符进行URL编码。
这种方式下,参数按照键值对形式出现在消息正文中,并用&符号连接起来,同时以?=?分隔键和值,
public static void main(String[] args) throws Exception { // 创建 ContentType 对象为 form 表单模式 ContentType contentType = ContentType.create("application/x-www-form-urlencoded", StandardCharsets.UTF_8); String url = "http://localhost:10010/user/body"; HttpPost httpPost = new HttpPost(url); //设置请求头,添加到 HttpPost 头中 httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType); //HttpPost请求 要传的参数 这里先将参数封装起来 List<BasicNameValuePair> params = new ArrayList<>(); params.add(new BasicNameValuePair("name", "张三")); params.add(new BasicNameValuePair("age", "20")); //这一步才是 为post 请求设置参数 这是创建表单的实体对象 设置当前参数的编码格式 //设置请求数据,把HttpEntity 设置到 HttpPost 中 httpPost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8)); //获取默认配置的 HttpClient CloseableHttpClient httpclient = HttpClients.createDefault(); //调用 HttpClient 的 execute 方法执行请求 CloseableHttpResponse response = httpclient.execute(httpPost); try { HttpEntity entity = response.getEntity(); String result = EntityUtils.toString(entity); EntityUtils.consume(entity); System.out.println(result); } finally { response.close(); } }
2、使用?
application/json
?编码方式,可以将数据序列化成一个 JSON 字符串作为请求主体。3、multipart/form-data
这种编码方式主要用于文件上传,可以有效地传输二进制(非字母数字)数据,同时还可以携带其他信息
HTTP 中的 POST 请求的数据是包含在请求体中的。在 HttpClient 中 POST 请求发送数据是通过,调用?HttpPost
?类的?setEntity(HttpEntity entity)
?方法设置消息内容的
发送 JSON 数据