项目下载地址: https://download.csdn.net/download/chouyan1884/10692331
1. 项目目录
目录描述:
talent.client:通讯客户端
talent.server : 通讯服务端
talent.entity : domino对象
talent.entity.fixed : domino对象与定长报文转换对象
talent.entity.xml : domino对象与XML转换对象
talent.util : domino对象与 XML \ 定长报文转换工具类
2. XML 与 domino 对象转换
1、 相关依赖
XML 与 domino 对象转换使用 JAXB,项目如果使用的JDK是1.8以下,需引入java 1.8的 rt.jar ;项目使用的JDK为1.8以上,可以直接使用 JAXB API。
2、 domino 代码编写
package talent.entity.xml.req;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "BODY")
@XmlAccessorType(XmlAccessType.FIELD)
public class ReqBody implements Serializable{
private static final long serialVersionUID = 1L;
}
XML根目录对象 @XmlRootElement(name = “BODY”) ,BODY为根目录
package talent.entity.xml.req.impl;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import talent.entity.xml.req.ReqBody;
import talent.entity.xml.req.impl.ext.Req100004DetailsExt;
import talent.entity.xml.req.impl.ext.Req100004SumExt;
@XmlRootElement(name = "BODY")
@XmlAccessorType(XmlAccessType.FIELD)
public class Req100004Impl extends ReqBody {
/**
*/
private static final long serialVersionUID = 1L;
@XmlElement(name = "TRANS_SUM")
private Req100004SumExt sumExt;
@XmlElementWrapper(name = "TRANS_DETAILS")
@XmlElement(name = "TRANS_DETAIL")
private List<Req100004DetailsExt> detailsExt;
.........
get set 方法
.........
}
package talent.entity.xml.req.impl.ext;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@XmlAccessorType(XmlAccessType.FIELD)
public class Req100004SumExt implements Serializable{
private static final long serialVersionUID = 1L;
/** 业务代码 */
@XmlElement
private String BUSINESS_CODE;
/** 提交时间 */
@XmlElement
private String SUBMIT_TIME;
/** 总记录数 */
@XmlElement
private String TOTAL_ITEM;
/** 总金额 */
@XmlElement
private String TOTAL_SUM;
.........
get set 方法
.........
}
package talent.entity.xml.req.impl.ext;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@XmlAccessorType(XmlAccessType.FIELD)
public class Req100004DetailsExt implements Serializable{
private static final long serialVersionUID = 1L;
/**
* 账号
*/
@XmlElement
private String ACCOUNT_NO;
/**
* 账号名
*/
@XmlElement
private String ACCOUNT_NAME;
.........
get set 方法
.........
}
XML节点对象
3、domino 对象转换为 XML
public static String beanToXML(Object obj, String encoding, boolean noheader) throws JAXBException {
String result = null;
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);// xml格式
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, noheader); // 去掉生成xml的默认报文头
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
marshaller.setListener(new Marshaller.Listener() {
@Override
public void beforeMarshal(Object source) {
super.beforeMarshal(source);
Field[] fields = source.getClass().getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
try {
if (f.getType() == String.class && f.get(source) == null) {
f.set(source, "");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
});
StringWriter writer = new StringWriter();
marshaller.marshal(obj, writer);
result = writer.toString();
return result;
}
转换方法
public static void main(String[] args) throws JAXBException, DocumentException {
//创建body对象
Req100004Impl body = new Req100004Impl();
Req100004SumExt req100004SumExt = new Req100004SumExt();
body.setSumExt(req100004SumExt);
List<Req100004DetailsExt> detailsExt = new ArrayList<Req100004DetailsExt>();
Req100004DetailsExt req100004DetailsExt = new Req100004DetailsExt();
detailsExt.add(req100004DetailsExt);
body.setDetailsExt(detailsExt);
//对象转xml
String bodyxml = beanToXML(body,"gbk",true);
System.out.println(bodyxml );
}
转换
3. 定长报文 与 domino 对象转换
1、domino 代码编写
package talent.entity.fixed;
import java.lang.annotation.Annotation;
import talent.entity.fixed.anno.FixedLengthDesc;
import talent.entity.fixed.anno.FixedLengthFieldDesc;
/**
* 定长报文与实体间转换需继承该类
* 通过getThisClass获取定长描述信息
*/
public abstract class FixedLengthBody {
protected FixedLengthFieldDesc[] fixedLengthFields;
public abstract Class<? extends FixedLengthBody> getThisClass();
public FixedLengthBody() {
this.fixedLengthFields = init(getThisClass());
}
public FixedLengthFieldDesc[] init(Class<? extends FixedLengthBody> cls){
FixedLengthDesc fld = null;
Annotation[] ans = cls.getAnnotations();
for (Annotation an : ans) {
if(an instanceof FixedLengthDesc){
fld = (FixedLengthDesc) an;
break;
}
}
return fld.value();
}
public FixedLengthFieldDesc[] getFixedLengthFields() {
return fixedLengthFields;
}
public void setFixedLengthFields(FixedLengthFieldDesc[] fixedLengthFields) {
this.fixedLengthFields = fixedLengthFields;
}
}
父类,获取子类定长信息内容
package talent.entity.fixed.req;
import talent.entity.fixed.FixedLengthBody;
import talent.entity.fixed.anno.FixedLengthDesc;
import talent.entity.fixed.anno.FixedLengthFieldDesc;
import talent.entity.fixed.enums.FixedLengthEnum;
@FixedLengthDesc({
@FixedLengthFieldDesc(name = "tranType", length = 6, type = FixedLengthEnum.STRING),
@FixedLengthFieldDesc(name = "sendType", length = 4, type = FixedLengthEnum.STRING),
@FixedLengthFieldDesc(name = "tranIdx", length = 16, type = FixedLengthEnum.STRING),
.... 其他字段
})
public class FixedReq100301 extends FixedLengthBody {
private String tranType;
private String sendType;
private String tranIdx;
.... 其他字段
@Override
public Class<? extends FixedLengthBody> getThisClass() {
return FixedReq100301.class;
}
.........
get set 方法
.........
domino对象: 注解用来配置转换定长报文
2、定长报文注解配置
package talent.entity.fixed.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FixedLengthDesc {
public FixedLengthFieldDesc[] value();
}
package talent.entity.fixed.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import talent.entity.fixed.enums.FixedLengthEnum;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FixedLengthFieldDesc {
public String name();
public int length();
public FixedLengthEnum type();
}
3、转换工具类
package talent.util;
import java.lang.reflect.Method;
import talent.entity.fixed.FixedLengthBody;
import talent.entity.fixed.anno.FixedLengthFieldDesc;
import talent.entity.fixed.enums.FixedLengthEnum;
import talent.entity.fixed.req.FixedReq100301;
/**
* 定长报文 与 javaBean 相互转换
* @author admin
*
*/
public class FixedPacketUtil {
private final static char rightCharStr = ' ';
private final static char leftCharStr = '0';
/**
* 将pojo按照格式生成固定格式报文
* @param pojo 转换对象
* @param charsetName 编码格式
*/
public static String javaBeanToFixedLengthPacket(FixedLengthBody pojo, String charsetName) throws Exception {
String fieldName;
int fieldLenght;
FixedLengthEnum parameterClass;
StringBuffer requestStr = new StringBuffer();
FixedLengthFieldDesc[] fixedLengthFieldDescs = pojo.getFixedLengthFields();
// 循环类中配置的所有字段
int fixedLengthFieldDescsLength = fixedLengthFieldDescs.length;
for (int i = 0; i < fixedLengthFieldDescsLength; i++) {
FixedLengthFieldDesc fixedLengthFieldDesc = fixedLengthFieldDescs[i];
fieldName = fixedLengthFieldDesc.name();
fieldLenght = fixedLengthFieldDesc.length();
parameterClass = fixedLengthFieldDesc.type();
// 获取bean对象的get方法,拿到数据
Class<?> c = pojo.getClass();
Method m = c.getMethod("get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1));
String fieldValue = m.invoke(pojo) == null ? "" : m.invoke(pojo).toString();
// 对数据进行报文的拼接
if (parameterClass.equals(FixedLengthEnum.STRING))
requestStr.append(formatFieldByRightChar(fieldValue, fieldLenght, rightCharStr, charsetName));
else {
if (parameterClass.equals(FixedLengthEnum.FLOAT)) {
fieldValue = formatFieldByfloat(fieldValue, charsetName);
}
requestStr.append(formatFieldByLeftChar(fieldValue, fieldLenght, leftCharStr, charsetName));
}
}
return requestStr.toString();
}
/**
* FLOAT 浮点处理
*/
public static String formatFieldByfloat(String field, String charsetName) throws Exception {
int s = field.indexOf(".");
int length = field.length();
if (s == -1) {
return formatFieldByRightChar(field, length + 2, leftCharStr, charsetName);
} else {
String num = field.substring(0, s);
String point = field.substring(s + 1);
return num + formatFieldByRightChar(point, 2, leftCharStr, charsetName);
}
}
/**
* str右补charStr参数指定的字符,格式化为指定byte长度为size的字符串
* @param str 原字符串大小
* @param size byte长度
* @param charStr 补充字符
* @param charsetName 编码格式
*/
public static String formatFieldByRightChar(String str, int size, char charStr, String charsetName)
throws Exception {
byte[] bufferByte = new byte[size];
for (int i = 0; i < bufferByte.length; i++) {
bufferByte[i] = (byte) charStr;
}
byte[] strByte = str.getBytes(charsetName); // 得到字符的字节数
int strLength = strByte.length;
System.arraycopy(strByte, 0, bufferByte, 0, size > strLength ? strLength : size);
return new String(bufferByte);
}
public static String formatFieldByRightChar(String str, int size, String charsetName) throws Exception {
return formatFieldByRightChar(str, size, rightCharStr, charsetName);
}
/**
* str左补charStr参数指定的字符,格式化为指定byte长度为size的字符串
* @param str 原字符串大小
* @param size byte长度
* @param charStr 补充字符
*/
public static String formatFieldByLeftChar(String str, int size, char charStr, String charsetName)
throws Exception {
byte[] bufferByte = new byte[size];
for (int i = 0; i < bufferByte.length; i++) {
bufferByte[i] = (byte) charStr;
}
byte[] strByte = str.getBytes(charsetName);
int strLength = strByte.length;
System.arraycopy(strByte, 0, bufferByte, (size - strLength) > 0 ? (size - strLength) : 0,
(size - strLength) > 0 ? strLength : size);
return new String(bufferByte);
}
public static String formatFieldByLeftChar(String str, int size, String charsetName) throws Exception {
return formatFieldByLeftChar(str, size, leftCharStr, charsetName);
}
/**
* 将strByte字符串按照requestPacketFormatArray三维数组定义的格式生pojo
*/
public static void fixedLengthPacketToJavaBean(FixedLengthBody pojo, String str, String charsetName)
throws Exception {
// 初始化数据
int index = 0;
byte[] strByte = str.getBytes(charsetName);
String fieldName;
int fieldLenght;
FixedLengthEnum parameterClass;
// 循环类中配置的所有字段
FixedLengthFieldDesc[] fixedLengthFieldDescs = pojo.getFixedLengthFields();
int fixedLengthFieldDescsLength = fixedLengthFieldDescs.length;
for (int i = 0; i < fixedLengthFieldDescsLength; i++) {
FixedLengthFieldDesc fixedLengthFieldDesc = fixedLengthFieldDescs[i];
fieldName = fixedLengthFieldDesc.name();
fieldLenght = fixedLengthFieldDesc.length();
parameterClass = fixedLengthFieldDesc.type();
// 截取报文里每个字段配置的长度(按index下标到fieldLenght截取)
int tempLenght = fieldLenght;
byte[] byteTemp = new byte[tempLenght];
for (int k = 0; k < tempLenght; k++) {
byteTemp[k] = strByte[index + k];
}
index = index + tempLenght;
// 给pojo对象赋值
Class<?> c = pojo.getClass();
if (parameterClass.equals(FixedLengthEnum.STRING)) {
Method m = c.getMethod("set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1),
String.class);
m.invoke(pojo, new String(byteTemp).trim());
} else if (parameterClass.equals(FixedLengthEnum.INT)) {
Method m = c.getMethod("set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1),
int.class);
m.invoke(pojo, Integer.valueOf(new String(byteTemp)));
} else if (parameterClass.equals(FixedLengthEnum.LONG)) {
Method m = c.getMethod("set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1),
long.class);
m.invoke(pojo, Long.valueOf(new String(byteTemp)));
} else if (parameterClass.equals(FixedLengthEnum.FLOAT)) {
Method m = c.getMethod("set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1),
float.class);
m.invoke(pojo, Float.valueOf(new String(byteTemp))/100 );
}
}
}
public static void main(String args[]) {
FixedReq100301 fixed = new FixedReq100301();
fixed.setTranType("100301");
fixed.setSendType("1202");
fixed.setTranIdx("0000000000000003");
fixed.setEntrustDate("20080601");
fixed.setLiquidationDate("00000000");
fixed.setUserNum("1234567890");
fixed.setSendCode("231255297");
fixed.setSendNodeCode("");
fixed.setSendBankCode("");
fixed.setSendBankAcct("");
fixed.setReceiveCode("201581000018");
fixed.setReceiveNodeCode("");
fixed.setDraweeAcct("44001400102050031709");
fixed.setDraweeName("关羽");
fixed.setBizType("00700");
fixed.setProtocolId("0158102312552970070020144001400102050031709");
fixed.setCcyCode("CNY");
fixed.setAmt(1F);
fixed.setFee(0F);
fixed.setPostscript("附言");
fixed.setBizTranId("0000000000000000");
fixed.setRespCode("");
fixed.setPayLdentifi(0);
fixed.setFixedLength("00000000");
try {
System.out.println(javaBeanToFixedLengthPacket(fixed, "gb2312"));
} catch (Exception e) {
e.printStackTrace();
}
//
// /** 与行里进行通讯 */
//
// // 获取银行返回数据
// String respFixed = "1003011202000000000000000320080601000000001234567890 231255297 201581000018 44001400102050031709 关羽 007000158102312552970070020144001400102050031709 CNY000000000000100000000000000000附言 0000000000000000 00000000037613A9A055A55821E8C5771619A5B82876B02A47ADF57CAE3027DDA3A08268A";
// FixedResp100301 fixedResp = new FixedResp100301();
// try {
// fixedLengthPacketToJavaBean(fixedResp, respFixed, "gb2312");
// System.out.println(fixedResp);
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}