业务场景:
公司需要将xml数据推送到第三方系统,提供了服务的url和xml报文的格式
1、将入参封装进DTO,并以xml的方式赋值为数据推送做准备
@Data
public class EsbServiceDto {
private String serialNo;
private String serviceId;
private String serviceTime;
private String sourceSysId;
private String bukrs;
private String fromDate;
private String toDate;
public static String buildCostCenterSendXml(String serviceId,String sourceSysId,String bukrs){
EsbServiceDto esbServiceDto = new EsbServiceDto();
esbServiceDto.serviceId = serviceId;
esbServiceDto.sourceSysId = sourceSysId;
esbServiceDto.bukrs = bukrs;
//请求中时间相关的参数注入
Date datenow = new Date();
SimpleDateFormat year = new SimpleDateFormat("yyyyMMdd");
String date = year.format(datenow);
SimpleDateFormat hour = new SimpleDateFormat("HHmmss");
String time = hour.format(datenow);
esbServiceDto.serialNo = date+sourceSysId+time;
esbServiceDto.serviceTime = date + time;
Date yesterday = new Date(datenow.getTime() - 86400000L);
esbServiceDto.fromDate = new SimpleDateFormat("yyyy-MM-dd").format(yesterday);
esbServiceDto.toDate = new SimpleDateFormat("yyyy-MM-dd").format(datenow);
return esbServiceDto.buildCostCenterSendXml();
}
public String buildCostCenterSendXml(){
return "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<soapenv:Envelope\n" +
" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
" xmlns:impl=\"http://impl.webservcice.eis.com/\">\n" +
" <soapenv:Header>\n" +
" <impl:Route>\n" +
" <SerialNO>"+this.serialNo+"</SerialNO>\n" +
" <ServiceID>"+this.serviceId+"</ServiceID>\n" +
" <ServiceTime>"+this.serviceTime+"</ServiceTime>\n" +
" <SourceSysID>"+this.sourceSysId+"</SourceSysID>\n" +
" </impl:Route>\n" +
" </soapenv:Header>\n" +
" <soapenv:Body>\n" +
" <impl:EsbServiceOperation>\n" +
" <Importing>\n" +
" <I_BUKRS>"+this.bukrs+"</I_BUKRS>\n" +
" <I_FROM_DATE>"+this.fromDate+"</I_FROM_DATE>\n" +
" <I_TO_DATE>"+this.toDate+"</I_TO_DATE>\n" +
" <I_OTHER_FLAG />\n" +
" </Importing>\n" +
" </impl:EsbServiceOperation>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
}
}
2、根据请求方式的不同将RestTemplate封装成不同的参数调用
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.nio.charset.StandardCharsets;
/**
* Description: http请求类
* @version 1.0
*/
@Slf4j
public class HttpUtil {
private static final RestTemplate REST_TEMPLATE = new RestTemplate();
static {
REST_TEMPLATE.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
/**
* 发送POST JSON请求
*
* @param url 请求地址
* @param data 请求数据
*/
public static JSONObject post(String url, Object data) {
return post(url, data, JSONObject.class);
}
/**
* 发送POST JSON请求
*
* @param url 请求地址
* @param data 请求数据
* @param returnClass 返回类型
*/
public static <T> T post(String url, Object data, Class<T> returnClass) {
log.info("发送HTTP post请求 url: {},data: {}", url, data);
String resultStr = REST_TEMPLATE.postForObject(url, data, String.class);
log.info("HTTP POST请求返回数据: {}", resultStr);
return JSON.parseObject(resultStr, returnClass);
}
/**
* 发送POST JSON请求(携带鉴权)
*
* @param url 请求地址
* @param data 请求数据
* @param requestHeaders 请求头
* @param returnClass 返回类型
*/
public static <T> T post(String url, Object data, HttpHeaders requestHeaders, Class<T> returnClass) {
log.info("发送HTTP post请求 url: {},data: {},header:{}", url, data,requestHeaders);
HttpEntity<Object> requestEntity =new HttpEntity<>(data,requestHeaders);
String resultStr = REST_TEMPLATE.postForObject(url, requestEntity, String.class);
log.info("HTTP POST请求返回数据: {}", resultStr);
return JSON.parseObject(resultStr, returnClass);
}
/**
* 发送GET请求
*/
public static <T> T get(String url, Class<T> returnClass) {
log.info("发送HTTP GET请求 url: {}", url);
String resultStr = REST_TEMPLATE.getForObject(URI.create(url), String.class);
log.info("HTTP GET请求返回数据: {}", resultStr);
return JSON.parseObject(resultStr, returnClass);
}
/**
* 发送POST JSON请求(携带鉴权)
*
* @param url 请求地址
* @param data 请求数据
* @param requestHeaders 请求头
* @param returnClass 返回类型
*/
public static <T> T get(String url, Object data, HttpHeaders requestHeaders, Class<T> returnClass) {
log.info("发送HTTP get请求 url: {},data: {}", url, data);
HttpEntity<Object> requestEntity =new HttpEntity<>(data,requestHeaders);
ResponseEntity<T> exchange = REST_TEMPLATE.exchange(url, HttpMethod.GET, requestEntity, returnClass);
log.info("HTTP GET请求返回数据: {}", exchange);
return exchange.getBody();
}
/**
* 发送post表单请求
* <p>
* 上传文件示例 {@code data.put("file", new FileSystemResource()));}
*/
public static <T> T postFormData(String url, MultiValueMap<String, Object> data, Class<T> returnClass) {
log.info("发送HTTP POST 表单请求 url: {} ,data: {}", url, data);
String resultStr = REST_TEMPLATE.postForObject(url, data, String.class);
log.info("HTTP POST表单请求返回数据: {}", resultStr);
return JSON.parseObject(resultStr, returnClass);
}
/**
* 发送post xml请求
*/
public static String postXml(String url, String xmlString) {
log.info("发送HTTP POST XML 请求 url: {} ,data: {}", url, xmlString);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_XML);
String resultStr = REST_TEMPLATE.postForObject(url, new HttpEntity<>(xmlString, httpHeaders), String.class);
log.info("HTTP POST XML返回数据: {}", resultStr);
return resultStr;
}
}
3、将封装的数据调用发送请求 String soap = HttpUtil.postXml(gxSendUrl, xmlInfo);
/**
* Description: 请求esb获取数据
* @version 1.0
* @author zhanglin
* @date 2022/6/9 16:00
*/
@SneakyThrows
private List<ReceiveDealerInfoDto> sendInfoToEsb(){
String serviceId = gxserviceId;
String sourceSysId = gxSourceSysId;
GxEsbQueryReqDTO gxEsbQueryReqDTO = new GxEsbQueryReqDTO();
gxEsbQueryReqDTO.setServiceId(serviceId);
gxEsbQueryReqDTO.setSourceSysId(sourceSysId);
gxEsbQueryReqDTO.setPartType("D");
// 公司编码
List<String> companyList = companyList();
List<ReceiveDealerInfoDto> resultList = new ArrayList<>();
for (String company : companyList) {
gxEsbQueryReqDTO.setBukrs(company);
// 日期处理
Date datenow = new Date();
SimpleDateFormat year = new SimpleDateFormat("yyyyMMdd");
String date = year.format(datenow);
SimpleDateFormat hour = new SimpleDateFormat("HHmmss");
String nowTime = hour.format(datenow);
Date afterDate = new Date(new Date().getTime()+ 4*3600*1000);//4小时后的数据
String after4hourTime = hour.format(afterDate);
gxEsbQueryReqDTO.setUpdateDate(date);
gxEsbQueryReqDTO.setUpdateDateTo(date);
gxEsbQueryReqDTO.setUpdateTime(nowTime);
gxEsbQueryReqDTO.setUpdateTimeTo(after4hourTime);
// 获取返回数据
String s = EsbGxQueryServiceDTO.buildDataOfCostCenterSendXml(gxEsbQueryReqDTO);
String soap = HttpUtil.postXml(gxSendUrl, s);
System.out.println("打印输出:"+ soap);
// 将数据解析返回
List<ReceiveDealerInfoDto> receiveDealerInfoDtoList = dealSoapInfo(soap);
resultList.addAll(receiveDealerInfoDtoList);
}
return resultList;
}
4、由于返回的数据也是xml数据,我们需要解析出我们需要的数据进行处理
美化后数据如下: 我们实际要抓的是ET_OUT中的数据
解析xml需要引入以下依赖:
<!-- 解析xml引入依赖-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
这里需要注意的一点是,string类型的xml不要手动进行换行,我们按照返回数据原封给它解析处理就好了
/**
* 将soap中的数据解析成List<T>
* @param soap 数据如下
* String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:impl=\"http://impl.webservcice.eis.com/\"><soapenv:Header><impl:Route><SerialNO>2022061304011132713</SerialNO><ServiceID>03102000000613</ServiceID><ServiceTime>20220613132713</ServiceTime><SourceSysID>04011</SourceSysID><ServiceResponse><Status>COMPLETE</Status></ServiceResponse></impl:Route></soapenv:Header><soapenv:Body><impl:EsbServiceResponse><ET_OUT p_type=\"G\" loop_num=\"1\"><NAME1>浙江星全汽车服务有限公司</NAME1><KUNNR>D00200102</KUNNR><BANKN/><KOINH/><BANKL/><BANKA/><ORT01/><ZSSYH/><ZYHMC/><BUKRS>9110</BUKRS><ZZHLX/><STATUS>I</STATUS><TEXTVALUE1/><TEXTVALUE2/><TEXTVALUE3/></ET_OUT><ET_OUT p_type=\"G\" loop_num=\"98\"><NAME1>天津中远河西店</NAME1><KUNNR>D22070302</KUNNR><BANKN/><KOINH/><BANKL/><BANKA/><ORT01/><ZSSYH/><ZYHMC/><BUKRS>9110</BUKRS><ZZHLX/><STATUS>I</STATUS><TEXTVALUE1/><TEXTVALUE2/><TEXTVALUE3/></ET_OUT></impl:EsbServiceResponse> </soapenv:Body></soapenv:Envelope>";
* @return
*/
@SneakyThrows
public List<ReceiveDealerInfoDto> dealSoapInfo(String soap) {
Map map = new HashMap();
List<ReceiveDealerInfoDto> dataList = new ArrayList<>();
Document doc = DocumentHelper.parseText(soap);
//获取根元素,准备递归解析这个XML树
Element root = doc.getRootElement();
//获取到data的集合
List<Element> mzList = root.element("Body").element("EsbServiceResponse").elements("ET_OUT");
//遍历data集合
for (Element e : mzList) {
List<Element> elements = e.elements();
//遍历将元素中的key和value存到map中
for (Element item : elements) {
if (!org.springframework.util.StringUtils.isEmpty(item.getText())) {
map.put(item.getName(), item.getText());
}
}
//将map转换成对象
ReceiveDealerInfoDto data = BeanUtil.mapToBean(map, ReceiveDealerInfoDto.class, true);
//对象存到集合中
dataList.add(data);
}
return dataList;
}