Socket与Http方式解析发送xml消息封装中间件jar包

  最近项目代码中太多重复的编写Document,不同的接口需要不同的模板,于是重写提取公共部分打成jar包,方便各个系统统一使用~

  提取结构:

Http连接方式:

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

public class HttpConnect {
    
    final Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String SECCUESS_CODE = "000000";

    private RestTemplate restTemplate ;

    private int connectTimeout = 1000;

    private int readTimeout = 15000;
    
    private static final String CHARSET_GBK = "GBK";

    public String getMessages(Map<String,Object> sendData){
        restTemplate = createRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        MediaType type = new MediaType("text", "xml",
                Charset.forName(CHARSET_GBK));
        headers.setContentType(type);
        String connectIp = (String) sendData.get("RequestIp");
        String connectPort = (String) sendData.get("RequestPort");
        String content = (String) sendData.get("message");
        String url = "http://" + connectIp + ":" + connectPort;
        HttpEntity<String> entity = new HttpEntity<String>(content, headers);
        String result = restTemplate.postForObject(url, entity, String.class);
        logger.info("send data:{},result:{}", content, result);
        
        return result;
    }
    
    public RestTemplate createRestTemplate() {
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setConnectTimeout(connectTimeout);
        requestFactory.setReadTimeout(readTimeout);

        RestTemplate restTemplate = new RestTemplate(requestFactory);
        restTemplate.getMessageConverters().add(0,
                new MyStringHttpMessageConverter());
        return restTemplate;
    }
    
    static class MyStringHttpMessageConverter extends
    StringHttpMessageConverter {

        List<Charset> acceptedCharsets = Arrays.asList(Charset.forName("GBK"),
        Charset.forName("GB2312"), Charset.forName("GB18030"),
        Charset.forName("UTF-8"));

        @Override
        protected List<Charset> getAcceptedCharsets() {
        return acceptedCharsets;
        }
    }
}

Socket方式:

package SocketClient;
 
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class SocketClient {
 
 final Logger logger = LoggerFactory.getLogger(this.getClass());
 
 private Socket socket;
 
 public SocketClient() {
 
 }
 
 public SocketClient(String connectIp, String connectPort,
   String connectTime, String readTime) throws SocketTimeoutException,
   ConnectException, UnknownHostException, Exception {
   createSocket(connectIp, connectPort, connectTime, readTime);
 }
 
 private void createSocket(String hostName, String port, String connectTime,
 String readTime) throws SocketTimeoutException, ConnectException,
   UnknownHostException, Exception {
   InetAddress address = InetAddress.getByName(hostName);
   int timeOut = Integer.parseInt(connectTime);
   int readTimeOut = Integer.parseInt(readTime);
   socket = new Socket();
   int connectPort = Integer.valueOf(port);
   InetSocketAddress socketAddr = new InetSocketAddress(address,
   connectPort);
   // 连接后返回结果超时时间
   socket.setSoTimeout(readTimeOut);
   socket.setReuseAddress(true);
   socket.connect(socketAddr, timeOut);
 }
 
 public void sendData(byte[] data) throws IOException,RuntimeException{
   DataOutputStream dos = null;
 
 try {
   dos = new DataOutputStream(socket.getOutputStream());
   dos.writeInt(data.length);
   dos.write(data);
 } catch (IOException e) {
   e.printStackTrace();
 } catch (RuntimeException e) {
   e.printStackTrace();
 } finally {
   if (dos != null) {
     dos.close();
   }
   }
 }
 
 public byte[] recvData() throws Exception {
   byte[] data = null;
   DataInputStream dis = null;
 
   try {
     dis = new DataInputStream(socket.getInputStream());
     int dataLen = dis.readInt();
     data = new byte[dataLen];
     dis.readFully(data);
     } catch (IOException e) {
       e.printStackTrace();
     }finally {
       if (dis != null) {
         dis.close();
       }
     }
     return data;
 }
 
 public void destory()  {
 if (this.socket != null && !this.socket.isClosed()) {
   try {
     this.socket.close();
     this.socket = null;
     } catch (IOException e) {
     logger.error("Socket Destory Error",e);
     }
     }
   }
}

加载hdfs中的模板文件,并转化为map形式嵌入项目中,存入内存缓存

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class LoadHdfsTemplate {
    static final Logger logger = LoggerFactory
            .getLogger(LoadHdfsTemplate.class);
    
    protected FileSystem fileSystem;
    
    public final boolean checkFile(String filePath) {
        boolean exists = false;
        try {
            Path path = new Path(filePath);
            exists = fileSystem.exists(path);
        } catch (IOException e) {
            logger.error("模板文件不存在!", e);
        } catch (Exception e) {
            logger.error("", e);
        }
        return exists;
    }
    
    public Map<String,Object> readHdfsFile(String hdfsPath) throws IOException{
        Path path = new Path(hdfsPath);
        InputStream in = fileSystem.open(path);
        List<String> lines = IOUtils.readLines(in);
        if(null == lines || lines.isEmpty()){
            return null;
        }
        Map<String,Object> map = new HashMap<String,Object>();
        int rowNum = 0;
        for(String line : lines){
            rowNum++;
            String[] content = line.split("    ");
            String code = content[0];
            String template = content[1];
            if(StringUtils.isEmpty(line) || StringUtils.isEmpty(template)){
                logger.error("第{}条模板格式错误!内容为:{}",rowNum,line);
                continue;
            }
            map.put(code, template);
        }
        return map;
        
    }
}

加载本地文件,用于测试

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;

public class LoadTemplate{
    
    final Logger logger = LoggerFactory.getLogger(LoadTemplate.class);

    private String filePath = "D:/template.txt";
    
    public Map<String,Object> templateMap = new HashMap<String,Object>();
    
    public Map<String, Object> loadTemplate() {
        try {
            File file = new File(filePath);
            Integer lineCount = Files.readLines(file, Charsets.UTF_8,
                    new LineProcessor<Integer>() {
                        private int lineCount;

                        public boolean processLine(String line)
                                throws IOException {
                            doSync(line);
                            lineCount++;
                            logger.debug("{} :  {}", lineCount, line);
                            return true;
                        }

                        public Integer getResult() {
                            return lineCount;
                        }
                    });
            
            
            logger.info("读取{}行数据。", lineCount);
        } catch (Exception e) {
            logger.error("载入模板文件出错!", e);
        }
        return templateMap;
    }
    
    private void doSync(String line) {
        if(StringUtils.isEmpty(line)){
            return;
        }
        
        String[] content = line.split("    ");
        String code = content[0];
        String template = content[1];
        templateMap.put(code, template);
    }
}

解析发送的xml模板: (这里说明下,在系统调用时候,会传入调用的接口对应的模板,与封装的对应模板的值,与模板进行匹配封装)

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import com.google.common.base.Preconditions;
public class ParseTemplate {
	
	public Map<String,Object> parseData(Map<String,Object> data,String template) throws DocumentException{
		Map<String,Object> parseMap = new HashMap<String,Object>();
		  Document documnet = DocumentHelper.parseText(template);
		  Element root = documnet.getRootElement();
		  Element headElement = root.element("Head");
		  Preconditions.checkArgument(headElement != null, "XML中无Head元素");
		  HeadElements(parseMap,headElement);
		  Element bodyElement = root.element("body");
		  if(null == bodyElement){
			    bodyElement = root.element("Body");
		  }else{
			    Preconditions.checkArgument(bodyElement != null, "XML中无body元素");
		  }
		  bodyElements(data,bodyElement);
		  parseMap.put("message", "<?xml version='1.0' encoding='gb18030'?>"+root.asXML());
		  return parseMap;
	}
	//
	@SuppressWarnings("unchecked")
	private void HeadElements(Map<String,Object> parseMap , Element parentElement) {
		  List<Element> fieldElements = parentElement.elements();
		  for (Element fieldElement : fieldElements) {
			    if(fieldElement.getName().equals("RequestType")){
				      parentElement.remove(fieldElement);
				      parseMap.put("RequestType", fieldElement.getText());
			    }
			    if(fieldElement.getName().equals("RequestIp")){
				      parentElement.remove(fieldElement);
				      parseMap.put("RequestIp", fieldElement.getText());
			    }
			    if(fieldElement.getName().equals("RequestPort")){
				      parentElement.remove(fieldElement);
				      parseMap.put("RequestPort", fieldElement.getText());
			    }
			    if(fieldElement.getName().equals("CreateTime")){
				      String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
				      fieldElement.setText(now);
			    }
		  }
	}
	
	@SuppressWarnings("unchecked")
	private void bodyElements(Map<String,Object> data , Element parentElement) {
		@SuppressWarnings("rawtypes")
		  Iterator iter = parentElement.elementIterator();
		  while(iter.hasNext()){
			    Element childElement = (Element) iter.next();
			    String filedName = childElement.getName();
			    if(filedName.equals("field")){	//如果数据为filed,则进行填充处理
				      String name = childElement.attributeValue("name");
				      String value = (String) data.get(name);
				      if(null != value){
					        childElement.setText(value);
				      }
			    }else if(filedName.equals("struct")){
				    //如果存在该节点对应的field填充数据,则进行后续处理
				    String name = childElement.attributeValue("name");
				    if(data.containsKey(name)){	
					      Map<String,Object> childData = (Map<String, Object>) data.get(name);
					      bodyElements(childData, childElement);
				    }
			  }
		}
	}
	
	/**
	 * 解析返回报文
	 * @param input
	 * @return
	 * @throws DocumentException
	 */
	public Map<String,Object> parseXml(String input) throws DocumentException{
		  Map<String, Object> resultMap = new HashMap<String,Object>();
		  Map<String,Object> result = new HashMap<String,Object>();
		  Document documnet = DocumentHelper.parseText(input);
		  Element root = documnet.getRootElement();
		  Element headElement = root.element("Head");
		  Preconditions.checkArgument(headElement != null, "XML中无Head元素");
		  result.putAll(setHeadData(resultMap, headElement));
		  Element bodyElement = root.element("Body");
		  Preconditions.checkArgument(bodyElement != null, "XML中无Body元素");
		  result.putAll(setBodyData(resultMap, bodyElement));
		  return 	result;
	}
	
	@SuppressWarnings("unchecked")
	public Map<String,Object> setHeadData(Map<String,Object> dataMap,Element parentElement){
		  List<Element> fieldElements = parentElement.elements();
		  for (Element fieldElement : fieldElements) {
			    String name = fieldElement.getName();
			    String value = fieldElement.getText();
			    dataMap.put(name, value);
		  }
		  return dataMap;
		
	}
	
	@SuppressWarnings("unchecked")
	private Map<String,Object> setBodyData(Map<String, Object> dataMap, Element parentElement) {
		  List<Element> fieldElements = parentElement.elements("field");
		  if(fieldElements.size() != 0){
			    Preconditions.checkArgument(
					    (fieldElements != null && !fieldElements.isEmpty()),
					    "XML缺少field元素");
			    for (Element fieldElement : fieldElements) {
				      String name = fieldElement.attributeValue("name");
				      String value = StringUtils.trimToNull(fieldElement.getTextTrim());
				      dataMap.put(name, value);
			    }
		  }
		  return dataMap;
	}
}

方法调用入口: 从xml解析获得的连接方式为socket或http及其Ip和port 进行相应连接,发送并返回请求数据,随之进行解析封装入map,供应用系统提取使用字段值。

import java.io.UnsupportedEncodingException;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;

import Http.HttpConnect;
import Socket.SocketClient;

import temlateRead.ParseTemplate;

public class InterFaceCall {
    
    public  Map<String,Object> getMessage(Map<String,Object> map,String template){
        if(null != map && StringUtils.isNotBlank(template) && !map.isEmpty()){
            try{
                //解析封装模板
                ParseTemplate parse = new ParseTemplate();
                Map<String,Object> sendData = parse.parseData(map,template);
                //连接方式
                String connectType = (String) sendData.get("RequestType");
                String connectIp = (String) sendData.get("RequestIp");
                String connectPort = (String) sendData.get("RequestPort");
                if("socket".equals(connectType)){
                    String content = (String) sendData.get("message");
                    SocketClient socketClient = new SocketClient(connectIp,connectPort); 
                    socketClient.sendData(content.getBytes());
                    byte[] res = socketClient.recvData();
                    String resultData =  new String(res,"gb18030");
                    map = parse.parseXml(resultData);
                }else if("http".equals(connectType)){
                    HttpConnect request = new HttpConnect();
                    String resultData = request.getMessages(sendData);
                    map = parse.parseXml(resultData);
                }
            }catch(DocumentException e){
                map.put("errorMessage", e);
                e.printStackTrace();
            }catch (UnsupportedEncodingException e) {
                map.put("errorMessage", e);
                e.printStackTrace();
            }catch(Exception e){
                map.put("errorMessage", e);
                e.printStackTrace();
            }
        }else{
            map.put("errorMessage", "传入数据或模板不能为空"); } return map; } }

测试类:

public static void main(String args[]){
        String cusUseCashAmount = "";
        Map<String,Object> resultData = null;
        String template = "";
        LoadTemplate aaa = new LoadTemplate();
        Map<String,Object> temp = aaa.loadTemplate();;
        //从****接口获取用户可用取现金额
        String cardNo = "";
        template = (String) temp.get("****");
        InterFaceCall DataMap = new InterFaceCall();
        Map<String,Object> sendData = new HashMap<String,Object>();
        String SeqNo = UUID.randomUUID().toString().replace("-", "");
        sendData.put("TrxType", "10010");
        ......
        resultData = DataMap.getMessage(sendData, template);
        cusUseCashAmount = (String)resultData.get("value1");
    }

 整理还没有完善,异常处理以及压力测试还没有进行,有空还要重写下。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏cmazxiaoma的架构师之路

你真的了解Spring MVC处理请求流程吗?

3064
来自专栏技术专栏

java程序 如何优雅地读取xml文件

5742
来自专栏mukekeheart的iOS之旅

No.009 Palindrome Number

9. Palindrome Number Total Accepted: 136330 Total Submissions: 418995 Difficulty...

2287
来自专栏算法修养

FZU 2150 Fire Game(BFS)

Problem 2150 Fire Game Accept: 1302    Submit: 4569 Time Limit: 1000 mSec    M...

3224
来自专栏一个会写诗的程序员的博客

禅与 JavaScript 编程艺术, Zen and The Art of JavaScript Programming禅与 JavaScript 编程艺术

Zen and The Art of JavaScript Programming

1151
来自专栏Golang语言社区

【Go 语言每日package解析】 package json

Go 语言 开发包大全: http://www.goserver.club/discuz/ ... =12&from=portal 注:在开发包大全中找 jso...

3764
来自专栏JMCui

项目工具类

一、前言     在工作中,难免遇到各种各样的问题,每个人似乎都有一套自己的解决方案。而我,又不想每次解决完问题就把东西扔了,捡了芝麻,丢了西瓜,什么时候才能进...

4526
来自专栏吴生的专栏

spring boot 源码解析-SpringApplication初始化

就是这么简单的代码,构成了spring boot的世界. 那么代码中只有⼀个@SpringBootApplication 注解 和 调⽤了SpringAppli...

4445
来自专栏java、Spring、技术分享

深入分析Spring MVC中RequestBody与ResponseBody

  在SpringMVC中,可以使用@RequestBody和@ResponseBody两个注解,分别完成请求报文到对象和对象到响应报文的转换。在Sprin...

2301
来自专栏Hongten

python开发_calendar

如果你用过linux,你可能知道在linux下面的有一个强大的calendar功能,即日历

1202

扫码关注云+社区

领取腾讯云代金券