需要的依赖:

        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

参考视频:

https://www.bilibili.com/video/BV1W54y1s7BZ

1、原生JDK实现的网络请求

这个在狂神的爬虫上面有看到过原生的方式

当时还不明白这个技术其实就是后台的Ajax

    @Test
public void quickStart() throws IOException {
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try { // 原生JDK API 发送请求
String urlString = "https://www.baidu.com/";
URL url = new URL(urlString);
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection; httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("aaa", "123"); inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(inputStreamReader); String line = null;
while (null != ( line = bufferedReader.readLine())) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
}
}

2、使用ApacheHttpClient发送请求:

    @Test
public void useHttpClient() throws IOException {
// 使用 HttpClient Get 无参请求实现 CloseableHttpClient closeableHttpClient = null;
CloseableHttpResponse closeableHttpResponse = null;
HttpEntity httpEntity = null;
try {
// 创建一个可关闭的Http客户端对象
closeableHttpClient = HttpClients.createDefault(); // 要请求的地址
String urlString = "https://www.baidu.com/"; // GET参数需要进行URL编码处理
String param1 = "orderId=21343000123324";
String param2 = "orderRemark=大三大四1王企鹅1 哇多久啊是巴西 &%……¥%";
param1 = URLEncoder.encode(param1, StandardCharsets.UTF_8.name());
param2 = URLEncoder.encode(param2, StandardCharsets.UTF_8.name()); // 根据地址创建一个Http请求对象 这里使用的是GET请求对象
// HttpGet httpGet = new HttpGet(urlString);
HttpGet httpGet = new HttpGet(urlString + "?" + param1 + "&" + param2); // 浏览器伪装信息
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Edg/94.0.992.38"); // 防盗链设置 https://www.jianshu.com/p/0a1338db6cab
httpGet.addHeader("Referer", "https://ntp.msn.cn/"); // 客户端对象带着请求对象 执行请求发送, 返回响应对象
closeableHttpResponse = closeableHttpClient.execute(httpGet); // 可以从响应对象获取对应的响应信息
StatusLine statusLine = closeableHttpResponse.getStatusLine();
System.out.println(statusLine); // HTTP/1.1 200 OK // 响应不成功状态直接结束后续逻辑
if (HttpStatus.SC_OK != statusLine.getStatusCode()) return; ProtocolVersion protocolVersion = statusLine.getProtocolVersion(); // HTTP/1.1
int major = protocolVersion.getMajor(); // 1 主版本协议号
int minor = protocolVersion.getMinor(); // 1 附属小版本协议号
String protocol = protocolVersion.getProtocol(); // HTTP int statusCode = statusLine.getStatusCode(); // 200
String reasonPhrase = statusLine.getReasonPhrase(); // OK Header[] allHeaders = closeableHttpResponse.getAllHeaders();
for (Header header : allHeaders) {
System.out.println("Response Header -> " + header.getName() + " : " + header.getValue());
} // 从响应对象中获取响应实体对象
httpEntity = closeableHttpResponse.getEntity(); Header contentType = httpEntity.getContentType();
String contentTypeName = contentType.getName(); // Content-Type
String contentTypeValue = contentType.getValue(); // Content-Type: text/html;charset=utf-8 // 这个响应头不常见
// Header contentEncoding = httpEntity.getContentEncoding(); // null
// String contentEncodingName = contentEncoding.getName();
// String contentEncodingValue = contentEncoding.getValue(); // 使用实体工具类转换成字符结果
String httpEntityResult = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
// System.out.println(httpEntityResult); } catch (Exception exception) {
exception.printStackTrace();
} finally {
// 最后调用此方法确保资源释放
EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}
}

3、下载图片资源:

    @Test
public void downloadWebPicture() throws Exception { // 请求发送
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
String resource = "https://img.zcool.cn/community/01088b5a052431a801204a0e253198.jpg@1280w_1l_2o_100sh.jpg";
HttpGet httpGet = new HttpGet(resource);
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpGet);
HttpEntity httpEntity = closeableHttpResponse.getEntity(); // 类型解析
Header contentType = httpEntity.getContentType();
String contentTypeValue = contentType.getValue(); // image/jpeg
String fileTypeSuffix = contentTypeValue.split("/")[1]; // jpeg // 文件下载
byte[] bytes = EntityUtils.toByteArray(httpEntity);
String localPath = "C:\\Users\\Administrator\\Desktop\\test." + fileTypeSuffix;
OutputStream outputStream = new FileOutputStream(localPath);
outputStream.write(bytes);
// 资源释放
outputStream.close();
EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

4、配置代理主机:

    @Test
public void proxySettings() throws Exception { CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
String target = "https://www.baidu.com/";
HttpGet httpGet = new HttpGet(target); // 代理主机的信息 http://www.66ip.cn/
String ip = "176.121.1.81";
int port = 8181;
HttpHost httpHost = new HttpHost(ip, port); // 创建请求配置对象
RequestConfig requestConfig = RequestConfig
.custom()
.setProxy(httpHost) // 设置代理主机的信息
.build(); // 设置请求配置
httpGet.setConfig(requestConfig); CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpGet);
HttpEntity httpEntity = closeableHttpResponse.getEntity(); Header[] allHeaders = closeableHttpResponse.getAllHeaders();
for (Header header : allHeaders) {
System.out.println("Response Header -> " + header.getName() + " : " + header.getValue());
} String httpEntityResult = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
System.out.println(httpEntityResult); // 资源释放
EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

5、设置超时相关的配置:

    @Test
public void proxySettings() throws Exception {
// 请求发送
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
String target = "https://www.baidu.com/";
HttpGet httpGet = new HttpGet(target); // 代理主机的信息 http://www.66ip.cn/
String ip = "176.121.1.81";
int port = 8181;
HttpHost httpHost = new HttpHost(ip, port); // 创建请求配置对象
RequestConfig requestConfig = RequestConfig
.custom()
.setProxy(httpHost)
.setConnectTimeout(5000) // 设置连接超时的上限 TCP3次握手的时限
.setSocketTimeout(3000) // 设置读取超时上限 从请求的网址中获取响应数据的间隔时限(因为并不是一次请求就完成了加载)
.setConnectionRequestTimeout(3000) // 从HttpClient连接池中获取connection对象的时限

.build(); // 设置请求配置
httpGet.setConfig(requestConfig); CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpGet);
HttpEntity httpEntity = closeableHttpResponse.getEntity(); Header[] allHeaders = closeableHttpResponse.getAllHeaders();
for (Header header : allHeaders) {
System.out.println("Response Header -> " + header.getName() + " : " + header.getValue());
} String httpEntityResult = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
System.out.println(httpEntityResult); // 资源释放
EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

6、MIME-TYPE 邮件扩展类型 与POST请求

mime-type 就是具体文件类型的前面的所属规范类型

在Tomcat里面配置的web.xml信息就可以看到所有的规范类型了

E:\apache-tomcat-8.5.70\conf\web.xml

片段:

    <mime-mapping>
<extension>zirz</extension>
<mime-type>application/vnd.zul</mime-type>
</mime-mapping>
<mime-mapping>
<extension>zmm</extension>
<mime-type>application/vnd.handheld-entertainment+xml</mime-type>
</mime-mapping>

常见Content-type:

# 一般html表单提交 发送的类型
application/x-www-form-urlencoded # html上传文件规范的类型
multipart/form-data # 目前主流规范的类型
application/json

POST表单类型提交案例:

1、客户端请求代码

    @Test
public void postWithFormType() throws Exception {
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
String target = "http://localhost:8080/mvc-framework/test/testMethod2"; // 首先创建POST请求对象
HttpPost httpPost = new HttpPost(target);
// 设置表单需要提交的参数
List<NameValuePair> nvpList = new ArrayList<>();
nvpList.add(new BasicNameValuePair("username", "张三"));
nvpList.add(new BasicNameValuePair("password", "w123e21")); // 表单类型实体对象 装填参数信息 application/x-www-form-urlencoded
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvpList, Consts.UTF_8); // 设置表单类型实体对象
httpPost.setEntity(urlEncodedFormEntity);
// 客户端执行请求发送
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost);
HttpEntity httpEntity = closeableHttpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity, StandardCharsets.UTF_8)); EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

2、服务器处理代码:

    /**
*
* POST请求测试
* http://localhost:8080/mvc-framework/test/testMethod2
* @param request
* @param response
*/
// @RequestMethod(MethodType.POST)
@RequestMapping(value = "/testMethod2", methodType = MethodType.POST)
public void testMethod2(HttpServletRequest request, HttpServletResponse response) {
System.out.println("testMethod2"); ServletUtil.printAllParamByRequestMap(request); Map<String, Object> requestAttribute = (Map<String, Object>) request.getAttribute(ServletConstants.POST_PARAM_KEY); for (String s : requestAttribute.keySet()) {
System.out.println("postParam " + s + ": " + requestAttribute.get(s));
}
}

服务这里没有对请求做出响应,就是打印看看没有收到参数信息:

doPost detected
doGet detected
testMethod2
username: [张三]
password: [w123e21]
postParam password: w123e21
postParam username: 张三

做了两次打印的原因是第一个打印是直接调用ServletAPI实现:

基本的POST表单请求Servlet有做识别处理

    public static void printAllParamByRequestMap(HttpServletRequest request) {
Map<String, String[]> parameterMap = request.getParameterMap();
for (String s : parameterMap.keySet()) {
System.out.println(s + ": " + Arrays.toString(parameterMap.get(s)));
}
}

第二次打印是从输入流中获取识别的

    /**
* 从POST请求中获取参数
* @param request
* @return
* @throws Exception
*/
public static Map<String, Object> getPostParam(HttpServletRequest request) throws Exception {
// 返回参数
Map<String, Object> params = new HashMap<>(); // 获取内容格式
String contentType = request.getContentType(); if (null == contentType || "".equals(contentType)) throw new ServletException("没有设置请求头项Content-Type!!!");
else contentType = contentType.split(";")[0]; // form表单格式 表单形式可以从 ParameterMap中获取
if (ServletConstants.CONTENT_TYPE_VALUE_URL_ENCODED2.equalsIgnoreCase(contentType)) {
// 获取参数
Map<String, String[]> parameterMap = request.getParameterMap();
if (parameterMap != null) {
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
params.put(entry.getKey(), entry.getValue()[0]);
}
}
}
// json格式 json格式需要从request的输入流中解析获取
if (ServletConstants.CONTENT_TYPE_VALUE_JSON2.equalsIgnoreCase(contentType)) {
// 使用 commons-io中 IOUtils 类快速获取输入流内容
String paramJson = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
Map parseObject = JSON.parseObject(paramJson, Map.class);
params.putAll(parseObject);
} return params ;
}

也可以不使用  UrlEncodedFormEntity  ,使用请求头设置即可

这个意思在视频里说错了,应该是这个Entity已经在Header这么处理了

        // 配置Http请求头
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

因为表单的参数还是需要放到Entity里面发送过去的

这里特意看了下Entity的实现结构:

搜寻Entity相关的时候发现这个博客写的也很好,涉及到Cookie相关的操作

https://www.cnblogs.com/licl11092/p/9075677.html

POST + JSON类型案例:

SpringMVC接受Post JSON数据时要带上 @RequestBody给方法

普通Get参数则是@RequestParam

类注解为@RestController就可以不注解@RequestBody方法

在这里我使用的是封装的一套MVC,Servlet对JSON参数是不支持的,只能从输入流自行获取

这里JSON参数采用的是StringEntity实现存储,看了源码发现默认是text/plain类型,也允许构造器自行设置类型

    @Test
public void postWithFormJson() throws Exception {
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
java.lang.String target = "http://localhost:8080/mvc-framework/test/testMethod2"; // 首先创建POST请求对象
HttpPost httpPost = new HttpPost(target); // 设置需要提交的JSON参数 这里做简单案例,就不去下载Fastjson来转换了,自己手写一个
String jsonParam = "{ \"username\": \"张三\", \"password\": \"w123e21\" }"; // 表单类型实体对象 装填参数信息 application/x-www-form-urlencoded
StringEntity jsonEntity = new StringEntity(jsonParam , Consts.UTF_8); // 配置Http请求头
// httpPost.addHeader("Content-Type", "application/json; charset=UTF-8");
jsonEntity.setContentType(new BasicHeader("Content-Type", "application/json; charset=UTF-8"));
// StringEntity 设置编码
jsonEntity.setContentEncoding(Consts.UTF_8.name());
// 设置JSON实体对象
httpPost.setEntity(jsonEntity); // 客户端执行请求发送
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost);
HttpEntity httpEntity = closeableHttpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity, StandardCharsets.UTF_8)); EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

POST + 文件类型案例:

首先测试Html表单上传文件处理:

上传操作的页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>静态资源访问 3333</h3>
<form action="http://localhost:8080/mvc-framework/test/fileUploadTest" enctype="multipart/form-data" method="post">
<p><label >上传文件</label> <input type="file" name="upload" ></p>
<p><label >用户名</label> <input type="text" name="username"></p>
<input type="submit" value="提交">
</form>
</body>
</html>

Servlet后台:

    /**
* POST数据处理
* http://localhost:8080/mvc-framework/test/fileUploadTest
* @return
*/
@RequestMapping(value = "/fileUploadTest", methodType = MethodType.POST)
public Map<String, Object> fileUploadTest(HttpServletRequest request) throws ServletException, IOException { String contentType = request.getContentType();
// request.setCharacterEncoding("UTF-8"); 注意中文乱码
if (null == contentType || "".equals(contentType)) throw new ServletException("ContentType类型未声明!");
System.out.println(contentType);
if (!contentType.contains("multipart/form-data")) throw new ServletException("ContentType类型不符合文件上传的要求!"); //获取上传的文件集合(应该是所有表单数据封装成的part对象集合)
Collection<Part> parts = request.getParts();
if(null == parts) throw new ServletException("没有需要上传的文件!");
for (Part part : parts) { //Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition"); // 注意这个part只有文件才会有 filename属性
if (!header.contains("filename")) continue; /**
* 每个浏览器的输出情况
* Edge -> form-data; name="upload"; filename="QQ截图20210817220501.png"
* 360极速 -> form-data; name="upload"; filename="C:\Users\Administrator\Pictures\QQ截图20210820005513.png"
* 火狐 -> form-data; name="upload"; filename="QQ截图20210817220501.png"
* 谷歌 -> form-data; name="upload"; filename="QQ截图20210817220501.png"
* IE -> form-data; name="upload"; filename="C:\Users\Administrator\Pictures\QQ截图20210817220501.png"
*/ // 取得文件名称与后缀信息
String[] nameWithSuffix = ServletUtil.getFileNameWithSuffix(header); // 获取本地位置:
String savePath = request.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println(savePath); // 如果这个路径没有就创建一个出来
File storagePosition = new File(savePath);
if (!storagePosition.exists()) storagePosition.mkdirs(); // mkdirs 允许创建多层级目录 // 输出写入到本地
part.write(savePath + File.separator + nameWithSuffix[0]);
} Map<String, Object> res = new HashMap<>();
res.put("status", 200);
res.put("msg", "OK");
res.put("data", "文件上传成功!!!");
return res;
}

注意,这里我发现原来是没有使用Servlet3.0提供的内容来解决文件上传下载的

用的ApacheCommonsIO + FileUpload

后来才知道3.0已经提供文件上传的一些功能:

@MultipartConfig注解,注解在你需要做文件上传的Servlet类上面

package javax.servlet.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MultipartConfig {
String location() default ""; long maxFileSize() default -1L; long maxRequestSize() default -1L; int fileSizeThreshold() default 0;
}

当你想从Servlet获取上传的文件,但是没有声明此注解

Tomcat会报错:

由于没有提供multi-part配置,无法处理parts

类同SpringMVC一样

由于我是封装的MVC框架,所有Servlet处理的后台在DispatchServlet中调用

所以对他配置注解:

@MultipartConfig
public class DispatchServlet extends HttpServlet { // private Class<?> thisClass = this.getClass(); private static Mapping currentMapping;
private static Map<String, Mapping> allRequestMapping;
public static final String REDIRECT = "redirect:";
public static String dispatchPath = "/WEB-INF/jsp/";
public static String fileSuffix = ".jsp";

下面是后台逻辑:

    /**
* POST数据处理
* http://localhost:8080/mvc-framework/test/fileUploadTest
* @return
*/
@RequestMapping(value = "/fileUploadTest", methodType = MethodType.POST)
public Map<String, Object> fileUploadTest(HttpServletRequest request) throws ServletException, IOException { String contentType = request.getContentType();
// request.setCharacterEncoding("UTF-8"); 注意中文乱码
if (null == contentType || "".equals(contentType)) throw new ServletException("ContentType类型未声明!");
System.out.println(contentType);
if (!contentType.contains("multipart/form-data")) throw new ServletException("ContentType类型不符合文件上传的要求!"); //获取上传的文件集合(应该是所有表单数据封装成的part对象集合)
Collection<Part> parts = request.getParts();
if(null == parts) throw new ServletException("没有需要上传的文件!");
for (Part part : parts) { //Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition"); // 注意这个part只有文件才会有 filename属性
if (!header.contains("filename")) continue; /**
* 每个浏览器的输出情况
* Edge -> form-data; name="upload"; filename="QQ截图20210817220501.png"
* 360极速 -> form-data; name="upload"; filename="C:\Users\Administrator\Pictures\QQ截图20210820005513.png"
* 火狐 -> form-data; name="upload"; filename="QQ截图20210817220501.png"
* 谷歌 -> form-data; name="upload"; filename="QQ截图20210817220501.png"
* IE -> form-data; name="upload"; filename="C:\Users\Administrator\Pictures\QQ截图20210817220501.png"
*/
// 取得文件名称与后缀信息
String[] nameWithSuffix = ServletUtil.getFileNameWithSuffix(header); // 获取本地位置:
String savePath = request.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println(savePath); // 如果这个路径没有就创建一个出来
File storagePosition = new File(savePath);
if (!storagePosition.exists()) storagePosition.mkdirs(); // mkdirs 允许创建多层级目录 // 输出写入到本地
part.write(savePath + File.separator + nameWithSuffix[0
]);
} Map<String, Object> res = new HashMap<>();
res.put("status", 200);
res.put("msg", "OK");
res.put("data", "文件上传成功!!!");
return res;
}

这个功能比之前的Apache封装要简单多了

直接可以输出写入到本地

追加上获取文件名的办法:

    public static String[] getFileNameWithSuffix(String partHeader) throws ServletException {
String[] fileNameArr = new String[2];
if(!partHeader.contains("filename")) throw new ServletException("找不到文件名称");
String filename = partHeader.split("filename")[1]; filename = filename.replace("=", "");
filename = filename.replace("\"", "");
if (filename.contains("\\")) { // 例如IE的情况,带有绝对路径信息
filename = filename.substring(filename.lastIndexOf("\\"));
}
fileNameArr[0] = filename;
fileNameArr[1] = filename.substring(filename.lastIndexOf("."));
return fileNameArr;
}

视频里面用的IE浏览器,可以抓到这个Content-Disposition 信息

但是我用Edge是看不到的

同样用IE看也没有。。。

使用HttpClient实现文件上传:

需要新增一个MIME依赖:

        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>

客户端代码:

    @Test
public void postWithFormMultiPart() throws Exception {
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
java.lang.String target = "http://localhost:8080/mvc-framework/test/fileUploadTest"; // 首先创建POST请求对象
HttpPost httpPost = new HttpPost(target); // 创建文件上传实体对象
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); HttpEntity httpEntity = multipartEntityBuilder
// 设置ContentType 类型
.setContentType(ContentType.MULTIPART_FORM_DATA)
// 设置编码,编码重置
.setCharset(Consts.UTF_8)
// 设置模式(浏览器模式)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
// 添加附件
.addBinaryBody("project-repo.txt", new File("C:\\Users\\Administrator\\Desktop\\project-repo.txt"))
// 添加part附件
.addPart("partFile", new FileBody(new File("C:\\Users\\Administrator\\Pictures\\QQplayerPic\\4[00_00_50][20210919-092125].png")))
// 添加文本附件 但是文本附件不会被上传到服务器里面 原因可能是不具备filename
.addTextBody("txtBody1", "张三")
.addTextBody("txtBody2", "1qwdasx")
.build();
// 设置文件上传实体对象
httpPost.setEntity(httpEntity);
// 客户端执行请求发送
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost);
httpEntity = closeableHttpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity, StandardCharsets.UTF_8)); EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

关于addPart下面一个重载方法:

客户端响应:

{"msg":"OK","data":"文件上传成功!!!","status":200}

服务器只触发了两次:

说明下面的两个textBody是不识别的,因为我设置了方法

doPost detected
doGet detected
multipart/form-data; boundary=0Oz1eCUwv_bwYAEDfOi5K-s4DshztEqsLWsW5; charset=UTF-8
C:\Users\Administrator\IdeaProjects\MVC-Framework\out\artifacts\MVC_Framwork\WEB-INF\upload
C:\Users\Administrator\IdeaProjects\MVC-Framework\out\artifacts\MVC_Framwork\WEB-INF\upload

我放开打印再看看结果:

可以看到文本体就是没有filename的存在

form-data; name="project-repo.txt"; filename="project-repo.txt"
C:\Users\Administrator\IdeaProjects\MVC-Framework\out\artifacts\MVC_Framwork\WEB-INF\upload
form-data; name="partFile"; filename="4[00_00_50][20210919-092125].png"
C:\Users\Administrator\IdeaProjects\MVC-Framework\out\artifacts\MVC_Framwork\WEB-INF\upload
form-data; name="txtBody1"
form-data; name="txtBody2"

也就是textBody相当于input标签,设置类型type="text"了

这里存在一个中文乱码的问题,并不是过滤器能够解决的了

txtBody1: [??]
txtBody2: [1qwdasx]

客户端发送就会乱码

因为建造器不支持对应的中文字符

// 添加文本附件 但是文本附件不会被上传到服务器里面 原因可能是不具备filename
.addTextBody("txtBody1", "张三")
.addTextBody("txtBody2", "1qwdasx")

需要这样编写:

// 添加文本附件 但是文本附件不会被上传到服务器里面 原因可能是不具备filename
.addPart("txtBody1", new StringBody("张三", ContentType.create("text/plain", Consts.UTF_8)))
.addTextBody("txtBody2", "1qwdasx")

再打印就正常了:

doPost detected
doGet detected
txtBody1: [张三]
txtBody2: [1qwdasx]
multipart/form-data; boundary=VBLteRGDXG2JWQyo3e3o7Ez8Wzzzb-u4fOURku0; charset=UTF-8
form-data; name="project-repo.txt"; filename="project-repo.txt"
C:\Users\Administrator\IdeaProjects\MVC-Framework\out\artifacts\MVC_Framwork\WEB-INF\upload
form-data; name="partFile"; filename="4[00_00_50][20210919-092125].png"
C:\Users\Administrator\IdeaProjects\MVC-Framework\out\artifacts\MVC_Framwork\WEB-INF\upload
form-data; name="txtBody1"
form-data; name="txtBody2"

7、HTTPS安全认证越过:

这里借用JSON的那个请求测试

唯一的区别是请求地址追加了s,使用HTTPS认证

然后客户端请求就会报错

    @Test
public void sslCross() throws Exception {
CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
java.lang.String target = "https://localhost:8080/mvc-framework/test/testMethod2"; // 首先创建POST请求对象
HttpPost httpPost = new HttpPost(target); // 设置需要提交的JSON参数 这里做简单案例,就不去下载Fastjson来转换了,自己手写一个
String jsonParam = "{ \"username\": \"张三\", \"password\": \"w123e21\" }"; // 表单类型实体对象 装填参数信息 application/x-www-form-urlencoded
StringEntity jsonEntity = new StringEntity(jsonParam , Consts.UTF_8); // 配置Http请求头
// httpPost.addHeader("Content-Type", "application/json; charset=UTF-8");
jsonEntity.setContentType(new BasicHeader("Content-Type", "application/json; charset=UTF-8"));
// StringEntity 设置编码
jsonEntity.setContentEncoding(Consts.UTF_8.name()); // 设置JSON实体对象
httpPost.setEntity(jsonEntity); // 客户端执行请求发送
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost);
HttpEntity httpEntity = closeableHttpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity, StandardCharsets.UTF_8)); EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

报错信息:

"C:\Program Files (x86)\Java\jdk1.8.0_291\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=60373:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\plugins\junit\lib\junit-rt.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\charsets.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\deploy.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\access-bridge-32.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\cldrdata.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\dnsns.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\jaccess.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\jfxrt.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\localedata.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\nashorn.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunec.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunjce_provider.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunmscapi.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunpkcs11.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\zipfs.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\javaws.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jce.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jfr.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jfxswt.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jsse.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\management-agent.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\plugin.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\resources.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\rt.jar;C:\Users\Administrator\IdeaProjects\Anything\Framework\target\test-classes;C:\Users\Administrator\IdeaProjects\Anything\Framework\target\classes;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpclient\4.5.13\httpclient-4.5.13.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpcore\4.4.12\httpcore-4.4.12.jar;C:\Users\Administrator\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\Users\Administrator\.m2\repository\commons-codec\commons-codec\1.13\commons-codec-1.13.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpmime\4.5.13\httpmime-4.5.13.jar;C:\Users\Administrator\.m2\repository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;C:\Users\Administrator\.m2\repository\javax\servlet\jstl\1.2\jstl-1.2.jar;C:\Users\Administrator\.m2\repository\javax\servlet\jsp\javax.servlet.jsp-api\2.3.3\javax.servlet.jsp-api-2.3.3.jar;C:\Users\Administrator\.m2\repository\org\reflections\reflections\0.9.11\reflections-0.9.11.jar;C:\Users\Administrator\.m2\repository\com\google\guava\guava\20.0\guava-20.0.jar;C:\Users\Administrator\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest-core\2.1\hamcrest-core-2.1.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest\2.1\hamcrest-2.1.jar;C:\Users\Administrator\.m2\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar;C:\Users\Administrator\.m2\repository\commons-beanutils\commons-beanutils\1.7.0\commons-beanutils-1.7.0.jar;C:\Users\Administrator\.m2\repository\org\javassist\javassist\3.26.0-GA\javassist-3.26.0-GA.jar;C:\Users\Administrator\.m2\repository\com\alibaba\fastjson\1.2.78\fastjson-1.2.78.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 HttpClientTest,sslCross

javax.net.ssl.SSLException: Unsupported or unrecognized SSL message at sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(SSLSocketInputRecord.java:448)
at sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:174)
at sun.security.ssl.SSLTransport.decode(SSLTransport.java:110)
at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1290)
at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1199)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:401)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:373)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
at HttpClientTest.sslCross(HttpClientTest.java:348)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54
) Process finished with exit code -1

同样服务器也报错:

05-Oct-2021 14:40:01.846 信息 [http-nio-8080-exec-6] org.apache.coyote.http11.Http11Processor.service 解析 HTTP 请求 header 错误
注意:HTTP请求解析错误的进一步发生将记录在DEBUG级别。
java.lang.IllegalArgumentException: 在方法名称中发现无效的字符串, HTTP 方法名必须是有效的符号.
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:434)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:511)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1650)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

这里没证书,一笔带过了,直接上代码:

主要是对客户端设置相关的SSL机制,其余的都是一样使用

    @Test
public void sslCross() throws Exception { SSLContextBuilder sslContextBuilder = new SSLContextBuilder(); sslContextBuilder.loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true;
}
}); SSLContext sslContext = sslContextBuilder.build(); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{
"SSLv2Hello",
"SSLv3",
"TLSv1",
"TLSv1.1",
"TLSv1.2"
},
null,
NoopHostnameVerifier.INSTANCE
); Registry<ConnectionSocketFactory> registry = RegistryBuilder
.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslConnectionSocketFactory)
.build(); PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry); // 客户端对象需要定制化
HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(poolingHttpClientConnectionManager); CloseableHttpClient closeableHttpClient =
httpClientBuilder.build(); java.lang.String target = "https://localhost:8080/mvc-framework/test/testMethod2"; // 首先创建POST请求对象
HttpPost httpPost = new HttpPost(target); // 设置需要提交的JSON参数 这里做简单案例,就不去下载Fastjson来转换了,自己手写一个
String jsonParam = "{ \"username\": \"张三\", \"password\": \"w123e21\" }"; // 表单类型实体对象 装填参数信息 application/x-www-form-urlencoded
StringEntity jsonEntity = new StringEntity(jsonParam , Consts.UTF_8); // 配置Http请求头
// httpPost.addHeader("Content-Type", "application/json; charset=UTF-8");
jsonEntity.setContentType(new BasicHeader("Content-Type", "application/json; charset=UTF-8"));
// StringEntity 设置编码
jsonEntity.setContentEncoding(Consts.UTF_8.name()); // 设置JSON实体对象
httpPost.setEntity(jsonEntity); // 客户端执行请求发送
CloseableHttpResponse closeableHttpResponse = closeableHttpClient.execute(httpPost);
HttpEntity httpEntity = closeableHttpResponse.getEntity();
System.out.println(EntityUtils.toString(httpEntity, StandardCharsets.UTF_8)); EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
}

8、连接池与工具封装

package cn.dzz.framework.util;

import org.apache.http.*;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext;
import javax.servlet.ServletException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; public class HttpClientUtil { private static final HttpClientBuilder httpClientBuilder = HttpClients.custom(); static {
try {
// 连接管理器
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true;
}
}); SSLContext sslContext = sslContextBuilder.build(); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{
"SSLv2Hello",
"SSLv3",
"TLSv1",
"TLSv1.1",
"TLSv1.2"
},
null,
NoopHostnameVerifier.INSTANCE
); Registry<ConnectionSocketFactory> registry = RegistryBuilder
.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslConnectionSocketFactory)
.build(); PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
poolingHttpClientConnectionManager.setMaxTotal(50);// 连接池最大连接数量
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(50); // 每个路由的默认连接 路由 = ip + port httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager); // 请求默认配置
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectTimeout(6000)
.setSocketTimeout(3000)
.setConnectionRequestTimeout(6000)
.build();
httpClientBuilder.setDefaultRequestConfig(requestConfig); // 默认请求头配置
List<Header> headerList = new ArrayList<>();
BasicHeader agentHeader = new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Edg/94.0.992.38"); headerList.add(agentHeader);
httpClientBuilder.setDefaultHeaders(headerList); } catch (Exception e) {
e.printStackTrace();
}
} /**
* 发送GET请求
* @param url
* @param headers
* @return
*/
public static String executeGetRequest(String url, Map<String, String> headers) {
CloseableHttpClient closeableHttpClient = null;
CloseableHttpResponse closeableHttpResponse = null;
HttpEntity httpEntity = null;
String resJson = null;
try {
closeableHttpClient = httpClientBuilder.build(); // 配置请求地址
HttpGet httpGet = new HttpGet(url); // 配置请求头信息
for (String key : headers.keySet()) httpGet.addHeader(key, headers.get(key)); // 请求发送
closeableHttpResponse = closeableHttpClient.execute(httpGet); // 状态判定
StatusLine statusLine = closeableHttpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
if ( ! isSuccessRequest(statusCode)) throw new ServletException(url + " 请求失败, " + statusLine); httpEntity = closeableHttpResponse.getEntity();
resJson = EntityUtils.toString(httpEntity);
} catch (Exception exception) {
exception.printStackTrace();
return null;
} finally {
try {
EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
} catch (Exception exception) {
exception.printStackTrace();
}
}
return resJson;
} /**
* 发送POST请求
* @param url
* @param headers
* @return
*/
public static String executeGetRequest(String url, String json, Map<String, String> headers) {
CloseableHttpClient closeableHttpClient = null;
CloseableHttpResponse closeableHttpResponse = null;
HttpEntity httpEntity = null;
String resJson = null;
try {
closeableHttpClient = httpClientBuilder.build(); // 配置请求地址
HttpPost httpPost = new HttpPost(url); // 配置请求头信息
for (String key : headers.keySet()) httpPost.addHeader(key, headers.get(key));
httpPost.addHeader("Content-Type", "application/json; charset=UTF-8"); // 请求体设置
StringEntity jsonEntity = new StringEntity(json, Consts.UTF_8);
jsonEntity.setContentEncoding(Consts.UTF_8.name());
jsonEntity.setContentType("application/json; charset=UTF-8");
httpPost.setEntity(jsonEntity); // 请求发送
closeableHttpResponse = closeableHttpClient.execute(httpPost); // 状态判定
StatusLine statusLine = closeableHttpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
if ( ! isSuccessRequest(statusCode)) throw new ServletException(url + " 请求失败, " + statusLine); httpEntity = closeableHttpResponse.getEntity();
resJson = EntityUtils.toString(httpEntity);
} catch (Exception exception) {
exception.printStackTrace();
return null;
} finally {
try {
EntityUtils.consume(httpEntity);
closeableHttpResponse.close();
closeableHttpClient.close();
} catch (Exception exception) {
exception.printStackTrace();
}
}
return resJson;
} /**
* 这里判定条件宽泛,只要是2和3都算请求成功
* @param statusCode
* @return
*/
public static boolean isSuccessRequest(int statusCode) {
boolean flag = false;
switch (statusCode) {
// 2XX状态
case HttpStatus.SC_OK:
case HttpStatus.SC_CREATED:
case HttpStatus.SC_ACCEPTED:
case HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION:
case HttpStatus.SC_NO_CONTENT:
case HttpStatus.SC_RESET_CONTENT:
case HttpStatus.SC_PARTIAL_CONTENT:
case HttpStatus.SC_MULTI_STATUS:
case HttpStatus.SC_MULTIPLE_CHOICES:
// 3XX状态
case HttpStatus.SC_MOVED_PERMANENTLY:
case HttpStatus.SC_MOVED_TEMPORARILY:
case HttpStatus.SC_SEE_OTHER:
case HttpStatus.SC_NOT_MODIFIED:
case HttpStatus.SC_USE_PROXY:
case HttpStatus.SC_TEMPORARY_REDIRECT:
flag = true;
break;
default:
}
return flag;
}
}

【JavaWeb】HttpClient的更多相关文章

  1. 【JavaWeb】EL表达式&过滤器&监听器

    EL表达式和JSTL EL表达式 EL表达式概述 基本概念 EL表达式,全称是Expression Language.意为表达式语言.它是Servlet规范中的一部分,是JSP2.0规范加入的内容.其 ...

  2. 【JavaWeb】【JSP】【Bean】JavaBean基础使用方法与操作步骤

    JavaBean基础使用方法与操作步骤 JavaWeb jsp Bean 项目结构 JavaBean的概念 JavaBean是可复用的.平台独立的软件组件 JavaBean既可以是简单的GUI要素,如 ...

  3. 【Javaweb】poi实现通过上传excel表格批量导入数据到数据库

    1.导入poi相关jar包 对于只操作2003及以前版本的excel,只需要导入poi-XXX.jar ,如果还需要对2007及以后版本进行操作,则需要导入 poi-ooxml-XXX.jar poi ...

  4. 【JavaWeb】SpringBoot架构

    0.文件夹结构 1.接口统一返回值 2.全局异常处理 3.数据库访问配置[OK] 4.前端模版页[OK] 5.Swagger接口[OK] 6.公共插件[OK] ---lombok ---google ...

  5. 【JavaWeb】书城项目

    书城网站 项目说明 项目地址 阶段一 登录.注册的验证 使用 jQuery 技术对登录中的用户名.密码进行非空验证: 使用 jQuery 技术和正则表达式对注册中的用户名.密码.确认密码.邮箱进行格式 ...

  6. 【java】httpclient的使用之java代码内发送http请求

    场景: 需要本项目发送HTTP请求到另一个项目中,处理完成返回值给本项目. 1.本项目引入架包 <!-- httpclient 后台发送http请求--> <dependency&g ...

  7. 【JavaWeb】SSM+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(六)

    Showings 我个人的项目,当前不断地在更新. 我希望做成一个好项目,同时,也是在锻炼自己的技术. 在项目中发现问题,学习知识,是比较可取的一条路子. 这样学习到的知识,虽然分散,但是都很实用,而 ...

  8. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(五)

    SpringSecurity(2) 好久没有写了,之前只写了一半,我是一边开发一边写Blog一边上班,所以真心没有那么多时间来维护Blog,项目已经开发到编写逻辑及页面部分了,框架基本上已经搭建好不会 ...

  9. 【JavaWeb】客户关系管理系统

    前言 为了巩固开发的流程,我们再拿一个客户关系管理系统来练手...! 成果图 我们完成的就是下面的项目! 搭建配置环境 配置Tomcat 导入开发包 建立开发用到的程序包 在数据库创建相对应的表 CR ...

  10. 【JavaWeb】权限管理系统

    前言 前面我们做的小项目都是一个表的,业务代码也相对简单.现在我们来做一个权限管理系统,体验一下多表的业务逻辑,顺便巩固一下过滤器的知识.! 目的 现在我有一个管理商品.订单的页面.当用户点击某个超链 ...

随机推荐

  1. 三大显卡厂商(Intel NVIDIA AMD)产品对硬件解码编码支持程度列表

    三大显卡厂商(Intel NVIDIA AMD)产品对硬件解码编码支持程度列表 以下全部为重庆Debug原创博客园独发,资料收集不易,贵请珍惜,更新日期2023年6月8日 Intel GPU解码编码的 ...

  2. INFINI Easysearch 与兆芯完成产品兼容互认证

    近日,极限科技旗下软件产品 INFINI Easysearch 搜索引擎软件 V1.0 与兆芯完成兼容性测试,功能与稳定性良好,并获得兆芯产品兼容互认证书. 此次兼容适配基于银河麒麟高级服务器操作系统 ...

  3. 刀剑英雄 刀剑Online 双开 多开 窗口在后台 画面不动

    刀剑英雄 刀剑Online 双开 多开 窗口在后台 画面不动 解决方法: 进游戏前,在游戏设置中,选择"后台渲染",然后再进游戏.

  4. # android studio启动虚拟机长时间无响应,无法启动

    问题 虚拟设备长时间不响应,无法启动设备 方案 根据 android studio启动虚拟器失败 尝试删除锁文件 失败,.android 目录下不存在锁文件 电脑内存或计算配置不足 查看了模拟器需要的 ...

  5. MySQL GROUP BY 用法介绍

    MySQL 中 GROUP BY 用法 简介 GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. 可以把 分组理解成 Excel 中的分组. 把 合计函数理解成 Excel 中 ...

  6. 记一次 React context 使用

    学习 React 之 Context 使用 记录一次React context 使用 React.createContext Api 新建文件 contexts.js 文件用来存放 context 对 ...

  7. linux安装redis完整步骤

    linux安装redis完整步骤 安装:1.获取redis资源 wget http://download.redis.io/releases/redis-4.0.8.tar.gz 2.解压 tar x ...

  8. 【解决方案】Java 互联网项目中消息通知系统的设计与实现(上)

    目录 前言 一.需求分析 1.1发送通知 1.2撤回通知 1.3通知消息数 1.4通知消息列表 二.数据模型设计 2.1概念模型 2.2逻辑模型 三.关键流程设计 本篇小结 前言 消息通知系统(not ...

  9. [OC]一个括号新建一个类

    [OC]一个括号新建一个类 特别说明 以下代码仅仅用于说明用途,命名也不是特别规范,小朋友不要模仿哦. 前言 在iOS开发中,我们会经常用到这么一段代码: UIView *myView = [UIVi ...

  10. .NET App 与Windows系统媒体控制(SMTC)交互

    当你使用Edge等浏览器或系统软件播放媒体时,Windows控制中心就会出现相应的媒体信息以及控制播放的功能,如图. SMTC (SystemMediaTransportControls) 是一个Wi ...