1、Http请求概述
HTTP 请求是用来与服务器进行交互的,在Web开发中占有核心地位。常见的HTTP请求方法有多种,每种方法都有其特定的用途。以下是主要的HTTP请求方法及其作用:
1.1、GET
1.用途:请求从服务器获取数据。
2.使用场景:当浏览器向服务器请求一个网页时,通常使用GET请求。GET请求也经常用于获取资源,如图片、数据列表等。
3.特点:数据通常会附加在URL中(即请求参数)。GET请求一般是“幂等”的(同样的请求可以重复多次而不会产生副作用)。不建议用于传递敏感数据(比如密码),因为数据在URL中是可见的。
1.2、POST
1.用途:向服务器提交数据以创建资源。
2.使用场景:当需要提交表单数据、上传文件,或者发送复杂的数据给服务器时使用。
3.特点:数据在请求体中发送,不会出现在URL中。POST请求是“非幂等”的(同样的请求多次执行可能会导致不同的结果,比如多次提交会创建多个相同的资源)。支持更大的数据量。
1.3、 PUT
1.用途:向服务器发送数据以更新资源,如果资源不存在,则可以选择创建新资源。
2.使用场景:用来更新已有记录的场景,如修改用户资料信息。
3.特点:请求是“幂等”的(同样的请求多次执行会得到相同的结果,不会重复增加资源)。通常将数据发送到特定的URL路径。
1.4、DELETE
1.用途:删除指定的资源。
2.使用场景:用来删除记录或文件等资源,比如删除用户或文章。
3.特点:请求是“幂等”的,重复发送删除请求通常不会造成额外的影响(前提是资源不存在时返回404等状态码)。
1.5、HEAD
1.用途:与GET请求类似,但只返回头部信息,不返回具体内容。
2.使用场景:用于检查资源的元数据,比如是否存在、是否被修改等,而不获取实际数据。
3.特点:常用于性能优化和资源检查,如在判断内容是否需要更新时使用。
2、典型使用示例
1、GET 请求用户信息:GET /users/123
2、POST 提交表单数据:POST /form
3、PUT 更新文章内容:PUT /posts/456
4、DELETE 删除记录:DELETE /records/789
不同的HTTP请求方法针对不同场景设计,规范了客户端与服务器之间如何交互并保持数据一致性。
3、HTTP&HTTPS
1、HTTP(HyperText Transfer Protocol):是一种应用层协议,主要用于在客户端和服务器之间传输网页数据,如HTML文档、图像、视频等。HTTP是一种明文传输协议,意味着数据在传输时没有经过加密。
2、HTTPS(HyperText Transfer Protocol Secure):是在HTTP的基础上增加了安全层,通过使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)对数据进行加密和身份验证。它可以确保通信的机密性、完整性和真实性。
3.1、HTTP 和 HTTPS 的主要区别
3.1.1、安全性
1、HTTP 是明文传输,数据在客户端与服务器之间传输时容易被第三方截获和窃听。这对敏感信息如密码、信用卡号等存在很大风险。
2、HTTPS 通过加密机制提供了更高的安全性。传输数据经过加密,确保通信内容不被窃取、篡改和伪造。
3.1.2、端口号
1、HTTP 使用的默认端口号是 80。
2、HTTPS 使用的默认端口号是 443。
3.1.3、数据传输方式
1、HTTP 直接通过TCP进行传输。
2、HTTPS 通过SSL/TLS协议进行加密,然后再通过TCP进行传输。也就是说,HTTPS是HTTP和SSL/TLS的结合。
3.1.4、证书验证
1、HTTP 不需要证书即可工作。
2、HTTPS 需要服务器端配置SSL/TLS证书,通过证书来验证服务器的身份并加密数据。
3.2、HTTP 和 HTTPS 的工作原理
3.2.1、HTTP 的工作原理
1、建立连接:客户端与服务器之间通过TCP/IP建立连接。
2、发送请求:客户端向服务器发送HTTP请求,包括请求方法、URL、头部信息等。
3、服务器处理请求并返回响应:服务器处理请求后返回响应,包括状态码、头部和数据内容等。
4、关闭连接(HTTP/1.0)或保持连接(HTTP/1.1/2/3):连接关闭或保持,以便后续请求使用。
HTTP 是一种无状态的明文协议,数据在传输时没有加密,所以通信的隐私性和安全性无法保证。
3.2.2、HTTPS 的工作原理
1、HTTPS 工作原理相对复杂,因为它涉及加密和身份验证过程。以下是 HTTPS 的大致流程:
2、建立连接和握手:客户端与服务器建立连接并发起 SSL/TLS 握手过程。这个过程涉及:
3、客户端发送Hello消息:客户端向服务器发送请求,说明它支持的加密算法和TLS版本。
4、服务器发送证书和响应:服务器返回一个数字证书,其中包含其公钥和其他信息,供客户端验证。
5、客户端验证证书:客户端验证服务器的证书,确保其合法性和真实性。如果证书有效,客户端生成一个“会话密钥”,并用服务器的公钥加密后发送给服务器。
6、建立加密通信通道:服务器使用其私钥解密会话密钥,双方使用该会话密钥来对接下来的通信进行对称加密。这意味着后续传输的数据都是加密的,第三方无法轻易解读。
7、发送请求和响应:在加密通道上,客户端发送HTTP请求,服务器处理并返回响应,整个通信过程都被加密。
8、关闭连接:通信完成后,连接可能被关闭(如果使用短连接)。
4、封装的工具类代码
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Map;
@Slf4j
public class HttpUtil {
private static final int MAX_RETRIES = 5;
private static final int TIMEOUT = 5000;
public static <T> T sendGet(String url, Class<T> clazz) throws Exception {
return sendHttpRequest("GET", url, null, null, clazz);
}
public static <T> T sendPost(String url, String postData, Map<String, String> headers, Class<T> clazz) throws Exception {
return sendHttpRequest("POST", url, postData, headers, clazz);
}
private static <T> T sendHttpRequest(String method, String url, String postData, Map<String, String> headers, Class<T> clazz) throws Exception {
int retries = 0;
while (retries < MAX_RETRIES) {
HttpURLConnection connection = null;
try {
URL requestUrl = new URL(url);
connection = (HttpURLConnection) requestUrl.openConnection();
connection.setRequestMethod(method);
connection.setConnectTimeout(TIMEOUT);
connection.setReadTimeout(TIMEOUT);
if ("POST".equalsIgnoreCase(method)) {
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json");
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
try (OutputStream outputStream = connection.getOutputStream()) {
outputStream.write(postData.getBytes());
outputStream.flush();
}
}
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
return handleResponse(connection, clazz);
} else if (responseCode == HttpURLConnection.HTTP_FORBIDDEN) {
retries++;
log.warn("{} request failed with 403, retrying {}/{} in {} ms...", method, retries, MAX_RETRIES, 10000 * retries);
if (retries == MAX_RETRIES) {
throw new RuntimeException("Max retries reached for " + method + " request. Please try again later.");
}
Thread.sleep(10000L * retries);
} else {
throw new RuntimeException("HTTP " + method + " Request Failed with Error code : " + responseCode);
}
} catch (SocketTimeoutException e) {
retries++;
log.warn("{} request timed out, retrying {}/{} in {} ms...", method, retries, MAX_RETRIES, 10000 * retries);
if (retries == MAX_RETRIES) {
throw new RuntimeException("Max retries reached for " + method + " request.", e);
}
Thread.sleep(10000L * retries);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
return null;
}
private static <T> T handleResponse(HttpURLConnection connection, Class<T> clazz) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
String responseBody = response.toString();
if (clazz == String.class) {
return clazz.cast(responseBody);
} else if (clazz == JSONObject.class) {
return clazz.cast(JSON.parseObject(responseBody));
} else if (clazz == JSONArray.class) {
return clazz.cast(JSON.parseArray(responseBody));
} else {
return JSON.parseObject(responseBody, clazz);
}
} catch (Exception e) {
throw new RuntimeException("Error parsing response", e);
}
}
}
此工具类,可以代码重试,可以根据你想要返回的类型,自定义一个返回类,比较方便快捷。
评论