本文介绍了三方平台接口对接方法,一是基于OkHttp请求工具及dom4j报文封装解析xml的方法,二是采用RestTemplate方法封装请求,三是采用建立视图和从库数据源的方式查询。
一、OkHttp请求工具及dom4j报文封装解析
1、 依赖引入
java
<!-- okhttp3包 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
<scope>compile</scope>
</dependency>
java
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.4</version>
</dependency>
2、OkHttp请求工具类
java
package com.inspur.common.utils.okhttp;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* OkHttp封装,调用示例OkHttpUtil.postJson(...)
*/
public class OkHttpUtil {
private static final Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
private static final byte[] LOCKER = new byte[0];
private static volatile OkHttpClient okHttpClient;
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
private OkHttpUtil() {
}
private static OkHttpClient getOkHttpClient() {
if (okHttpClient == null) {
synchronized (LOCKER) {
if (okHttpClient == null) {
OkHttpClient.Builder ClientBuilder = new OkHttpClient.Builder();
ClientBuilder.readTimeout(30, TimeUnit.SECONDS);//读取超时
ClientBuilder.connectTimeout(30, TimeUnit.SECONDS);//连接超时
ClientBuilder.writeTimeout(60, TimeUnit.SECONDS);//写入超时
okHttpClient = ClientBuilder.build();
}
}
}
return okHttpClient;
}
/**
* 发送get请求
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static Result<String> get(String url) throws IOException {
logger.debug("请求url:{}", url);
Request request = new Request.Builder()
.url(url)
.get()
.build();
return execute(request);
}
/**
* 发送get请求,带参数
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static Result<String> get(String url, Map<String, String> params) throws IOException {
logger.debug("请求url:{}", url);
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
//追加表单信息
urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
}
Request request = new Request.Builder()
.url(urlBuilder.build())
.build();
return execute(request);
}
/**
* 发送json请求
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static Result<String> postJson(String url, String json) throws IOException {
logger.debug("请求url:{},请求体:{}", url, json);
RequestBody requestBody = RequestBody.create(json,JSON);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
return execute(request);
}
public static Result<String> postXml(String url, String xml) throws IOException {
RequestBody requestBody = RequestBody.create(xml, XML);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
return execute(request);
}
/**
* 发送form表单post请求
*
* @param url
* @param params
* @return
* @throws IOException
*/
public static Result<String> post(String url, Map<String, String> params) throws IOException {
logger.debug("请求地址:{};", url);
//创建一个FormBody.Builder
FormBody.Builder builder = new FormBody.Builder();
for (Map.Entry<String, String> entry : params.entrySet()) {
//追加表单信息
builder.add(entry.getKey(), entry.getValue());
}
//生成表单实体对象
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
return execute(request);
}
/**
* 发送form表单post请求
*
* @param url
* @param params
* @return
* @throws IOException
*/
public static Result<String> postWithHeader(String url, Map<String, String> params, String... headers) throws IOException {
logger.debug("请求url:{};", url);
//创建一个FormBody.Builder
FormBody.Builder builder = new FormBody.Builder();
for (Map.Entry<String, String> entry : params.entrySet()) {
//追加表单信息
builder.add(entry.getKey(), entry.getValue());
}
//生成表单实体对象
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.headers(Headers.of(headers))
.post(formBody)
.build();
return execute(request);
}
/**
* 发送form表单post请求
*
* @param url
* @param params
* @return
* @throws IOException
*/
public static Result<String> postFile(String url, String fileName, File file, Map<String, String> params) throws IOException {
logger.debug("请求url:{};", url);
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.addFormDataPart(fileName, fileName, RequestBody.create(MediaType.parse("application/octet-stream"), file));
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
//追加表单信息
builder.addFormDataPart(entry.getKey(), entry.getValue());
}
}
MultipartBody multipartBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(multipartBody)
.build();
return execute(request);
}
private static Result<String> execute(Request request) {
Result<String> result = new Result();
try (Response response = OkHttpUtil.getOkHttpClient().newCall(request).execute()) {
logger.debug("{} 请求结果:{}", request.url().url(), response);
if (response.isSuccessful()) {
ResponseBody body = response.body();
if (body != null) {
result = Result.ok(response.message(), body.string());
}else {
result = Result.ok(response.message());
}
}else {
result = Result.fail(response.code(),response.message());
}
} catch (Exception e) {
result = Result.fail(e.getMessage());
}
return result;
}
}
3、基于dom4j解析和封装xml
(1)xml文件报文示例
/admin-module/src/main/resources/nc/classStudent.xml
XML
<?xml version="1.0" encoding='UTF-8'?>
<ufinterface account="tpy63_wzx0731" billtype="4D" filename="" groupcode="" isexchange="Y" replace="Y" roottag="" sender="gyhlw">
<classInfo>
<school>市第一中学</school>
<city>济南</city>
<location>2楼</location>
</classInfo>
<students>
<student name="zhangsan" age="18"></student>
<student name="lisi" age="19"></student>
</students>
</ufinterface>
(2)构建封装xml报文文件
java
public String buildXml(){
// 创建saxReader对象
SAXReader reader = new SAXReader();
try (InputStream classInfo = new ClassPathResource("nc/classStudent.xml").getInputStream()) {
// 通过read方法读取一个文件 转换成Document对象
Document document = reader.read(classInfo);
// 获取根节点元素对象
Element node = document.getRootElement();
// 根节点下的一级子节点
Element classInfo = node.element("classInfo"); // 根节点下的子节点 classInfo
Element students = node.element("students"); // 根节点下的子节点 students
// 一级子节点classInfo 下属二级节点
students.element("school").setText("市第一中学");
students.element("city").setText("济南");
students.element("location").setText("2楼");
// 一级子节点students 下属二级节点
// 以此添加成List并设置属性
List<Student> st = ArrayList<T> obj = new ArrayList<Student>() {{
add(new Student("zhangsan",18));
add(new Student("lisi",19));
}};
students.stream().forEach(student -> {
root.addElement("student")
.addAttribute("name", student.getName())
.addAttribute("age", String.valueOf(student.getAge()))
});
// 生成xml对象
String xml = document.asXML();
logger.info("生成XML:\n{} ", xml);
}
}
(3)okHttp三方接口请求
(4)xml报文读取解析
java
public Object handlerReturn() {
try {
/* 直接读取文件解析
// 创建SAXReader
SAXReader saxReader = SAXReader.createDefault();
// 将xml解析为树
Document document = saxReader.read("xml/students.xml");*/
String xml = this.buildXml();
// 三方接口请求地址
String url = "http://110.10.1.11:8888/service/xxx"
// 1、请求发送
Result<String> result = OkHttpUtil.postXml(url, xml);
if (result.isOk()) {
String resMess = result.getData();
logger.info("调用结果:{}", resMess);
// resMess实际为classStudent.xml文件格式内容
Document respXml = DocumentHelper.parseText(resMess);
Element rootElement = respXml.getRootElement();
// 2、获取根节点下的一级子节点
Element classInfo = rootElement.element("classInfo"); // 根节点下的子节点 classInfo
Element students = rootElement.element("students"); // 根节点下的子节点 students
// 3、获取一级子节点classInfo 下属二级节点属性
String school = classInfo.elementText("school");
String city = classInfo.elementText("city");
String location = classInfo.elementText("location");
// 4、获取一级子节点students,遍历下属二级节点student列表并获取属性值
List<Element> eles = students.elements();
List<Student> students = new ArrayList<>();
// 遍历子节点列表
for(Element ele : eles){
// 读取节点属性
String name = element.attributeValue("name");
Interger age = element.attributeValue("age");
Student stu = new Student(name,age);
students.add(stu)
}
}
} catch (DocumentException | IOException e) {
logger.error("调用接口异常", e);
}
// 5、解析结果值构建对应实体类或map
HashMap resObj = new HashMap<>();
resObj.put("students",students);
resObj.put("school",school);
return resObj;
}
二、 RestTemplate
OutInterfaceDomain 实体类根据接口规范自行组装定义
1、依赖
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、使用
java
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
public class OutInterfaceService {
@Autowired
private RestTemplate restTemplate;
private String url = "http://110.1.1.129:8087/DataStandard/*****";
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
// 要传递的业务内容
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("DEVICE_NO", factoryDevice.getDeviceNo());
// 按接口规范组装
OutInterfaceDomain outInterfaceDomain = new OutInterfaceDomain();
outInterfaceDomain.setColumns(columnMap);
String contentJson = JSON.toJSONString(outInterfaceDomain, SerializerFeature.WriteMapNullValue);
HttpEntity<String> httpEntity = new HttpEntity<>(contentJson, httpHeaders);
// 调用三方接口
restTemplate.postForEntity(url, httpEntity, String.class);
}
三、sql视图
在原表建立视图,并创建新用户,赋予只读权限。使用@DataSource来切换数据库查询。
1、创建视图和用户并赋予权限
sql
grant select on [view] to [username];//查询视图权限
grant connect to [username];//连接数据库权限
# 创建设备视图
create or replace view factory_device_view as
select * from factory_device;
comment on table factory_device_view is '设备视图';
SELECT * FROM all_tab_cols WHERE table_name ='FACTORY_DEVICE_VIEW';
# 创建用户
create user jtgViewer identified by password123$
# 赋予权限
GRANT SELECT ON jtg.factory_device_view TO jtgViewer;
grant connect to jtgViewer
2、配置文件
XML
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: true
url: jdbc:mysql://192.168.100.200:3306/esis_tjzg?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
username: root
password: Inspur@2023
3、查询使用
java
@DataSource(DataSourceType.SLAVE)
public List<Map<String,Object>> selectOutAmountByMaterial(TImMaterialrequestbill tImMaterialrequestbill);