设置各种 timeout

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
        restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        log.info("message converters {}", restTemplate.getMessageConverters());
        return restTemplate;
    }

    private ClientHttpRequestFactory getClientHttpRequestFactory() {
        int timeout = 5000;
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setConnectTimeout(timeout);
        return clientHttpRequestFactory;
    }

GET

        String body;
        if (value != null) {
            body = value.toString();
        } else {
            body = restTemplate.getForObject("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={ID}&corpsecret={SECRECT}", String.class, request.getCorpid(), request.getCorpsecret());
            log.info("send token http response {}", body);
        }

后面的是 url 的参数. url 中的变量使用 {}, {} 的形式表示.

注: 名字不影响, 只是 {} 中间是一个占位符而已.

POST BODY

String body = restTemplate.postForObject("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={ACCESS_TOKEN}", jsonBody, String.class, token);

POST JSON BODY

        final TextMsg textMsg = new TextMsg();
        textMsg.setAgentid(agentid);
        TextMsg.TextBean textBean = new TextMsg.TextBean();
        textBean.setContent(text);
        textMsg.setText(textBean);

        final String sendMsgUrl = String.format(SEND_MSG_URL, accessToken.getAccessToken());

        // set headers
        final HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        final HttpEntity<String> entity = new HttpEntity<>(GsonKit.toJSON(textMsg), headers);
        // send request and parse result
        ResponseEntity<String> response = restTemplate.exchange(sendMsgUrl, HttpMethod.POST, entity, String.class);

POST file

https://stackoverflow.com/questions/14738394/making-a-multipart-post-request-with-compressed-jpeg-byte-array-with-spring-for

这种是纯 bytes 内存的方式

        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        Resource res = new ByteArrayResource(request.getStream().toByteArray()) {
            @Override
            public String getFilename() throws IllegalStateException {
                return "hello.jpg";
            }
        };
        HttpHeaders imageHeaders = new HttpHeaders();
        imageHeaders.setContentType(MediaType.IMAGE_JPEG);
        HttpEntity<Resource> imageEntity = new HttpEntity<>(res, imageHeaders);
        map.add("file", imageEntity);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(map, httpHeaders);
        ResponseEntity<String> result = restTemplate.exchange("http://127.0.0.1:8888/upload", HttpMethod.POST, httpEntity, String.class);

如果直接是文件系统中的文件的方式的话, 则直接提交即可:

        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("file", new FileSystemResource("/tmp/hello.jpg"));

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(map, httpHeaders);
        ResponseEntity<String> result = restTemplate.exchange("http://127.0.0.1:8888/upload", HttpMethod.POST, httpEntity, String.class);

        final String body = result.getBody();

解决乱码

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(GsonKit.GSON));
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

Post Form

    public void sendText(final int agentId, final String content) {
        final HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        final MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("agentId", agentId+"");
        map.add("content", content);

        final HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(host + textContext, request, String.class);
        if (response.getStatusCode() == HttpStatus.OK) {
            log.info("send ok {} => {}, {}", agentId, content, response);
        } else {
            log.error("send error {} => {}, {}", agentId, content, response);
        }
    }

注意, 是用: MultiValueMap . 看源码可知:

    @Override
    @SuppressWarnings("unchecked")
    public void write(MultiValueMap<String, ?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {

        if (!isMultipart(map, contentType)) {
            writeForm((MultiValueMap<String, String>) map, contentType, outputMessage);
        }
        else {
            writeMultipart((MultiValueMap<String, Object>) map, outputMessage);
        }
    }

当不是 multipart 时, 是 <String, String>.

参考

Using-RestTemplate