【JavaWeb】HttpClient
需要的依赖:
<!-- 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的更多相关文章
- 【JavaWeb】EL表达式&过滤器&监听器
EL表达式和JSTL EL表达式 EL表达式概述 基本概念 EL表达式,全称是Expression Language.意为表达式语言.它是Servlet规范中的一部分,是JSP2.0规范加入的内容.其 ...
- 【JavaWeb】【JSP】【Bean】JavaBean基础使用方法与操作步骤
JavaBean基础使用方法与操作步骤 JavaWeb jsp Bean 项目结构 JavaBean的概念 JavaBean是可复用的.平台独立的软件组件 JavaBean既可以是简单的GUI要素,如 ...
- 【Javaweb】poi实现通过上传excel表格批量导入数据到数据库
1.导入poi相关jar包 对于只操作2003及以前版本的excel,只需要导入poi-XXX.jar ,如果还需要对2007及以后版本进行操作,则需要导入 poi-ooxml-XXX.jar poi ...
- 【JavaWeb】SpringBoot架构
0.文件夹结构 1.接口统一返回值 2.全局异常处理 3.数据库访问配置[OK] 4.前端模版页[OK] 5.Swagger接口[OK] 6.公共插件[OK] ---lombok ---google ...
- 【JavaWeb】书城项目
书城网站 项目说明 项目地址 阶段一 登录.注册的验证 使用 jQuery 技术对登录中的用户名.密码进行非空验证: 使用 jQuery 技术和正则表达式对注册中的用户名.密码.确认密码.邮箱进行格式 ...
- 【java】httpclient的使用之java代码内发送http请求
场景: 需要本项目发送HTTP请求到另一个项目中,处理完成返回值给本项目. 1.本项目引入架包 <!-- httpclient 后台发送http请求--> <dependency&g ...
- 【JavaWeb】SSM+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(六)
Showings 我个人的项目,当前不断地在更新. 我希望做成一个好项目,同时,也是在锻炼自己的技术. 在项目中发现问题,学习知识,是比较可取的一条路子. 这样学习到的知识,虽然分散,但是都很实用,而 ...
- 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(五)
SpringSecurity(2) 好久没有写了,之前只写了一半,我是一边开发一边写Blog一边上班,所以真心没有那么多时间来维护Blog,项目已经开发到编写逻辑及页面部分了,框架基本上已经搭建好不会 ...
- 【JavaWeb】客户关系管理系统
前言 为了巩固开发的流程,我们再拿一个客户关系管理系统来练手...! 成果图 我们完成的就是下面的项目! 搭建配置环境 配置Tomcat 导入开发包 建立开发用到的程序包 在数据库创建相对应的表 CR ...
- 【JavaWeb】权限管理系统
前言 前面我们做的小项目都是一个表的,业务代码也相对简单.现在我们来做一个权限管理系统,体验一下多表的业务逻辑,顺便巩固一下过滤器的知识.! 目的 现在我有一个管理商品.订单的页面.当用户点击某个超链 ...
随机推荐
- 荣耀无5G开关,荣耀手机,荣耀80GT
荣耀无5G开关,荣耀手机,荣耀80GT. Magic OS 版本号是:7.0.0.138(C00E135R2P6). 解决方法: 1.进入设置-关于手机-连续点击7次版本号. 会提示,开发者选项已开启 ...
- 实时数据同步Inofity、sersync、lsyncd
数据备份方案 企业网站和应用都得有完全的数据备份方案确保数据不丢失,通常企业有如下的数据备份方案 定时任务定期备份 需要周期性备份的数据可以分两类: 后台程序代码.运维配置文件修改,一般会定时任务执行 ...
- Java学习笔记 - 单例模式
概述 单例模式是一种创建者模式.当我们需要确保系统中某个类仅能存在一个对象时,比如:全局信息类例如当项目启动时我们将一个配置文件读取为一个Config类的实例从而在业务逻辑中通过操作对象读取配置.无状 ...
- 三月十五号 anaconda 安装 tensorflow 教程
今天下载anaconda 并安装tensorflow 首先下载anaconda 因为官网下载特别慢 所有选择国内镜像网站 https://mirrors.tuna.tsinghua.edu.cn/a ...
- vue2 混入 (mixin) 带来的小惊喜
最近在review自己写的代码时发现,在很多的地方都用了以下的代码块 1 async initCode() { 2 const resSource = await this.$API.syscode. ...
- mysql ON DUPLICATE KEY UPDATE 演示
<e>查询:INSERT INTO member_test(mem_no,flag)VALUE('111','1') 错误代码: 1062Duplicate entry '111' for ...
- springboot3使用validation进行参数验证
前言 今天学习了使用validation整合springboot进行字段的校验,体验下来感觉很不错,有了validation可以省下一大堆控制器里面的数据校验,例如前端发送了一个请求到我们后端,请 ...
- Centos编译加载toa模块
什么是toa模块 toa模块是为了让后端的realserver能够看到真实的clientip而不是lvs的dip 安装步骤 安装依赖包 yum -y install kernel-devel gcc ...
- CLR via C# 笔记 -- 字符、字符串、文本处理(14)
1. 字符串一经创建,便不能以任何方式修改,只能修改引用. 2. ToLowerInvariant() 和 ToUpperInvariant() 以忽略语言文化的方式将字符串转换为小写或大写形式.性能 ...
- Android 7 默认声音/大小修改
背景 客户机器默认的开机声音一直很大:客户觉得无法接受,需要改小点. 基于Android 7的代码 前言 一般主要通过系统层来进行修改. 在系统关于音频的有关代码中,定义了两个数组: 注意,这些代码根 ...