• 【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.70confweb.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:UsersAdministratorPicturesQQ截图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:UsersAdministratorPicturesQQ截图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:UsersAdministratorPicturesQQ截图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:UsersAdministratorPicturesQQ截图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:UsersAdministratorIdeaProjectsMVC-FrameworkoutartifactsMVC_FramworkWEB-INFupload
    C:UsersAdministratorIdeaProjectsMVC-FrameworkoutartifactsMVC_FramworkWEB-INFupload

    我放开打印再看看结果:

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

    form-data; name="project-repo.txt"; filename="project-repo.txt"
    C:UsersAdministratorIdeaProjectsMVC-FrameworkoutartifactsMVC_FramworkWEB-INFupload
    form-data; name="partFile"; filename="4[00_00_50][20210919-092125].png"
    C:UsersAdministratorIdeaProjectsMVC-FrameworkoutartifactsMVC_FramworkWEB-INFupload
    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:UsersAdministratorIdeaProjectsMVC-FrameworkoutartifactsMVC_FramworkWEB-INFupload
    form-data; name="partFile"; filename="4[00_00_50][20210919-092125].png"
    C:UsersAdministratorIdeaProjectsMVC-FrameworkoutartifactsMVC_FramworkWEB-INFupload
    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)Javajdk1.8.0_291injava.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2021.2.1libidea_rt.jar=60373:C:Program FilesJetBrainsIntelliJ IDEA 2021.2.1in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJetBrainsIntelliJ IDEA 2021.2.1libidea_rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2021.2.1pluginsjunitlibjunit5-rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2021.2.1pluginsjunitlibjunit-rt.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibcharsets.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibdeploy.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextaccess-bridge-32.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextcldrdata.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextdnsns.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextjaccess.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextjfxrt.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextlocaledata.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibext
    ashorn.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextsunec.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextsunjce_provider.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextsunmscapi.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextsunpkcs11.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibextzipfs.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibjavaws.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibjce.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibjfr.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibjfxswt.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibjsse.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibmanagement-agent.jar;C:Program Files (x86)Javajdk1.8.0_291jrelibplugin.jar;C:Program Files (x86)Javajdk1.8.0_291jrelib
    esources.jar;C:Program Files (x86)Javajdk1.8.0_291jrelib
    t.jar;C:UsersAdministratorIdeaProjectsAnythingFramework	arget	est-classes;C:UsersAdministratorIdeaProjectsAnythingFramework	argetclasses;C:UsersAdministrator.m2
    epositoryorgapachehttpcomponentshttpclient4.5.13httpclient-4.5.13.jar;C:UsersAdministrator.m2
    epositoryorgapachehttpcomponentshttpcore4.4.12httpcore-4.4.12.jar;C:UsersAdministrator.m2
    epositorycommons-loggingcommons-logging1.2commons-logging-1.2.jar;C:UsersAdministrator.m2
    epositorycommons-codeccommons-codec1.13commons-codec-1.13.jar;C:UsersAdministrator.m2
    epositoryorgapachehttpcomponentshttpmime4.5.13httpmime-4.5.13.jar;C:UsersAdministrator.m2
    epositoryjavaxservletjavax.servlet-api4.0.1javax.servlet-api-4.0.1.jar;C:UsersAdministrator.m2
    epositoryjavaxservletjstl1.2jstl-1.2.jar;C:UsersAdministrator.m2
    epositoryjavaxservletjspjavax.servlet.jsp-api2.3.3javax.servlet.jsp-api-2.3.3.jar;C:UsersAdministrator.m2
    epositoryorg
    eflections
    eflections.9.11
    eflections-0.9.11.jar;C:UsersAdministrator.m2
    epositorycomgoogleguavaguava20.0guava-20.0.jar;C:UsersAdministrator.m2
    epositoryjunitjunit4.12junit-4.12.jar;C:UsersAdministrator.m2
    epositoryorghamcresthamcrest-core2.1hamcrest-core-2.1.jar;C:UsersAdministrator.m2
    epositoryorghamcresthamcrest2.1hamcrest-2.1.jar;C:UsersAdministrator.m2
    epositorycommons-iocommons-io2.11.0commons-io-2.11.0.jar;C:UsersAdministrator.m2
    epositorycommons-beanutilscommons-beanutils1.7.0commons-beanutils-1.7.0.jar;C:UsersAdministrator.m2
    epositoryorgjavassistjavassist3.26.0-GAjavassist-3.26.0-GA.jar;C:UsersAdministrator.m2
    epositorycomalibabafastjson1.2.78fastjson-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;
        }
    }

     

  • 相关阅读:
    揭开正则表达式的神秘面纱
    海量数据库的查询优化及分页算法方案
    ASP.NET纯数字验证码
    ASP.NET四种页面导航方式之比较与选择
    C#数据结构之队列
    if exists
    使用tfs online做代码片段笔记管理
    强制删除数据库
    C# GetType()
    TreeView
  • 原文地址:https://www.cnblogs.com/mindzone/p/15367993.html
Copyright © 2020-2023  润新知