详解Hpptclient 与RestTemplate 的Get与Post请求

2023-11-10

spring中最长见得两种请求方式:Get与Post
有些时候我们需要跨域去访问其他服务上的接口,此时就用到HtppClient与RestTemplate;重点讲一下RestTemplate

一、HttpClient

1、引入相关依赖包
maven:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.5</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

2、主要类HttpClientService

package com.sinotn.service;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;

/**
 * HttpClient发送GET、POST请求
 * @Author libin
 * @CreateDate 2018.5.28 16:56
 */
public class HttpClientService {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientService.class);
    /**
     * 返回成功状态码
     */
    private static final int SUCCESS_CODE = 200;

    /**
     * 发送GET请求
     * @param url   请求url
     * @param nameValuePairList    请求参数
     * @return JSON或者字符串
     * @throws Exception
     */
    public static Object sendGet(String url, List<NameValuePair> nameValuePairList) throws Exception{
        JSONObject jsonObject = null;
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try{
            /**
             * 创建HttpClient对象
             */
            client = HttpClients.createDefault();
            /**
             * 创建URIBuilder
             */
            URIBuilder uriBuilder = new URIBuilder(url);
            /**
             * 设置参数
             */
            uriBuilder.addParameters(nameValuePairList);
            /**
             * 创建HttpGet
             */
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            /**
             * 设置请求头部编码
             */
            httpGet.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
            /**
             * 设置返回编码
             */
            httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));
            /**
             * 请求服务
             */
            response = client.execute(httpGet);
            /**
             * 获取响应吗
             */
            int statusCode = response.getStatusLine().getStatusCode();

            if (SUCCESS_CODE == statusCode){
                /**
                 * 获取返回对象
                 */
                HttpEntity entity = response.getEntity();
                /**
                 * 通过EntityUitls获取返回内容
                 */
                String result = EntityUtils.toString(entity,"UTF-8");
                /**
                 * 转换成json,根据合法性返回json或者字符串
                 */
                try{
                    jsonObject = JSONObject.parseObject(result);
                    return jsonObject;
                }catch (Exception e){
                    return result;
                }
            }else{
                LOGGER.error("HttpClientService-line: {}, errorMsg{}", 97, "GET请求失败!");
            }
        }catch (Exception e){
            LOGGER.error("HttpClientService-line: {}, Exception: {}", 100, e);
        } finally {
            response.close();
            client.close();
        }
        return null;
    }

    /**
     * 发送POST请求
     * @param url
     * @param nameValuePairList
     * @return JSON或者字符串
     * @throws Exception
     */
    public static Object sendPost(String url, List<NameValuePair> nameValuePairList) throws Exception{
        JSONObject jsonObject = null;
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try{
            /**
             *  创建一个httpclient对象
             */
            client = HttpClients.createDefault();
            /**
             * 创建一个post对象
             */
            HttpPost post = new HttpPost(url);
            /**
             * 包装成一个Entity对象
             */
            StringEntity entity = new UrlEncodedFormEntity(nameValuePairList, "UTF-8");
            /**
             * 设置请求的内容
             */
            post.setEntity(entity);
            /**
             * 设置请求的报文头部的编码
             */
            post.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
            /**
             * 设置请求的报文头部的编码
             */
            post.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));
            /**
             * 执行post请求
             */
            response = client.execute(post);
            /**
             * 获取响应码
             */
            int statusCode = response.getStatusLine().getStatusCode();
            if (SUCCESS_CODE == statusCode){
                /**
                 * 通过EntityUitls获取返回内容
                 */
                String result = EntityUtils.toString(response.getEntity(),"UTF-8");
                /**
                 * 转换成json,根据合法性返回json或者字符串
                 */
                try{
                    jsonObject = JSONObject.parseObject(result);
                    return jsonObject;
                }catch (Exception e){
                    return result;
                }
            }else{
                LOGGER.error("HttpClientService-line: {}, errorMsg:{}", 146, "POST请求失败!");
            }
        }catch (Exception e){
            LOGGER.error("HttpClientService-line: {}, Exception:{}", 149, e);
        }finally {
            response.close();
            client.close();
        }
        return null;
    }

    /**
     * 组织请求参数{参数名和参数值下标保持一致}
     * @param params    参数名数组
     * @param values    参数值数组
     * @return 参数对象
     */
    public static List<NameValuePair> getParams(Object[] params, Object[] values){
        /**
         * 校验参数合法性
         */
        boolean flag = params.length>0 && values.length>0 &&  params.length == values.length;
        if (flag){
            List<NameValuePair> nameValuePairList = new ArrayList<>();
            for(int i =0; i<params.length; i++){
                nameValuePairList.add(new BasicNameValuePair(params[i].toString(),values[i].toString()));
            }
            return nameValuePairList;
        }else{
            LOGGER.error("HttpClientService-line: {}, errorMsg:{}", 197, "请求参数为空且参数长度不一致");
        }
        return null;
    }
}

3、调用方法

package com.sinotn.service.impl;

import com.sinotn.service.HttpClientService;
import org.apache.http.NameValuePair;

import java.util.List;

/**
 * 发送post/get 测试类
 */
public class Test {

    public static void main(String[] args) throws Exception{
        String url = "要请求的url地址";
        /**
         * 参数值
         */
        Object [] params = new Object[]{"param1","param2"};
        /**
         * 参数名
         */
        Object [] values = new Object[]{"value1","value2"};
        /**
         * 获取参数对象
         */
        List<NameValuePair> paramsList = HttpClientService.getParams(params, values);
        /**
         * 发送get
         */
        Object result = HttpClientService.sendGet(url, paramsList);
        /**
         * 发送post
         */
        Object result2 = HttpClientService.sendPost(url, paramsList);

        System.out.println("GET返回信息:" + result);
        System.out.println("POST返回信息:" + result2);
    }
}

4、对于发送https
为了避免需要证书,所以用一个类继承DefaultHttpClient类,忽略校验过程。
写一个SSLClient类,继承至HttpClient

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
//用于进行Https请求的HttpClient
public class SSLClient extends DefaultHttpClient{
    public SSLClient() throws Exception{
        super();
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {
                }
                @Override
                public void checkServerTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {
                }
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
        };
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = this.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", 443, ssf));
    }
}

5、对于https调用
在这里插入图片描述

二、RestTemplate

RestTemplate 是从 Spring3.0 开始支持的一个 Http 请求工具,这个请求工具和 Spring Boot 无关,更
和 Spring Cloud 无关。RestTemplate 提供了常见的 REST 请求方法模板,例如 GET、POST、PUT、
DELETE 请求以及一些通用的请求执行方法 exchange 和 execute 方法。

这里的execute类似于 . p o s t ( ) 与 .post() 与 .post().ajax();的区别,前者是简写,写好的用来post请求,后者是需要我们来自定义的;

RestTemplate 本身实现了 RestOperations 接口,而在 RestOperations 接口中,定义了常见的
RESTful 操作,这些操作在 RestTemplate 中都得到了很好地实现;

1、Get

首先我们在 provider(自己测试的生产者服务) 中定义一个 hello2 接口:

@GetMapping("/hello2")
public String hello2(String name) {
    return "hello " + name;
}

接下来,我们在 consumer 去访问这个接口,这个接口是一个 GET 请求,所以,访问方式,就是调用 RestTemplate 中的 GET 请求。 可以看到,在 RestTemplate 中,关于 GET 请求,一共有如下两大类方法:
在这里插入图片描述
这两大类方法实际上是重载的,唯一不同的,就是返回值类型。 getForObject 返回的是一个对象,这个对象就是服务端返回的具体值。getForEntity 返回的是一个 ResponseEntity,这个ResponseEntity 中除了服务端返回的具体数据外,还保留了 Http 响应头的数据。

@GetMapping("/hello4")
    public void hello4() {
        String s1 = restTemplate.getForObject("http://provider/hello2?name={1}", String.class, "javaboy");
        System.out.println(s1);
        ResponseEntity<String> responseEntity =
                restTemplate.getForEntity("http://provider/hello2", String.class, "javaboy");
        String body = responseEntity.getBody();
        System.out.println("body:" + body);
        HttpStatus statusCode = responseEntity.getStatusCode();
        System.out.println("HttpStatus:" + statusCode);
        int statusCodeValue = responseEntity.getStatusCodeValue();
        System.out.println("statusCodeValue:"+statusCodeValue);
        HttpHeaders headers = responseEntity.getHeaders();
        Set<String> keySet = headers.keySet();
        System.out.println("--------------header-----------");
        for (String s : keySet) {
            System.out.println(s+":"+headers.get(s));
        }
    }

执行打印:
在这里插入图片描述
这里大家可以看到,getForObject 直接拿到了服务的返回值,getForEntity 不仅仅拿到服务的返回值, 还拿到 http 响应的状态码。然后,启动 Eureka Server、provider 以及 consumer ,访问 consumer 中的 hello4 接口,既可以看到请求结果。 看清楚两者的区别之后,接下来看下两个各自的重载方法,getForObject 和 getForEntity 分别有三个 重载方法,两者的三个重载方法基本都是一致的。所以,这里,我们主要看其中一种。三个重载方法, 其实代表了三种不同的传参方式。

@GetMapping("/hello5")
    public void hello5() throws UnsupportedEncodingException {
        //第一种
        String s1 = restTemplate.getForObject("http://provider/hello2?name={1}",
                String.class, "javaboy");
        System.out.println(s1);
        //第二种
        Map<String, Object> map = new HashMap<>();
        map.put("name", "zhangsan");
        s1 = restTemplate.getForObject("http://provider/hello2?name={name}",
                String.class, map);
        System.out.println(s1);
        //第三种
        String url = "http://provider/hello2?name=" + URLEncoder.encode("张三", "UTF8");
        URI uri = URI.create(url);
        s1 = restTemplate.getForObject(uri, String.class);
        System.out.println(s1);
    }

执行:
在这里插入图片描述
这就是我们说的三种不同的传参方式

2、Post

首先在 provider 中提供两个 POST 接口,同时,因为 POST 请求可能需要传递 JSON,所以,这里我们 创建一个普通的 Maven 项目作为 commons 模块,然后这个 commons 模块被 provider 和 consumer 共同引用,这样我们就可以方便的传递 JSON 了。 (其实就是为了传参user)
commons 模块创建成功后,首先在 commons 模块中添加 User 对象,然后该模块分别被 provider 和 consumer 引用。 然后,我们在 provider 中,提供和两个 POST 接口:

@PostMapping("/user1")
    public User addUser1(User user) {
        return user;
    }
    @PostMapping("/user2")
    public User addUser2(@RequestBody User user) {
        return user;
    }

这里定义了两个 User 添加的方法,两个方法代表了两种不同的传参方式。
第一种方法是以 key/value 形式来传参,
第二种方法是以 JSON 形式来传参。
定义完成后,接下来,我们在 consumer 中调用这两个 POST 接口。
在这里插入图片描述
可以看到,这里的 post 和前面的 get 非常像,只是多出来了三个方法,就是 postForLocation,另外 两个 postForObject 和 postForEntiy 和前面 get 基本一致,所以这里我们主要来看 postForObject, 看完之后,我们再来看这个额外的 postForLocation。

@GetMapping("/hello6")
    public void hello6() {
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("username", "javaboy");
        map.add("password", "123");
        map.add("id", 99);
        User user = restTemplate.postForObject("http://provider/user1", map,
                User.class);
        System.out.println(user);
        user.setId(98);
        user = restTemplate.postForObject("http://provider/user2", user,
                User.class);
        System.out.println(user);
    }

运行:
在这里插入图片描述
post 参数到底是 key/value 形式还是 json 形式,主要看第二个参数,如果第二个参数是 MultiValueMap ,则参数是以 key/value 形式来传递的,如果是一个普通对象,则参数是以 json 形式 来传递的。

最后再看看一下 postForLocation 。有的时候,当我执行完一个 post 请求之后,立马要进行重定向, 一个非常常见的场景就是注册,注册是一个 post 请求,注册完成之后,立马重定向到登录页面去登 录。
对于这种场景,我们就可以使用 postForLocation。 首先我们在 provider 上提供一个用户注册接口:

@Controller
public class RegisterController {
 @PostMapping("/register")
 public String register(User user) {
     return "redirect:http://provider/loginPage?username=" +
             user.getUsername();
 }
 @GetMapping("/loginPage")
 @ResponseBody
 public String loginPage(String username) {
     return "loginPage:" + username;
 }
}

注意,这里的 post 接口,响应一定是 302,否则 postForLocation 无效。
注意,重定向的地址,一定要写成绝对路径,不要写相对路径,否则在 consumer 中调用时会出问题

@GetMapping("/hello7")
public void hello7() {
   MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
   map.add("username", "javaboy");
   map.add("password", "123");
   map.add("id", 99);
   URI uri = restTemplate.postForLocation("http://provider/register", map);
   String s = restTemplate.getForObject(uri, String.class);
   System.out.println(s);
}

运行:
在这里插入图片描述
这就是 postForLocation ,调用该方法返回的是一个 Uri,这个 Uri 就是重定向的地址(里边也包含了 重定向的参数),拿到 Uri 之后,就可以直接发送新的请求了

3、Put

PUT 请求比较简单,重载的方法也比较少。(PUT是没有返回值的)
我们首先在 provider 中提供一个 PUT 接口:

@PutMapping("/user1")
    public void updateUser1(User user) {
     System.out.println(user);
    }
    @PutMapping("/user2")
    public void updateUser2(@RequestBody User user) {
      System.out.println(user);
    }

注意,PUT 接口传参其实和 POST 很像,也接受两种类型的参数,key/value 形式以及 JSON 形式。
在 consumer 中,我们来调用该接口:

 @GetMapping("/hello8")
    public void hello8() {
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("username", "javaboy");
        map.add("password", "123");
        map.add("id", 99);
        restTemplate.put("http://provider/user1", map);
        
        User user = new User();
        user.setId(98);
        user.setUsername("zhangsan");
        user.setPassword("456");
        restTemplate.put("http://provider/user2", user);
    }

运行:
在这里插入图片描述
consumer 中的写法基本和 post 类似,也是两种方式,可以传递两种不同类型的参数

4、Delete

DELETE 也比较容易,我们有两种方式来传递参数,key/value 形式或者 PathVariable(参数放在路径 中),首先我们在 provider 中定义两个 DELETE 方法:

@DeleteMapping("/user1")
    public void deleteUser1(Integer id) {
        System.out.println(id);
    }
    @DeleteMapping("/user2/{id}")
    public void deleteUser2(@PathVariable Integer id) {
        System.out.println(id);
    }

然后在 consumer 中调用这两个删除的接口:

@GetMapping("/hello9")
public void hello9() {
    restTemplate.delete("http://provider/user1?id={1}", 99);
    restTemplate.delete("http://provider/user2/{1}", 99);
}

delete 中参数的传递,也支持 map,这块实际上和 get 是一样的。

三、RestTemplate拓展

1、手动指定转换器(HttpMessageConverter)

我们知道,调用reseful接口传递的数据内容是json格式的字符串,返回的响应也是json格式的字符串。
然而restTemplate.postForObject方法的请求参数RequestBean和返回参数ResponseBean却都是java类。是RestTemplate通过HttpMessageConverter自动帮我们做了转换的操作。

默认情况下RestTemplate自动帮我们注册了一组HttpMessageConverter用来处理一些不同的contentType的请求。
StringHttpMessageConverter来处理text/plain;MappingJackson2HttpMessageConverter来处理application/json;
MappingJackson2XmlHttpMessageConverter来处理application/xml。
你可以在org.springframework.http.converter包下找到所有spring帮我们实现好的转换器。
如果现有的转换器不能满足你的需求,你还可以实现org.springframework.http.converter.HttpMessageConverter接口自己写一个。详情参考官方api。

选好了HttpMessageConverter后怎么把它注册到我们的RestTemplate中呢

        RestTemplate restTemplate = new RestTemplate();
        //获取RestTemplate默认配置好的所有转换器
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        //默认的MappingJackson2HttpMessageConverter在第7个 先把它移除掉
        messageConverters.remove(6);
        //添加上GSON的转换器
        messageConverters.add(6, new GsonHttpMessageConverter());

这个简单的例子展示了如何使用GsonHttpMessageConverter替换掉默认用来处理application/json的MappingJackson2HttpMessageConverter

2、设置底层连接方式

要创建一个RestTemplate的实例,您可以像上述例子中简单地调用默认的无参数构造函数。这将使用java.net包中的标准Java类作为底层实现来创建HTTP请求。
但很多时候我们需要像传统的 HttpClient那样设置HTTP请求的一些属性。RestTemplate使用了一种很偷懒的方式实现了这个需求,那就是直接使用一个HttpClient作为底层实现…

        //生成一个设置了连接超时时间、请求超时时间、异常最大重试次数的httpClient
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(10000).setConnectTimeout(10000).setSocketTimeout(30000).build();
        HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(config).setRetryHandler(new DefaultHttpRequestRetryHandler(5, false));
        HttpClient httpClient = builder.build();
        //使用httpClient创建一个ClientHttpRequestFactory的实现
        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
         //ClientHttpRequestFactory作为参数构造一个使用作为底层的RestTemplate
        RestTemplate restTemplate = new RestTemplate(requestFactory);

3、设置拦截器(ClientHttpRequestInterceptor)

有时候我们需要对请求做一些通用的拦截设置,这就可以使用拦截器进行处理。拦截器需要我们实现org.springframework.http.client.ClientHttpRequestInterceptor接口自己写。

举个简单的例子,写一个在header中根据请求内容和地址添加令牌的拦截器。

public class TokenInterceptor implements ClientHttpRequestInterceptor
{
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
    {
        //请求地址
        String checkTokenUrl = request.getURI().getPath();
        //token有效时间
        int ttTime = (int) (System.currentTimeMillis() / 1000 + 1800);
        //请求方法名 POST、GET等
        String methodName = request.getMethod().name();
        //请求内容
        String requestBody = new String(body);
        //生成令牌 此处调用一个自己写的方法,有兴趣的朋友可以自行google如何使用ak/sk生成token,此方法跟本教程无关,就不贴出来了
        String token = TokenHelper.generateToken(checkTokenUrl, ttTime, methodName, requestBody);
        //将令牌放入请求header中
        request.getHeaders().add("X-Auth-Token",token);

        return execution.execute(request, body);
    }
}

创建RestTemplate实例的时候可以这样向其中添加拦截器

        RestTemplate restTemplate = new RestTemplate();
        //向restTemplate中添加自定义的拦截器
        restTemplate.getInterceptors().add(new TokenInterceptor());

spring cloud消费者根据生产者名称进行url调用时,在restTemplate上源码使用此种拦截器对uri进行了重构,将uri指向具体可访问的地址;

四、结尾

以上就是对HttpClient与RestTemplate的使用方法总结,最后附属一下自己做的一些调用测试代码:

package com.cn.testpost;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class TestController {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/testPost")
    public String testPost(){

        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("name", "%xiaoming");
        map.add("age", 27);
        String user = restTemplate.postForObject("http://127.0.0.1:8081/test", map,
                String.class);
        System.out.println(user);
        return user;
    }

    @GetMapping("/testPost2")
    public String testPost2(){
        Map<String, Object> map = new HashMap<>();
        map.put("name", "%xiaoming");
        map.put("age", 27);
        String s = JSON.toJSONString(map);
        String s1 = sendPost("http://127.0.0.1:8081/test", s, false);
        System.out.println(s1);
        return s1;


    }

    @GetMapping("/testPost3")
    public String testPost3(){
        Map<String, Object> map = new HashMap<>();
        map.put("app_id", "qianfsHis001");
        map.put("method", "060001");
        map.put("formatter", "json");
        map.put("version", "1.0.1");
        map.put("message_id", "123");
        map.put("message", "{\"version_code\":\"%1.0.1\"}");
        map.put("is_secret", "0");
        map.put("passKey", "843491CC879BDF2AFB2C20BDB387F546D54DCDC8");
        map.put("time", "12526");
        map.put("nonceStr", "85269");
        String s = JSON.toJSONString(map);
        String s1 = sendPost("http://127.0.0.1:8099/central/app/", s, false);
        System.out.println(s1);
        return s1;

    }


    @GetMapping("/testPost4")
    public String testPost4(){
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("app_id", "qianfsHis001");
        map.add("method", "060001");
        map.add("formatter", "json");
        map.add("version", "1.0.1");
        map.add("message_id", "123");
        map.add("message", "{\"version_code\":\"%1.0.1\"}");
        map.add("is_secret", "0");
        map.add("passKey", "843491CC879BDF2AFB2C20BDB387F546D54DCDC8");
        map.add("time", "12526");
        map.add("nonceStr", "85269");


        String s = restTemplate.postForObject("http://127.0.0.1:8099/central/app/", map,
                String.class);
        System.out.println(s);
        return s;
    }


    @GetMapping("/testPost5")
    public String testPost5() throws Exception {




        String url = "http://127.0.0.1:8099/central/app/";
        /**
         * 参数值
         */
        Object [] params = new Object[]{"app_id","method","formatter","version","message_id","message","is_secret","passKey"
               , "time","nonceStr"};
        /**
         * 参数名
         */
        Object [] values = new Object[]{"qianfsHis001","060001","json","1.0.1",
                "123","{\"version_code\":\"%251.0.1\"}","0","843491CC879BDF2AFB2C20BDB387F546D54DCDC8","12526","85269"};
        /**
         * 获取参数对象
         */
        List<NameValuePair> paramsList = getParams(params, values);
        /**
         * 发送post
         */
        Object result2 = sendHpptPost(url, paramsList);

        System.out.println("POST返回信息:" + result2);

        return String.valueOf(result2);
    }





    public static String sendPost(String url, String param, boolean isproxy) {
        OutputStreamWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            HttpURLConnection conn = null;
            if (isproxy) {//使用代理模式
                @SuppressWarnings("static-access")
                Proxy proxy = new Proxy(Proxy.Type.DIRECT.HTTP, new InetSocketAddress("127.0.0.1", 8080));
                conn = (HttpURLConnection) realUrl.openConnection(proxy);
            } else {
                conn = (HttpURLConnection) realUrl.openConnection();
            }
            // 打开和URL之间的连接

            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");    // POST方法


            // 设置通用的请求属性

            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            //conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");

            conn.connect();

            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            // 发送请求参数
            out.write(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }



    /**
     * 发送POST请求
     * @param url
     * @param nameValuePairList
     * @return JSON或者字符串
     * @throws Exception
     */
    public static Object sendHpptPost(String url, List<NameValuePair> nameValuePairList) throws Exception{
        JSONObject jsonObject = null;
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try{
            /**
             *  创建一个httpclient对象
             */
            client = HttpClients.createDefault();
            /**
             * 创建一个post对象
             */
            HttpPost post = new HttpPost(url);
            /**
             * 包装成一个Entity对象
             */
            StringEntity entity = new UrlEncodedFormEntity(nameValuePairList, "UTF-8");
            /**
             * 设置请求的内容
             */
            post.setEntity(entity);
            /**
             * 设置请求的报文头部的编码
             */
            post.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
            /**
             * 设置请求的报文头部的编码
             */
            post.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));
            /**
             * 执行post请求
             */
            response = client.execute(post);
            /**
             * 获取响应码
             */
            int statusCode = response.getStatusLine().getStatusCode();
            if (200 == statusCode){
                /**
                 * 通过EntityUitls获取返回内容
                 */
                String result = EntityUtils.toString(response.getEntity(),"UTF-8");
                /**
                 * 转换成json,根据合法性返回json或者字符串
                 */
                try{
                    jsonObject = JSONObject.parseObject(result);
                    return jsonObject;
                }catch (Exception e){
                    return result;
                }
            }else{
                LOGGER.error("HttpClientService-line: {}, errorMsg:{}", 146, "POST请求失败!");
            }
        }catch (Exception e){
            LOGGER.error("HttpClientService-line: {}, Exception:{}", 149, e);
        }finally {
            response.close();
            client.close();
        }
        return null;
    }

    /**
     * 组织请求参数{参数名和参数值下标保持一致}
     * @param params    参数名数组
     * @param values    参数值数组
     * @return 参数对象
     */
    public static List<NameValuePair> getParams(Object[] params, Object[] values){
        /**
         * 校验参数合法性
         */
        boolean flag = params.length>0 && values.length>0 &&  params.length == values.length;
        if (flag){
            List<NameValuePair> nameValuePairList = new ArrayList<>();
            for(int i =0; i<params.length; i++){
                nameValuePairList.add(new BasicNameValuePair(params[i].toString(),values[i].toString()));
            }
            return nameValuePairList;
        }else{
            LOGGER.error("HttpClientService-line: {}, errorMsg:{}", 197, "请求参数为空且参数长度不一致");
        }
        return null;
    }
}

附:添加消息请求头

        //headers
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("api-version", "1.0");
        //body
        MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("roundid", "1");
        //HttpEntity
        HttpEntity<MultiValueMap> requestEntity = new HttpEntity<MultiValueMap>(requestBody, requestHeaders);
        RestTemplate restTemplate = new RestTemplate();
        //post
        ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://xxx", requestEntity, String.class);
        System.out.println(responseEntity.getBody());

参考文章:
https://www.cnblogs.com/klslb/p/9121276.html
https://www.jianshu.com/p/90ec27b3b518

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解Hpptclient 与RestTemplate 的Get与Post请求 的相关文章

随机推荐

  • Linux入坑教程

    服务器安装所需环境 Linux 一 安装基础环境 1 1 JDK 1 2 Mysql 1 3 FastDFS 1 4 Redis 1 5 GIT 1 6 Node 二 Basic commands 基础命令 2 1 查询命令 2 1 1 查
  • 僵尸进程~

    僵尸进程 1 僵尸进程概述 什么是僵尸进程 在Linux系统中 任何一个子进程在调用exit 函数结束运行后 内核会释放该进程的所有资源 包括占用的内存和打开的文件等 同时 也会留下一个叫做僵尸进程 Zombie 的数据结构 Zombie中
  • HIDL详解-Android10.0 HwBinder通信原理(二)

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系
  • sentinel搭建与使用

    下载 https github com alibaba Sentinel releases 启动 脚本 java jar Dserver port 9013 Dsentinel dashboard auth username sentine
  • ERROR in ./src/main.jsModule build failed (from ./node_modules/babel-loader/lib/index.js):Error: e

    ERROR in src main js Module build failed from node modules babel loader lib index js Error error 0308010C digital envelo
  • mysql数据库连接

    一 自带的客户端命令行 直接输入密码即可连接 二 使用口令连接 1 切换目录 输入cd C web mysql 8 0 11 winx64 bin 2 登录 输入mysql u root p 3 输入密码 root 数据库密码 连接成功
  • 【Docker】ubuntu20.04 X86机器搭建NVIDIA ARM64 TX2的Docker镜像

    文章目录 1 设置ubuntu为清华源 1 1 备份源文件 1 2 替换清华源 1 3 更新清华源 2 Ubuntu Docker 安装 3 安装qemu 4 安装Nvidia TX2 Docker镜像 5 如何使用TX2容器 6 参考资料
  • ubuntu下载使用mtcnn和facenet并运行demo

    首先搭建好环境 ubuntu18 04 python3 6 5 tensorflow1 8 0 opencv3 4 3 pip install tqdm为了显示进度条 主要在这两个网站上学习 github上有很多教程和样例 以一般选择星星最
  • Windows使用ssh登入远程服务器(包含mac版)

    windows 首先Windows是没有ssh这个命令的 所以我们先要使Windows可以使用ssh命令 下载openssh for Winodws http linux linuxidc com index php folder MjAx
  • SpringBoot工程使用logback-spring.xml

    在SpringBoot工程中 推荐使用logback spring xml来替换logback xml 原因是SpringBoot加载logback xml是在application yml之前 所以在yml里面的信息不会被logback
  • Python疫情数据可视化分析+数据预测(pandas+pyecharts+statsmodels+matplotlib+sql)

    1 MySQL数据库获取数据 此处的原始数据表是全国各省的实时数据集 现在只获取江苏省份的数据 engine create engine mysq conn 具体内容以自己上就可以为准 select data select from tab
  • C++---类成员变量定义为引用

    摘要 类成员变量是可以定义为引用类型的 但是我们需要注意一下用法 note1 在类中定义引用变量 必须要在初始化列表中初始化该成员变量 const 类型数据成员也必须在初始化列表中进行初始化 include
  • synchronized (成员变量) 和 synchronized (静态成员变量)

    synchronized 成员变量 和 synchronized 静态成员变量 在同步方面有不同的效果 在 Java 中 每个对象都有一个 内置锁 或 对象锁 也称为 monitor 对象 它可以用来同步代码块或方法 使用 synchron
  • 彻底理解数字图像处理中的卷积-以Sobel算子为例

    链接 原文出处 作者 FreeBlues 概述 卷积在信号处理领域有极其广泛的应用 也有严格的物理和数学定义 本文只讨论卷积在数字图像处理中的应用 在数字图像处理中 有一种基本的处理方法 线性滤波 待处理的平面数字图像可被看做一个大矩阵 图
  • 理想的程序员

    http blog jobbole com 84747 我算是靠坑蒙拐骗进了程序员的门 然后一路狂奔 26岁之前几乎没有任何写代码的经验 研究生毕业却意外选择了一家不可能提供培训的初创公司 在每日担忧公司倒闭 害怕被炒鱿鱼以及同事冷落白眼的
  • 偶写的第一个CUDA程序——向量加法

    这个CUDA工程包括了三个文件 一个是makefile 一个是vector add cu 用于联系主机端与设备端 最后是vector add kernel cu 这个就是设备端要执行的真正的CUDA程序 首先看看makefile Add s
  • HarmonyOS开发:探索动态共享包的依赖与使用

    前言 所谓共享包 和Android中的Library本质是一样的 目的是为了实现代码和资源的共享 在HarmonyOS中 给开发者提供了两种共享包 HAR Harmony Archive 静态共享包 和HSP Harmony Shared
  • Can you solve this equation?(二分)

    Problem Description Now given the equation 8 x 4 7 x 3 2 x 2 3 x 6 Y can you find its solution between 0 and 100 Now ple
  • 解决MDK通过JLink或ST-Link烧写程序之后必须断电才可以运行的问题

    问题描述 通过JLink或ST Link烧写完程序之后发现程序不运行 断电重启程序又能跑起来 解决方法 1 打开魔术棒 2 进入Debug界面 点击Setting 3 进入Cortex M Target Driver Setup界面 将 R
  • 详解Hpptclient 与RestTemplate 的Get与Post请求

    spring中最长见得两种请求方式 Get与Post 有些时候我们需要跨域去访问其他服务上的接口 此时就用到HtppClient与RestTemplate 重点讲一下RestTemplate 一 HttpClient 1 引入相关依赖包 m