准备工作
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包不熟悉,但是,相比之下,太香了