java调用第三方api实践记录

准备工作

0. 前导图

项目文件结构

 

 

1. idea创建项目(不采用maven)

1)new > project > java > 项目名称

2)右键项目,添加框架支持,选择JAVAEE

3)配置idea的tomcat服务器,设置URL以及发布的上下文路径

4)在项目下新建lib文件夹,用于存放所需要的jar包

  (注) 试图直接导入本地的jar包到项目时,不成功,没找到资源,所以采用项目下复制所需的jar包导入

2. 导spring以及springmvc必要jar包

  commons-logging-1.2.jar
  spring-aop-5.3.8.jar
  spring-beans-5.3.8.jar
  spring-context-5.3.8.jar
  spring-core-5.3.8.jar
  spring-expression-5.3.8.jar


  spring-web-5.3.8.jar
  spring-webmvc-5.3.8.jar

  加到模块中

注:idea貌似不会自动调用tomcat的servlet-api.jar包,必须手动导入!

3. springmvc创建Hello World

采用分容器管理方式管理spring以及springmvc,配置文件放于src下

spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="top.dreamcenter.epoch" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>

    <context:property-placeholder location="classpath:ThirdPartyService.properties"/>
    <bean id="apikey" class="java.lang.String">
        <constructor-arg name="original" value="${APIKEY}"/>
    </bean>
    <bean id="chinaZKey" class="java.lang.String">
        <constructor-arg name="original" value="${CHINAZ.KEY}"></constructor-arg>
    </bean>
    <bean id="qWeatherKey" class="java.lang.String">
        <constructor-arg name="original" value="${QWEATHER.KEY}"></constructor-arg>
    </bean>
</beans>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <context:component-scan base-package="top.dreamcenter.epoch" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- method 1
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-service.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    -->

    <servlet>
        <servlet-name>thirdParty</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-*.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>thirdParty</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

 

编写代码

1. 创建工具类

ThirdPartyRequest [ 调用第三方api工具类]

package top.dreamcenter.epoch.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

public class ThirdPartyRequest {

    private static String doRequest(String urlPath,String data,String method) throws IOException {
        if (method.equalsIgnoreCase("GET") && data != null)
            urlPath = urlPath + "?" + data;
//        System.out.println(urlPath);
        URL url = new URL(urlPath);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod(method);
        OutputStreamWriter osw = null;
        if (data != null && method.equalsIgnoreCase("POST")) {
            connection.setDoOutput(true);
            osw = new OutputStreamWriter(connection.getOutputStream(),"utf-8");
            osw.write(data);
            osw.flush();
        }
        connection.setDoInput(true);
        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
        String result = br.readLine();
        if (osw != null) osw.close();
        br.close();
        return result;
    }

    /**
     * GET request
     * @param urlPath
     * @param data
     * @return
     * @throws IOException
     */
    public static String getGETRequest(String urlPath,String data) throws IOException {
        return doRequest(urlPath,data,"GET");
    }

    /**
     * POST request
     * @param urlPath
     * @param data
     * @return
     * @throws IOException
     */
    public static String getPOSTRequest(String urlPath,String data) throws IOException {
        return doRequest(urlPath,data,"POST");
    }
}

JsonDataRegex [粗糙的json字符串类型结果取值]

package top.dreamcenter.epoch.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonDataRegex {
    /**
     * basic way to get Json Data by regex, not useful when too many cycle
     * @param jsonData
     * @param target
     * @return
     */
    public static String getResult(String jsonData,String target){
        Pattern pattern1 = Pattern.compile(target + "\":\"(.*?)\"");
        Pattern pattern2 = Pattern.compile(target + "\":\\{(.*?)\\}");
        Pattern pattern3 = Pattern.compile(target + "\":\\[(.*?)\\]");

        Matcher matcher = pattern1.matcher(jsonData);
        if (matcher.find()) return matcher.group(1);
        matcher = pattern2.matcher(jsonData);
        if (matcher.find()) return "{" + matcher.group(1) + "}";
        matcher = pattern3.matcher(jsonData);
        if (matcher.find()) return "[" + matcher.group(1) + "]";
        return "";
    }
}

 

2. 创建controller和service

ThirdPartyController

package top.dreamcenter.epoch.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import top.dreamcenter.epoch.service.ThirdPartyService;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/api/third")
public class ThirdPartyController {

    @Autowired
    private ThirdPartyService tps;

    @RequestMapping("/date")
    public void getDateDetail(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(tps.getDateDetail());
    }

    @RequestMapping("/flatterer")
    public void getFlattererSentence(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(tps.getFlattererSentence());
    }

    @RequestMapping("/rainbow")
    public void getRainbowPiSentence(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(tps.getRainbowPiSentence());
    }

    @RequestMapping("/gold")
    public void getGoldSentence(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(tps.getGoldSentence());
    }

    @RequestMapping("/ip/number")
    public void getIP(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(tps.getIP());
    }

    @RequestMapping("/ip/detail")
    public void getIPDetail(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(tps.getIPDetail());
    }

}

ThirdPartyService

package top.dreamcenter.epoch.service;

import org.springframework.stereotype.Service;
import top.dreamcenter.epoch.util.JsonDataRegex;
import top.dreamcenter.epoch.util.ThirdPartyRequest;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;

@Service
public class ThirdPartyService {

    @Resource(name = "apikey")
    private String apikey;

    @Resource(name = "chinaZKey")
    private String chinaZKey;

    @Resource(name = "qWeatherKey")
    private String qWeatherKey;

    public String getDateDetail() throws IOException {
        return ThirdPartyRequest.getGETRequest(
                "http://api.tianapi.com/txapi/lunar/index",
                "key=" + apikey);
    }

    public String getFlattererSentence() throws IOException {
        return ThirdPartyRequest.getGETRequest(
                "http://api.tianapi.com/txapi/tiangou/index",
                "key=" + apikey);
    }

    public String getRainbowPiSentence() throws IOException {
        return ThirdPartyRequest.getGETRequest(
                "http://api.tianapi.com/txapi/caihongpi/index",
                "key=" + apikey);
    }

    public String getGoldSentence() throws IOException {
        return ThirdPartyRequest.getGETRequest(
                "http://api.tianapi.com/txapi/one/index",
                "key=" + apikey);
    }

    public String getIP() throws IOException {
        return ThirdPartyRequest.getGETRequest(
                "http://api.ipify.org/",null);
    }

    public String getIPDetail() throws IOException {
        return ThirdPartyRequest.getGETRequest(
                "https://apidatav2.chinaz.com/single/ip",
                "key=" + chinaZKey + "&ip=" + getIP());
    }
}

 

开始测试与运行

1. 启动tomcat服务

第一次启动失败了,原因:端口被占用了。😓

改了端口后成功了,并且正常的访问到了各个api的数据

2. 添加新的api调用需求

@RequestMapping("/weather")
public void getWeather(HttpServletResponse response) throws Exception {
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write(tps.getWeather());
}

此时,如果仍然用我之前的调用api工具类的方法,出现500错误,

考虑到可能是url中的中文可能无法识别的原因,进行了UrlEncoding,结果确实不报错了,

只是返回的结果出现乱码,更改了各种可能的编码格式,都不能成功。

无论怎样修改都没有效果。

无奈之下百度,结果大多数都用的httpcomponent这个apache旗下的jar包

3. 导入httpcomponent

经过不断的测试,发现这些包是必须的:

slf4j-api-1.7.25.jar
httpcore5-5.1.1.jar
httpclient5-5.1.jar

并且,貌似发布到tomcat时,这些资源没有发布过去,

所以,配置发布的时候,把这几项加到WEB-INF/lib下

4. 添加httpcomponent方式的get请求

public static String doGetApache(String url){
    //创建HttpClient对象
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    HttpGet get = new HttpGet(url);

    try {
        get.addHeader("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");
        HttpResponse response = httpClient.execute(get);

        if (response.getCode() == HttpStatus.SC_OK){
            //返回json格式
            String res = EntityUtils.toString(((CloseableHttpResponse) response).getEntity());
            return res;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

编写新api的请求服务

private String getDistrictInf(String district) throws IOException {
    return ThirdPartyRequest.doGetApache(
            "https://geoapi.qweather.com/v2/city/lookup" + "?" +
            "key=" + qWeatherKey + "&location=" + URLEncoder.encode(district,"utf-8"));
}
public String getWeather() throws Exception {
    String districtInf = getDistrictInf(
        JsonDataRegex.getResult(getIPDetail(), "District"));
    String districtCode = JsonDataRegex.getResult(districtInf, "id");

    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
    String dateFormatted = sdf.format(calendar.getTime());

    System.out.println(districtCode);

    return ThirdPartyRequest.doGetApache(
            "https://devapi.qweather.com/v7/weather/3d" + "?" +
            "key=" + qWeatherKey + "&location=" + districtCode
                +"&date=" + dateFormatted);
}

一些总结

  • 手动导jar包的话,jar包需要复制到项目下,并且servlet-api需要手动导入
  • tomcat的url后面项目名字和发布的项目上下文一样才能访问的到
  • ssm的整合有两中国方式,一种是DispatcherServlet配置时上下文值设置成通配,或者设置context-param/listener
  • 配置文件放在src目录下
  • maven真的香,虽然会对jar包不熟悉,但是,相比之下,太香了

 

 

 

 

posted @ 2021-07-09 16:46  时光潜流  阅读(665)  评论(0编辑  收藏  举报