springboot之httpClient使用

1 篇文章 0 订阅


使用前景,项目是springcloud项目,想调用外部一个服务,这个服务不会注入到我的注册中心去,我也不知道他是个啥玩意,就知道是个java服务,springcloud自带的Ribbon+RestTemplate或者Feign都是rpc远程调用技术,但是分装了,我本来想使用spring的restTemplate,并配置该客户端工程,设置连接时间,但是启动会报错,影响该springcoud的内部配置,会报错,配置代码如下,如果不用cloud,使用springboot就可以

restTemplate

 

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * @version 0.0.1
 * @program: fuse-system
 * @description: 普通服务之间调用配置类
 * https://www.cnblogs.com/eternityz/p/12241380.html
 * @author: huangzq
 * @create: 2021-01-08 09:24
 */
@Configuration
public class RestTemplateConfig extends RibbonAutoConfiguration {

    /**
     * RibbonAutoConfiguration.class类中有方法创建并注入了ClientHttpRequestFactory,
     * 该类中方法simpleClientHttpRequestFactory也创建了,优先采用simpleClientHttpRequestFactory的,
     * 这样我不知道会对这个cloud服务造成什么影响,暂时放弃该配置类,cloud内部应该可以在yml中设置连接超时时间
     *
     * @param factory
     * @return
     */
    @Bean("restTemplate")
    public RestTemplate restTemplate(@Qualifier("simpleClientHttpRequestFactory") ClientHttpRequestFactory factory) {
        return new RestTemplate(factory);
    }


    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);
        factory.setReadTimeout(5000);
        return factory;
    }
}

工具类

package com. utils;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;

/**
 * @version 0.0.1
 * @program: fuse-system
 * @description: 普通服务之间调用工具类
 * @author: huangzq
 * @create: 2021-01-08 09:16
 */
public class RestTemplateUtil {

    /**
     * 发送表单参数的post请求
     *
     * @param url      请求url
     * @param param    参数
     * @param respType 返回类型
     * @return T
     */
    public static <T> T postForm(String url, Map<String, List<Object>> param, Class<T> respType) {
        return getRestInstance().postForEntity(url, getHttpEntity(param, false), respType).getBody();
    }

    /**
     * 发送表单参数的异步post请求
     *
     * @param url      请求url
     * @param callback 回调接口
     * @param respType 返回类型
     */
    public static <T> void asyncPostForm(String url, Map<String, List<Object>> param,
                                         Class<T> respType, ListenableFutureCallback<ResponseEntity<T>> callback) {
        getAsyncRestInstance().postForEntity(url, getHttpEntity(param, false), respType).addCallback(callback);
    }

    /**
     * 发送表单有参数get请求
     *
     * @param url      请求url
     * @param param    参数对象
     * @param respType 返回类型
     * @return T
     */
    public static <T> T getForm(String url, Class<T> respType, Map<String,String> param) {
        return getRestInstance().getForEntity(url, respType, param).getBody();
    }

    /**
     * @Description: 发送表单无参数的get请求
     * @Param: [url, param, respType]
     * @return: T
     * @Author: tonyzhang
     * @Date: 2019-01-18 17:23
     */
    public static <T> T getForm(String url, Class<T> respType) {
        return getRestInstance().getForObject(url, respType);
    }


    /**
     * 获取HttpEntity实例对象
     *
     * @param param  参数对象
     * @param isJson true 发送json请求,false发送表单请求
     * @return HttpEntity
     */
    private static <P> HttpEntity<P> getHttpEntity(P param, boolean isJson) {
        HttpHeaders headers = new HttpHeaders();
        if (isJson) {
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        } else {
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        }

        return new HttpEntity<>(param, headers);
    }

    /*-----------------生产单例对象,方便自定义如何构造对象------------------*/

    private static RestTemplate restInit() {
        //设置连接超时和读取超时时间
        SimpleClientHttpRequestFactory factory=new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(5000);
        RestTemplate restTemplate = new RestTemplate(factory);
        FormHttpMessageConverter fastConverter = new FormHttpMessageConverter();
        WxMappingJackson2HttpMessageConverter wmc=new WxMappingJackson2HttpMessageConverter();
        restTemplate.getMessageConverters().add(fastConverter);
        restTemplate.getMessageConverters().add(wmc);
        return restTemplate;
    }



    private static AsyncRestTemplate asyncRestInit() {
        return new AsyncRestTemplate();
    }

    private static RestTemplate getRestInstance() {
        return RestSingle.INSTANCE;
    }

    private static AsyncRestTemplate getAsyncRestInstance() {
        return AsyncRestSingle.INSTANCE;
    }

    private static class RestSingle {
        private static final RestTemplate INSTANCE = restInit();
    }

    private static class AsyncRestSingle {
        private static final AsyncRestTemplate INSTANCE = asyncRestInit();
    }
}

添加其他类型支持

package com. .utils;

import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.util.ArrayList;
import java.util.List;

/**
 * @version 0.0.1
 * @program: fuse-system
 * @description: 封装转换器, 添加更多类型的支持
 * @author: huangzq
 * @create: 2021-01-08 09:18
 */
public class WxMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
    public WxMappingJackson2HttpMessageConverter(){
        List<MediaType> mediaTypes=new ArrayList<>();
        //添加text/html类型的支持
        mediaTypes.add(MediaType.TEXT_HTML);
        //添加text/plain类型的支持.微信接口会用到
        mediaTypes.add(MediaType.TEXT_PLAIN);
        setSupportedMediaTypes(mediaTypes);
    }
}

想使用的话,就直接注入到你的需要的业务层即可

参考:https://www.cnblogs.com/eternityz/p/12241380.html

HttpClients

使用HttpClient,一般都需要设置连接超时时间和获取数据超时时间。这两个参数很重要,目的是为了防止访问其他http时,由于超时导致自己的应用受影响。
4.5版本中,这两个参数的设置都抽象到了RequestConfig中,由相应的Builder构建,具体的例子在下面post带文件上传的请求中体现出来了

导入必要的jar包

<!-- httpclient核心包 -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.4</version>
        </dependency>

get

/**
     * 给第三方服务创建数据集
     *
     * @param createApiDataSetVo
     * @return 0成功 1失败
     */
    @Override
    public Integer createApiDataSet(CreateApiDataSetVo createApiDataSetVo) {
        //1.打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //调用地址
        String url = "http://localhost:8080/user/1";
        //2.声明get请求
        HttpGet request = new HttpGet(url);
        //发出请求  这种方式是可以的,下面的方式也可以,但是不知道我调用的服务是怎么返回数据的,要约定		       下
//        String result = null;
//        try {
//            //3.发送请求
//            result = client.execute(request,new BasicResponseHandler());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        //3.发送请求
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(request);
            //4.判断状态码
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                //使用工具类EntityUtils,从响应中取出实体表示的内容并转换成字符串
                String string = EntityUtils.toString(entity, "utf-8");
                log.info("数据创建成功,返回内容为:{}", string);
                return 0;
            } else {
                log.info("第三方创建数据集失败,第三方返回的状态码为:{}", response.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            log.error("第三方创建数据集失败:", e);
        } finally {
            //5.关闭资源
            try {
                if (response != null) {
                    response.close();
                }
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return 1;
    }

post 普通(form普通表单key-value)

form表单调用另外一个接口的,不是json串形式调用,所以被调用的后台是否添加@RequestBody

 @Override
    public ResponseEntity fileByLocalToApi() {
        //1.打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明post请求
        HttpPost httpPost = new HttpPost("https://www.oschina.net/");
        //3.开源中国为了安全,防止恶意攻击,在post请求中都限制了浏览器才能访问
        httpPost.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
        //4.判断状态码
        List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
        parameters.add(new BasicNameValuePair("scope", "project"));
        parameters.add(new BasicNameValuePair("q", "java"));
        CloseableHttpResponse response = null;
        try {
        	// 创建form表单对象
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters,"UTF-8");
            //这个是判断form表单是转成json形式的发送给被调用服务
            //formEntity.setContentType("Content-Type:application/json");
            httpPost.setEntity(formEntity);
            //5.发送请求
            response = httpClient.execute(httpPost);
            if(response.getStatusLine().getStatusCode()==200){
                HttpEntity entity = response.getEntity();
                String string = EntityUtils.toString(entity, "utf-8");
                log.info("文件上传功能,返回内容为:{}",string);
            } else {
                log.info("文件推送失败,第三方返回状态码为:{},信息为:{}",response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(), "utf-8"));
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //6.关闭资源
            try {
                if (response != null) {
                    response.close();
                }
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

post 普通(json串形式)

/**
     * 向第三方发送模型信息
     *
     * @param modelId
     * @return
     */
    @Override
    public ResponseEntity<String> modelApiSend(String modelId) {
        String url = "http://localhost:8080/modelInfo";
        //1.打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明post请求
        HttpPost httpPost = new HttpPost(url);
        //4.判断状态码  这个是我的一个实体类
        ApiModelSendMsg apiModelSendMsg = new ApiModelSendMsg();
        apiModelSendMsg.setBusType("dsadsa");
        apiModelSendMsg.setConfigFilePath("dsdasdsadasdsadasd");
        
        CloseableHttpResponse response = null;
        try {
            String CONTENT_TYPE_TEXT_JSON = "text/json";
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setHeader("Accept", "application/json");
            Gson gson = new Gson();
            String parameter = gson.toJson(apiModelSendMsg);
            //解决在调用的服务端中文乱码问题
            StringEntity se = new StringEntity(parameter, Charsets.UTF_8);
            se.setContentType(CONTENT_TYPE_TEXT_JSON);
            httpPost.setEntity(se);
            //5.发送请求
            response = httpClient.execute(httpPost);
            if(response.getStatusLine().getStatusCode()==200){
                HttpEntity entity = response.getEntity();
                String string = EntityUtils.toString(entity, "utf-8");
                log.info("模型信息发送成功:{}",string);
            } else {
                log.info("模型信息发送失败,第三方返回状态码为:{},信息为:{}",response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(), "utf-8"));
                return ResponseEntity.ok("error");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //6.关闭资源
            try {
                if (response != null) {
                    response.close();
                }
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ResponseEntity.ok("ok");
    }

post文件(支持多文件与其他参数传递)

 /**
     * 文件从本地下发给第三方服务
     *
     * @return
     */
    @Override
    public ResponseEntity fileByLocalToApi() {
        //文件URL,此处取豆瓣上的一个图片
        String fileUrl = "https://huangzouqiang-huangzouqiang.oss-cn-beijing.aliyuncs.com/3/2020-12-31/thum/01_20201231_101426_94O4W1d1.jpg";
        String fileUrl2 = "https://huangzouqiang-huangzouqiang.oss-cn-beijing.aliyuncs.com/3/2020-12-31/pic/01_20201231_101426_94O4W1d1.jpg";
        try {
            //提取到文件名
            String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
            //转换成文件流
            InputStream is = new URL(fileUrl).openStream();
            InputStream is2 = new URL(fileUrl2).openStream();
            //接收文件的服务器地址
            String uploadURL = "http://localhost:8080/fileupload";
            //创建HttpClient
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(uploadURL);
            //构建超时等配置信息
            RequestConfig config = RequestConfig.custom()
                    //连接超时时间
                    .setConnectTimeout(1000)
                    //从连接池中取的连接的最长时间
                    .setConnectionRequestTimeout(1000)
                    //数据传输的超时时间
                    .setSocketTimeout(6 * 1000)
                    .build();
            httpPost.setConfig(config);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            /*绑定文件参数,传入文件流和contenttype,此处也可以继续添加其他formdata参数*/
            builder.addBinaryBody("file", is, ContentType.MULTIPART_FORM_DATA, "1111.jpg");
            builder.addBinaryBody("file", is2, ContentType.MULTIPART_FORM_DATA, "22222.jpg");
            builder.addTextBody("prefix", "zhangsan");
            //builder.add
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);

            //执行提交
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                //将响应的内容转换成字符串
                String result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
                //此处根据服务器返回的参数转换,这里返回的是JSON格式
//                JSONObject output = JSON.parseObject(result);
//                JSONArray body = output.getJSONArray("body");
//                String resUrl = body.get(0) + "";
//                System.out.println(resUrl);
                System.out.println(result);
            }
            if (is != null) {
                is.close();
            }
            if (is2 != null) {
                is2.close();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

post文件接收服务端(另外一个服务项目)

/**
     * 上传文件
     *
     */
    @PostMapping("fileupload")
    public String upload(@RequestParam(defaultValue = "", required = false) String prefix,
                         @RequestParam("file") MultipartFile... files) {
        for (MultipartFile file : files) {
            if (file.isEmpty()) {
                continue;
            }
            String fileName = file.getOriginalFilename();
            File dest = new File(new File("C:\\Users\\shinelon\\Pictures\\jpeg\\").getAbsolutePath()+ "/" + fileName);
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                // 保存文件
                file.transferTo(dest);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        try {
        	//为了测试httpClient连接超时的问题
        	//在客户端那个设置调用超时请求中 数据传输的超时时间
            //setSocketTimeout(2 * 1000)   这样会出现超时
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    }

说明:
setConnectTimeout:设置连接超时时间,单位毫秒。
连接超时的意思是:
例如:httpclient连接超时我设置为60秒,如果我上传一个文件要几十分钟,那会导致连接超时么?

这个不会超时的,超时从最后一次操作算起,传文件算操作中,那就不会超时。传完了60秒啥都不做就超时了,只会出现在获取数据超时那个属性,也就是setSocketTimeout中。

setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。

setSocketTimeout:请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。

参考:http://www.yiidian.com/springcloud/httpclient-development.html
https://www.cnblogs.com/kitor/p/11235762.html
https://www.cnblogs.com/tobeymarshall/p/10215101.html
https://www.cnblogs.com/linus-tan/p/10592767.html

HttpURLConnection的get和post

package com. .utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;

/**
 * @version 0.0.1
 * @program: fuse-system
 * @description: 网络流形式服务调用工具类
 * @author: huangzq
 * @create: 2021-01-08 14:05
 */
@Slf4j
public class HttpUtil {
    public static String executeGetMethod(String path, String authorization) {
        String response = "";
        try {
            URL url = new URL(path);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setRequestProperty("Authorization", "Basic " + authorization);
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.connect();
            // 获得返回值
            InputStream in = connection.getInputStream();
            response = getResponse(in);
            log.info("response:{}", response);
            connection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    public static String executePostMethod(String path, JSONObject param) throws SocketTimeoutException {
        String paramStr = param.toString();
        String response = "";
        try {
            URL url = new URL(path);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setRequestMethod("POST");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("Content-Length", String.valueOf(paramStr.length()));
            connection.setRequestProperty("Content-Type", "application/json");
            connection.connect();
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            // 写入请求的字符串
            out.writeBytes(paramStr);
            out.flush();
            out.close();

            // 获得返回值
            InputStream in = connection.getInputStream();
            response = getResponse(in);

            connection.disconnect();
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    private static String getResponse(InputStream in) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        StringBuilder builder = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return builder.toString();
    }
}

参考:https://blog.csdn.net/egg1996911/article/details/73822803

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Boot使用HttpClient可以通过引入httpclient的POM依赖来实现。首先,在你的Spring Boot工程中,需要在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency> ``` 接下来,你可以创建一个HttpClientController类,并在该类中定义不同的接口方法,如doGetNoParams和doPostNoParams。这些方法可以使用@GetMapping和@PostMapping注解来标注,分别表示GET和POST请求。例如: ```java @RestController @RequestMapping("/httpClient") public class HttpClientController { @Autowired private HttpClientService httpClientService; // GET请求接口不带参数 @GetMapping("/doGetNoParams") public String doGetNoParams() { return httpClientService.doGetNoParams(); } // POST请求接口不带参数 @PostMapping("/doPostNoParams") public String doPostNoParams() { return httpClientService.doPostNoParams(); } } ``` 在这个示例中,我们使用@Autowired将HttpClientService注入到HttpClientController中,然后在doGetNoParams和doPostNoParams方法中调用相应的HttpClientService方法来实现GET和POST请求。具体的请求逻辑可以在HttpClientService中实现。 这样,你就可以在Spring Boot使用HttpClient来进行HTTP请求了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [「HttpClient」在 SpringBoot使用 HttpClient 实现 HTTP 请求](https://blog.csdn.net/wdj0311/article/details/121598212)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值