- 获取接口所需要的参数 以map的key value形式
Map<String, String> map = getCustomerInfoMapValue(basicInfo);
public Map<String, String> getCustomerInfoMapValue(CustBasicInfo basicInfo) {
//终端号//终端IP//获取的是本地的IP地址
map.put("终端IP", SocketUtil.getLocalHostLANAddress().getHostAddress());
//流水号 8 位交易日期+12 位交易序号
String trNum = SocketUtil.getTrNum(basicInfo.getId());
map.put("流水号", trNum);
map.put("当前日期时间", getStringDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
map.put("当前日期", getStringDate(new Date(), "yyyyMMdd"));
map.put("当前时间", getStringDate(new Date(), "HHmmss"));
return map;
}
- 根据接口要求创建报文头的枚举类:发送报文的 字段,名称,长度,必填,select转换,默认值
public class BaseXmlBeanEnum extends Enum {
private static final long serialVersionUID = 6582579870155714449L;
// 发送报文 字段,标记,长度,是否必填,select转换,默认值
// 接收报文 字段,标记
private String elementName ;
private String elementColumnName ;
private String elementLength ;
private String elementNotNull ;
private Map<String,String> elementOptions ;
private String elementDefaultValue ;
public BaseXmlBeanEnum(String elementName, String elementColumnName, String elementLength, String elementNotNull, Map<String,String> elementOptions, String elementDefaultValue) {
super(elementName);
this.elementName = elementName;
this.elementColumnName = elementColumnName;
this.elementLength = elementLength;
this.elementNotNull = elementNotNull;
this.elementOptions = elementOptions;
this.elementDefaultValue = elementDefaultValue;
}
public String getElementName() {
return elementName;
}
public void setElementName(String elementName) {
this.elementName = elementName;
}
public String getElementColumnName() {
return elementColumnName;
}
public void setElementColumnName(String elementColumnName) {
this.elementColumnName = elementColumnName;
}
public String getElementLength() {
return elementLength;
}
public void setElementLength(String elementLength) {
this.elementLength = elementLength;
}
public String getElementNotNull() {
return elementNotNull;
}
public void setElementNotNull(String elementNotNull) {
this.elementNotNull = elementNotNull;
}
public Map<String, String> getElementOptions() {
return elementOptions;
}
public void setElementOptions(Map<String, String> elementOptions) {
this.elementOptions = elementOptions;
}
public String getElementDefaultValue() {
return elementDefaultValue;
}
public void setElementDefaultValue(String elementDefaultValue) {
this.elementDefaultValue = elementDefaultValue;
}
}
public class Socket_Head extends BaseXmlBeanEnum {
private static final long serialVersionUID = 795381566820679308L;
public Socket_Head(String elementName, String elementColumnName, String elementLength, String elementNotNull, Map<String, String> elementOptions, String elementDefaultValue) {
super(elementName, elementColumnName, elementLength, elementNotNull, elementOptions, elementDefaultValue);
}
public static List<BaseXmlBeanEnum> getAllElement() {
List<BaseXmlBeanEnum> list = null;
try {
list = BaseXmlBeanEnum.getEnumList(Socket_Head.class);
}catch (Exception e){
}
return list;
}
public static BaseXmlBeanEnum getElementByName(String elementName) throws Exception{
BaseXmlBeanEnum baseXmlBeanEnum = (BaseXmlBeanEnum) BaseXmlBeanEnum.getEnum(BaseXmlBeanEnum.class, elementName);
return baseXmlBeanEnum;
}
public static final BaseXmlBeanEnum TrCode = new Socket_Head("TrCode", "交易码", "6", "1", null, "");
public static final BaseXmlBeanEnum TermId = new Socket_Head("TermId", "终端IP", "20", "1", null, "");
public static final BaseXmlBeanEnum TermDateTime = new Socket_Head("TermDateTime", "当前日期时间", "20", "1", null, "");
public static final BaseXmlBeanEnum TermIP = new Socket_Head("TermIP", "终端IP", "20", "1", null, "");
public static final BaseXmlBeanEnum SndDate = new Socket_Head("SndDate", "当前日期", "8", "1", null, "");
public static final BaseXmlBeanEnum SndTime = new Socket_Head("SndTime", "当前时间", "6", "1", null, "");
public static final BaseXmlBeanEnum Memo = new Socket_Head("Memo", "保留", "100", "0", null, "");
public static final BaseXmlBeanEnum RetCode = new Socket_Head("RetCode", "返回码", "6", "0", null, "");
public static final BaseXmlBeanEnum Desc = new Socket_Head("Desc", "错误信息", "60", "0", null, "");
}
- 根据接口要求创建报文体的枚举类
public class Socket_015001_1 extends BaseXmlBeanEnum {
public Socket_015001_1(String elementName, String elementColumnName, String elementLength, String elementNotNull, Map<String, String> elementOptions, String elementDefaultValue) {
super(elementName, elementColumnName, elementLength, elementNotNull, elementOptions, elementDefaultValue);
}
public static List<BaseXmlBeanEnum> getAllElement() {
List<BaseXmlBeanEnum> list = null;
try {
list = BaseXmlBeanEnum.getEnumList(Socket_015001_1.class);
}catch (Exception e){
}
return list;
}
public static String getSocketCode() {
return Socket_015001_1.class.getName().split("_")[1];
}
public static BaseXmlBeanEnum getElementByName(String elementName) throws Exception{
BaseXmlBeanEnum baseXmlBeanEnum = (BaseXmlBeanEnum) BaseXmlBeanEnum.getEnum(BaseXmlBeanEnum.class, elementName);
return baseXmlBeanEnum;
}
public static final BaseXmlBeanEnum customername = new Socket_015001_1("customername","基本信息客户名称","60","1",null,"");
public static final BaseXmlBeanEnum certificatestype = new Socket_015001_1("certificatestype","基本信息证件类型","1","1",
new HashMap<String, String>(){{put("1","01");put("2","08");put("3","03");put("4","02");put("5","07");put("6","04");put("7","05");put("8","09");put("9","10");put("10","06");put("11","99");}},"01");
public static final BaseXmlBeanEnum idnumber = new Socket_015001_1("idnumber","基本信息证件号码","18","1",null,"");
public static final BaseXmlBeanEnum mobile = new Socket_015001_1("mobile","基本信息手机","20","1",null,"");
public static final BaseXmlBeanEnum address = new Socket_015001_1("address","基本信息详细地址","100","1",null,"");
public static final BaseXmlBeanEnum postcode = new Socket_015001_1("postcode","基本信息邮政编码","6","0",null,"");
public static final BaseXmlBeanEnum sex = new Socket_015001_1("sex","基本信息性别","2","1",
new HashMap<String, String>(){{put("1","男");put("2","女");}},"");
}
- 构造socket xml报文
//根据对象 和 数据 拼装xml报文
public static String getSocketXml(String socketCode, List<BaseXmlBeanEnum> bodyList, Map<String, String> map, String macKey) throws Exception {
try{
map.put("交易码",socketCode);
Element transactionElement = DocumentHelper.createElement("transaction");
Document doc = DocumentHelper.createDocument(transactionElement);
doc.setXMLEncoding("GBK");
Element headElement = transactionElement.addElement("head");
Element bodyElement = transactionElement.addElement("body");
Element requestElement = bodyElement.addElement("request");
/*报文头*/
List<BaseXmlBeanEnum> headList = Socket_Head.getAllElement();
addXmlElement(headList, map, headElement);
/*报文体*/
addXmlElement(bodyList, map, requestElement);
/*报文签名处理*/
Element signatureElement = transactionElement.addElement("signature");
signatureElement.addText(getMac(bodyElement.asXML(),macKey));
String xml = doc.asXML();
return getSendXml(xml);
}catch (Exception e){
e.printStackTrace();
throw new Exception(e.getMessage());
}
}
private static void addXmlElement(List<BaseXmlBeanEnum> list, Map<String,String> map, Element parentElement) throws Exception {
try {
Element element ; String value;
//报文体
for (BaseXmlBeanEnum xmlBean : list) {
value = MapUtils.getString(map,xmlBean.getElementColumnName());
//转换options
if(MapUtils.isNotEmpty(xmlBean.getElementOptions())&& StringUtils.isNotBlank(value)){
value = MapUtils.getString(xmlBean.getElementOptions(),value,value);
}
//默认值
if(StringUtils.isBlank(value)&&StringUtils.isNotBlank(xmlBean.getElementDefaultValue())){
value = xmlBean.getElementDefaultValue();
}
//是否可为空
if(xmlBean.getElementNotNull().equals("1")&&StringUtils.isBlank(value)){
throw new Exception(xmlBean.getElementColumnName()+",不允许为空");
}
//长度截取
if(StringUtils.isNotBlank(value)){
int eLength = Integer.parseInt(xmlBean.getElementLength());
byte[] bytes = value.getBytes("GBK");
if(bytes.length>eLength){
if(eLength>value.length()){
eLength = value.length()/2;
}
value = value.substring(0,eLength);
}
}else{
value = "";
}
element = DocumentHelper.createElement(xmlBean.getElementName());
element.addText(value);
parentElement.add(element);
}
}catch (Exception e){
e.printStackTrace();
throw new Exception("封装请求报文出错:"+e.getMessage());
}
}
- 发送socet报文
public static synchronized String socketPost(String clientIp, String clientPort, String xml, String filePath) throws Exception {
String rs = "";
if(clientIp==null||"".equals(clientIp)||clientPort==null||"".equals(clientPort)){
throw new Exception("数据同步地址信息有误,请联系管理员!");
}
int clientPortInt = Integer.parseInt(clientPort);
// logger.info("clientIp:"+clientIp+" clientPort:"+clientPort);
Socket s = null;
OutputStream out = null;
InputStream in = null;
try {
s = new Socket(clientIp, clientPortInt);
s.setSendBufferSize(8192);
s.setReceiveBufferSize(8192);
s.setTcpNoDelay(true);
s.setSoTimeout(60*1000);
s.setKeepAlive(true);
out = s.getOutputStream();
in = s.getInputStream();
out.write(xml.getBytes("GBK"));
out.flush();
if (in.available()>0){
Thread.sleep(100);
}
//前8字节报文长度
byte[] byte8 = new byte[8];
in.read(byte8);
logger.info("===========================前8字节报文长度"+new String(byte8));
Integer int8 = Integer.parseInt(new String(byte8,"GBK"));
logger.info("==========================="+int8);
//报文正文
byte[] byteXml = new byte[int8];
//读取字节流不推荐下面这种一次性全部读取方式,受网络传输和大小的影响可能读取不全
in.read(byteXml);
rs = new String(byteXml, "GBK");
logger.info("===========================报文正文"+rs);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("socketPost发送请求异常:"+e.getMessage());
}finally{
try {
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
if(s!=null){
s.close();
}
} catch (IOException e) {
}
}
return rs;
}
/**
* 读取输入流
* @param in
* @return
*/
private static byte[] readStream(InputStream in,int length) throws Exception {
if(in==null){
return null;
}
byte[] b = null;
ByteArrayOutputStream outSteam = null;
try {
byte[] buffer = new byte[1024];
outSteam = new ByteArrayOutputStream();
int len = -1;
int readLen = 0;
while ((len = in.read(buffer)) != -1) {
if((readLen+len)>length){
len = length-readLen;
outSteam.write(buffer, 0, len);
break;
}else{
readLen += len;
outSteam.write(buffer, 0, len);
}
}
b = outSteam.toByteArray();
} catch (IOException e) {
throw new Exception("读取流信息异常:"+e.getMessage());
} finally{
try {
if(outSteam!=null){
outSteam.close();
outSteam = null;
}
if(in!=null){
in.close();
in = null;
}
} catch (IOException e) {
}
}
return b;
}
- 解析返回报文
//使用Document document = DocumentHelper.parseText(returnMassage);将返回的xml转换成Document对象 进行后续处理
String RetCode = document_015001.getRootElement().element("head").element("RetCode").getText();
String Desc = document_015001.getRootElement().element("head").element("Desc").getText();
- socket读取文件
//30位文件名
byte[] byte30 = new byte[30];
in.read(byte30);
String fileName = new String(byte30, "GBK").trim();
if(StringUtils.isBlank(fileName)){
fileName = UUID.randomUUID().toString()+".jpg";
}
logger.info("==========================="+fileName);
//前8字节文件长度
byte8 = new byte[8];
in.read(byte8);
int8 = Integer.parseInt(new String(byte8,"GBK"));
logger.info("==========================="+int8);
//文件
byte[] byteFile = readStream(in,int8);
//本地文件
File fileDir = new File(filePath);
if(!fileDir.exists()||!fileDir.isDirectory()) {
fileDir.mkdirs();
}
File file = new File(filePath + File.separatorChar + fileName);
FileOutputStream fos = new FileOutputStream(file);
fos.write(byteFile);
fos.flush();
fos.close();
我这里只列举我业务场景的socket处理过程,当然也可以简化或者配置化,比如:报文模版(报文头、报文体)通过数据库维护,socket发送方式可以使用多线程或者其他框架,如果返回报文通用简洁可以通过通用方法解析 等等。。。