java第三方接口调用笔记

编程

在实际项目开发过程中,经常需要调用外部提供的接口。如做短信认证码、身份认证、第三方电商,互联网金融、天气等。

在Java项目中调用第三方接口的常用方式有:
1)通过JDK网络类Java.net.HttpURLConnection;
2)通过common封装好的HttpClient;
3)通过Apache封装好的CloseableHttpClient;
4)通过SpringBoot-RestTemplate;
5)通过Feign插件调用;

HttpURLConnection调用
比较原始的一种调用做法,这里把get请求和post请求都统一放在一个方法里面。
代码如下:

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;

import java.net.URL;

import lombok.extern.slf4j.Slf4j;

@Slf4j

public class HttpUrlConnectionTest {

    /**

     * 以post或get方式调用对方接口方法,

     *

     * @param pathUrl

     */

    public static void doPostOrGet(String pathUrl, String data) {

        OutputStreamWriter out = null;

        BufferedReader br = null;

        String result = "";

        try {

            URL url = new URL(pathUrl);

            //打开和url之间的连接

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            //请求方式

            conn.setRequestMethod("POST");

            //conn.setRequestMethod("GET");

            //设置通用的请求属性

            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/json;charset=utf-8");

            //DoOutput设置是否向httpUrlConnection输出,DoInput设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个

            conn.setDoOutput(true);

            conn.setDoInput(true);

            /**

             * 下面的三句代码,就是调用第三方http接口

             */

            //获取URLConnection对象对应的输出流

            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");

            //发送请求参数即数据

            out.write(data);

            //flush输出流的缓冲

            out.flush();

            /**

             * 下面的代码相当于,获取调用第三方http接口后返回的结果

             */

            //获取URLConnection对象对应的输入流

            InputStream is = conn.getInputStream();

            //构造一个字符流缓存

            br = new BufferedReader(new InputStreamReader(is));

            String str = "";

            while ((str = br.readLine()) != null) {

                result += str;

            }

            System.out.println(result);

            //关闭流

            is.close();

            //断开连接,disconnect是在底层tcp socket链接空闲时才切断,如果正在被其他线程使用就不切断。

            conn.disconnect();

        } catch (Exception e) {

            log.error("", e);

        } finally {

            try {

                if (out != null) {

                    out.close();

                }

                if (br != null) {

                    br.close();

                }

            } catch (IOException e) {

                log.error("", e);

            }

        }

    }

    public static void main(String[] args) {

        /**

         *手机信息查询接口:http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手机号

         *            http://api.showji.com/Locating/www.showji.com.aspx?m=手机号&output=json&callback=querycallback

         */

        doPostOrGet("https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13168888888", "");

    }

}

通过HttpClient调用
httpClient的get或post请求方式步骤:
生成一个HttpClient对象并设置相应的参数;
生成一个GetMethod对象或PostMethod并设置响应的参数;
用HttpClient生成的对象来执行GetMethod生成的Get方法;
处理响应状态码;
若响应正常,处理HTTP响应内容;
释放连接。
导入如下jar包:
<!--HttpClient-->
<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

代码如下:

import java.io.IOException;

import java.nio.charset.Charset;

import java.security.MessageDigest;

import java.util.Map;

import java.util.TreeMap;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;

import org.apache.commons.httpclient.Header;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.HttpException;

import org.apache.commons.httpclient.HttpStatus;

import org.apache.commons.httpclient.methods.GetMethod;

import org.apache.commons.httpclient.methods.PostMethod;

import org.apache.commons.httpclient.params.HttpMethodParams;

import org.springframework.util.CollectionUtils;

import lombok.extern.slf4j.Slf4j;

import sun.misc.BASE64Encoder;

@Slf4j

public class HttpClientTest {

    /**

     * httpClient的get请求方式 使用GetMethod来访问一个URL对应的网页实现步骤: 1.生成一个HttpClient对象并设置相应的参数; 2.生成一个GetMethod对象并设置响应的参数;

     * 3.用HttpClient生成的对象来执行GetMethod生成的Get方法; 4.处理响应状态码; 5.若响应正常,处理HTTP响应内容; 6.释放连接。

     *

     * @param url

     * @param charset

     * @return

     */

    public static String doGet(String url, TreeMap<String, Object> parameter, String charset) throws Exception {

        if (parameter == null)

            parameter = new TreeMap<>();

        parameter.put("timestamp", System.currentTimeMillis());

        /**

         * 1.生成HttpClient对象并设置参数

         */

        HttpClient httpClient = new HttpClient();

        //设置Http连接超时为5秒

        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);

        /**

         * 2.生成GetMethod对象并设置参数

         */

        //添加请求参数

        if (!CollectionUtils.isEmpty(parameter)) {

            String pams = urlParameter(parameter);

            url = url + "?" + pams;

        }

        GetMethod getMethod = new GetMethod(url);

        //设置get请求超时为5秒

        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);

        //设置请求重试处理,用的是默认的重试处理:请求三次

        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

        String response = "";

        /**

         * 3.执行HTTP GET 请求

         */

        try {

            int statusCode = httpClient.executeMethod(getMethod);

            /**

             * 4.判断访问的状态码

             */

            if (statusCode != HttpStatus.SC_OK) {

                log.info(">>>>>> 请求出错:{}", getMethod.getStatusLine());

            }

            /**

             * 5.处理HTTP响应内容

             */

            //HTTP响应头部信息,这里简单打印

            Header[] headers = getMethod.getResponseHeaders();

            for (Header h : headers) {

                log.info(">>>>>> header: {}", h.getName() + "---------------" + h.getValue());

            }

            //读取HTTP响应内容,这里简单打印网页内容

            //读取为字节数组

            byte[] responseBody = getMethod.getResponseBody();

            response = new String(responseBody, charset);

            log.info(">>>>>> response: {}", response);

            //读取为InputStream,在网页内容数据量大时候推荐使用

            //InputStream response = getMethod.getResponseBodyAsStream();

        } catch (HttpException e) {

            //发生致命的异常,可能是协议不对或者返回的内容有问题

            log.error("请检查输入的URL!", e);

        } catch (IOException e) {

            log.error("发生网络异常!", e);

        } finally {

            /**

             * 6.释放连接

             */

            getMethod.releaseConnection();

        }

        return response;

    }

    /**

     * post请求

     *

     * @param url

     * @param parameter

     * @return

     */

    public static String doPost(String url, TreeMap<String, Object> parameter) throws Exception {

        if (parameter == null)

            parameter = new TreeMap<>();

        parameter.put("timestamp", System.currentTimeMillis());

        HttpClient httpClient = new HttpClient();

        PostMethod postMethod = new PostMethod(url);

        postMethod.addRequestHeader("accept", "*/*");

        postMethod.addRequestHeader("connection", "Keep-Alive");

        //设置json格式传送

        postMethod.addRequestHeader("Content-Type", "application/json;charset=utf-8");

        //必须设置下面这个Header

        postMethod.addRequestHeader("User-Agent",

            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");

        //添加请求参数

        if (!CollectionUtils.isEmpty(parameter)) {

            String val = "";

            for (Map.Entry<String, Object> entry : parameter.entrySet()) {

                if (entry.getValue() != null) {

                    val = String.valueOf(entry.getValue());

                }

                postMethod.addParameter(entry.getKey(), val);

            }

            //getSignature(TreeMap<String, Object> parameter)

            postMethod.addParameter("signature", getSignature(parameter));

        }

        String res = "";

        try {

            int code = httpClient.executeMethod(postMethod);

            if (code == 200) {

                res = postMethod.getResponseBodyAsString();

                log.info(">>>>>> response: {}", res);

            }

        } catch (IOException e) {

            log.error("", e);

        }

        return res;

    }

    /**

     * 签名生成规则视被调用方而定

     * @param parameter

     * @return

     * @throws Exception

     */

    private static String urlParameter(TreeMap<String, Object> parameter) throws Exception {

        if (CollectionUtils.isEmpty(parameter)) {

            return "";

        }

        StringBuilder params = new StringBuilder();

        int i = 1;

        for (Map.Entry<String, Object> entry : parameter.entrySet()) {

            if (i == 1) {

                params.append(entry.getKey()).append("=").append(entry.getValue());

            } else {

                params.append("&").append(entry.getKey()).append("=").append(entry.getValue());

            }

            i++;

        }

        params.append("signature=").append(getSignature(parameter));

        log.info(">>>>>>> urlParameter: {}", params.toString());

        return params.toString();

    }

    private static String getSignature(TreeMap<String, Object> parameter) throws Exception {

        String params = urlParameter(parameter);

        params = encryptBASE64(params.getBytes(Charset.forName("UTF-8")));

        byte[] param = encryptMD5(params.getBytes(Charset.forName("UTF-8")));

        return new String(param);

    }

    /**

     * BASE64加密

     *

     * @param data

     * @return

     * @throws Exception

     */

    private static String encryptBASE64(byte[] data) throws Exception {

        return (new BASE64Encoder()).encodeBuffer(data);

    }

    /**

     * MD5加密

     *

     * @param data

     * @return

     * @throws Exception

     */

    private static byte[] encryptMD5(byte[] data) throws Exception {

        MessageDigest md5 = MessageDigest.getInstance("MD5");

        md5.update(data);

        return md5.digest();

    }

    public static void main(String[] args) throws Exception {

        TreeMap<String, Object> parameter = new TreeMap<>();

        parameter.put("openId", "8888888");

        parameter.put("name", "asdf");

        parameter.put("age", 12);

        parameter.put("sex", 1);

        long timestamp = System.currentTimeMillis();

        parameter.put("timestamp", timestamp);

        urlParameter(parameter);

    }

}

通过SpringBoot-RestTemplate调用
springBoot-RestTemple是上面三种方式的集大成者,代码编写更加简单,目前可以采用的调用第三方接口有:
delete() 在特定的URL上对资源执行HTTP DELETE操作
exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
postForEntity() POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
postForLocation() POST 数据到一个URL,返回新创建资源的URL
put() PUT 资源到特定的URL

代码如下:

import com.alibaba.fastjson.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.HttpEntity;

import org.springframework.http.HttpHeaders;

import org.springframework.http.HttpMethod;

import org.springframework.http.MediaType;

import org.springframework.http.ResponseEntity;

import org.springframework.web.client.RestTemplate;

public class RestTemplateTest {

    @Autowired

    private RestTemplate restTemplate;

    /**

     * 以get方式请求第三方http接口 getForEntity

     * @param url

     * @param request

     * @return

     */

    public <T> ResponseEntity<T> doGet(String url, Class<T> request){

        return restTemplate.getForEntity(url, request);

    }

    /**

     * 以post方式请求第三方http接口 postForEntity

     * @param url

     * @param request

     * @return

     */

    public <T> ResponseEntity<String> doPost(String url, Class<T> request){

        return restTemplate.postForEntity(url, request, String.class);

    }

    /**

     * exchange

     * @param url

     * @param request

     * @return

     */

    public String doExchange(String url, JSONObject request){

        //header参数

        HttpHeaders headers = new HttpHeaders();

        String token = "asdfghjkl123456";

        headers.add("authorization", token);

        headers.setContentType(MediaType.APPLICATION_JSON);

        //组装

        HttpEntity<JSONObject> requestHttpEntity = new HttpEntity<>(request, headers);

        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestHttpEntity, String.class);

        return responseEntity.getBody();

    }

}

通过Feign插件调用

引入feign插件
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

普通调用
@FeignClient(name = "xxx", url = "https://www.xxx.com")
public interface FeignUserService {
    @RequestMapping(method = RequestMethod.POST, value = "/getUserById",consumes = "application/x-www-form-urlencoded;charset=UTF-8")
    String getUserById(String id);
}

如果是调用自己Eureka上服务的接口
@FeignClient(value="被调用方Eureka上的服务名")
public interface FeignUserService {
    @RequestMapping(method = RequestMethod.GET, value = "/getUserById")
    String getUserById(@RequestParam(name="id") String id);
}

 

以上是 java第三方接口调用笔记 的全部内容, 来源链接: utcz.com/z/515837.html

回到顶部