youyoumo 2017-03-13
架构设计中领域模型设计思路:
最终发送的是报文头+业务头+具体业务
抽象出的基类(大多数类共有的字段属性):报文头部分
1,实体分层嵌套
大层实体类也应设计有tostring双向方法
还有用反射机制做的操作自身属性(根据报文操作对应实体属性)
继承的方式拓展,处理方法也需公用的话,在子类父类的抽象方法,父类用反射操作子,虽然写在子类方便不必反射,但是不可公用
在联调接口的时候:
1,对方传来的字符串有固定的json等模式用工具转化为实体
2,不用类转化工具可以直接用反射的机制操作(这种反射机制在根据传过来的字符串调用不同的服务类的方法很有用)
3,按报文的固定位置依次遍历给相应的对象属性赋值
抽象方法
2,小的实体类
属性+tostring()双向方法
具体业务类:报文体部分
1,继承抽象类
2,通过复写抽象方法进一步个性化处理
3,自己的业务属性
小的实体类需要再细分的时候,中间的实体不必集成抽象方法(此时其仍为抽象类),最终类中覆盖即可
在应有的时候传入父类即可(类似于模式(在服务层之间套用服务应用))(在服务层用实体实体传值用(接口中的传值类型))
实体多态的使用:
public interface PacketProcesser<P extends PaPacket,T extends Answer> {
public T execute(P packet);
}
@Service
public class XxProcesser implements PacketProcesser<BP1303,RspBP1303> {
@Override
public RspBP1303 execute(BP1303 packet) {
}
}
服务多态的使用:
参考设计模式
反射机制也是一种转化返回信息为实体的方式,在需要根据返回字段调用对应方法时更优势
======================================================================================
根据报文位置依次给对象属性赋值示例:
this是调用此方法当前的对象,反射是用的字节码对点,this.getClass()
PacketHeader:业务头也类似BusinessHeader
Assert.isTrue(src.length >= PacketHeader.HEADERLEN, "报文头长度必须大于" + PacketHeader.HEADERLEN);
Assert.notNull(this.packetHeader);
将长的报文一段一段解析出(设值到实体属性)
int srcPos = 0;
// 1 报文类别
char[] dest = new char[4];
System.arraycopy(src, srcPos, dest, 0, dest.length);
this.setPacketType(new String(dest).trim());
srcPos += 4;
一段一段的拼接出长的报文(从实体属性拼出)
int dstBegin = 0;
char[] dst = new char[222];
for (int i = 0; i < dst.length; i++) {
dst[i] = ' ';
}
// 1 报文类别
packetType.getChars(0, 4, dst, dstBegin);
最终发送的是报文头+业务头+具体业务
这两个相当于PacketHeader的tostring的正反(在PacketHeader中)
使用反射机制根据报文调用相应方法示例:
ProcesserInfo info = processer.get(tranFunc);
Assert.notNull(info);
Object processer = this.beanFactory.getBean(info.getBeanName());
Class<PacketProcesser<PaPacket, Answer>> cls = (Class<PacketProcesser<PaPacket, Answer>>) processer.getClass();
PacketProcesser<PaPacket, Answer> proc = cls.cast(processer);
Type type = info.getBeanClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) type;
Type[] args = pt.getActualTypeArguments();
Class<PaPacket> clazz = (Class<PaPacket>) Class.forName(args[0].getTypeName());
PaPacket packet = clazz.newInstance();
packet.analyze(packetStr);
Answer answer = proc.execute(packet);
//验证方法返回的结果是否正确
ValidatorResult<Answer> result = packetValidator.validator(answer);
==============================================================================
实体层级设置示例:
往往涉及父类方法操作子类
1,父类提供抽象方法让子类传递需要操作的属性
2,父类用反射机制操作(子类操作父类用super即可 )
继承的方式拓展,处理方法也需公用的话,在子类父类的抽象方法,父类用反射操作子,虽然写在子类方便不必反射,但是不可公用
PaPacket:
PacketHeader//有自己的string方法,转化为实体的方法
BusinessHeader//有自己的string方法
protected abstract String[] order();
marshal//总的string方法
analyze//总转化为实体的方法
里面的抽象方法order()是业务实体中需要加入转化的字段
marshal将所有有关实体转化为字符串:
getstring转化业务实体到string,getPacketHeader转化报文头实体到string,
public String getString() {
StringBuilder sb = new StringBuilder();
try {
for (String fName : this.order()) {
Object obj = getValue(fName);
if (obj == null) {
sb.append("");
}
if (obj instanceof String) {
sb.append((String) obj);
}
if (obj instanceof Integer) {
sb.append(((Integer) obj).intValue());
}
if (obj instanceof Long) {
sb.append(((Long) obj).intValue());
}
if (obj instanceof Double) {
sb.append(df.format((Double) obj));
}
sb.append("&");
}
} catch (NoSuchFieldException | SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
private Object getValue(String fName) throws NoSuchFieldException, SecurityException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
fName = fName.substring(0, 1).toUpperCase() + fName.substring(1);
Method method = this.getClass().getMethod("get" + fName);
Assert.notNull(method);
return method.invoke(this);
}
也就是说父类需要操作子类用反射的原理做,不同类之间的(不是父子关系用获取实例(new)即可)又是根据传入的值动态变化调用(包括方法和属性)的用反射
analyze将整个报文转化为对象
业务类继承PaPacket
public abstract class InMoney extends PaPacket {
}
public class InMoneyBP1310 extends InMoney{
protected String[] order() {
String[] args={"supAcctId","custAcctId","tranAmount","tnAcctId","inAcctIdName","ccyCode","acctDate","reserve"};
return args;
}
}
覆盖order()方法加入需要转化的字段
小的实体类需要再细分的时候,中间的实体不必集成抽象方法(此时其仍为抽象类),最终类中覆盖即可
层级类的使用示例:
传入具体的,使用的时候用泛型,父类作为接收值,对于有用接口用到这些类,需要公用时也是用泛型或父类
结合抽象实例,方法抽象思维:
公用方法的抽象类别,
1,处理逻辑一样(接收参数的用父类或泛型)
2,同类功能方法(接口参数的用父类或泛型)
3,模式
1,常规方法:
RspBP1020 rsp = (RspBP1020) paTemplate.execute(bp1020, RspBP1020.class);
public class PaTemplate {
@Autowired
private RestTemplate restTemplate;
@Autowired
private PacketValidator packetValidator;
@Value("${pa.url}")
private String paUrl ;
public <T> T execute(PaPacket packet,Class<T> responseType){
//验证业务报问题是否符合规范
ValidatorResult<PaPacket> result = packetValidator.validator(packet);
Assert.isTrue(result.isValid(),result.getMessage());
HttpHeaders tempHeaders = new HttpHeaders();
tempHeaders.add("Content-type", "application/json");
HttpEntity<PaPacket> httpEntity = new HttpEntity<PaPacket>(packet,tempHeaders);
T response = restTemplate.postForObject(paUrl, httpEntity, responseType);
return response;
}
}
2,通用接口:
public interface PacketProcesser<P extends PaPacket,T extends Answer> {
public T execute(P packet);
}
@Service
public class XxProcesser implements PacketProcesser<BP1303,RspBP1303> {
@Override
public RspBP1303 execute(BP1303 packet) {
}
}
3,使用模式