最近开发总结

背景

开发完短信平台,开始做一个汇聚平台。现在开始大量使用设计模式来做了,其实也就是那些比较常用的。设计模式,用的合适的话,对扩展性和维护,带来了很大的便利。
短信平台使用模板方法和观察者模式,现在汇聚平台简单使用一个工厂模式,之前做了一个生产者消费者,但是发现queue有点问题,还是舍弃了。
既然是总结,还是多记录些代码。

接口

汇聚平台做数据服务,最主要的是数据接口。这里,做的时候是模仿支付宝的支付接口。
接口处,采用工厂模式,方便扩展,不同的服务根据服务名称进行区分。
主入口的类,只是对数据进行一些校验,并不是做业务逻辑。

 //参数验证通过,验证接口服务
                if (!valiService(service)){
                        return getRespCode(ErrorCode.SERVICE_ERR,key);
                }
                //接口服务通过,验证接入商
                Access access = getAccess(commuCode);
                if (access == null){
                        return getRespCode(ErrorCode.VALIDATE_ERR,key);
                }
                key = access.getAccessKey();
                //验证签名
                if (!valiSign(data,key)){
                        return getRespCode(ErrorCode.SIGN_ERR,key);
                }
                //处理业务逻辑
                String result ;
                try {
                        result = doBusi(service,data);
                } catch (ParamException e) {
                        return getRespCode(ErrorCode.PARAM_ERR,key);
                } catch (SystemException e1){
                        return getRespCode(ErrorCode.SYS_ERR,key);
                }
                logger.info("Cost Time:" + (System.currentTimeMillis() - a));
                //流量数据不需要返回具体的业务数据,对外服务需要返回特定的数据
                return "".equals(result) ? getRespCode(ErrorCode.SUCCESS,key) : result;

这里定义了两个自定义的异常,分别由处理业务的时候抛出来。这里的业务采用工厂方式,根据不同的服务来产生。

        private String doBusi(String service,String data) throws ParamException, SystemException {
                //处理不同业务
                setServiceMap(serviceMap);
                Business business = ServiceFactory.produce(service);
                return business.doProcess(serviceMap,data);
        }

所有业务实现业务接口就可以:

public interface Business {
        //返回处理数据
        String doProcess(Map<String,BaseService> services,String data) throws ParamException, SystemException;
}

然后配一个简单的工厂类:

public class ServiceFactory {
        private static Logger logger = Logger.getLogger(ServiceFactory.class);

        public static Business produce(String type){
                if (Services.FLOW_DATA.key.equals(type)){
                        return new FlowDataProcess();
                }
                else if (Services.PARK_AROUND.key.equals(type)){
                        return new ParkAroundProcess();
                }
                else if (Services.PARK_ALL.key.equals(type)){
                        return new ParkAllProcess();
                }
                else {
                        logger.error("Error Type When DoProcess in Factory");
                        return null;
                }
        }
}

这样就将业务的耦合性降低了很多。

数据格式

对外服务的接口,数据格式都有一定的约束。所以,就写了一个工具包,将字符串数据转换为相应的对象,或者将对象转为字符串。不只是为自己使用,也为客户端提供。使用泛型写一个,比较通用。
这个时候,规定两个接口Encoder和Decoder 。
其中,有涉及到多个数据,使用list来存放,具体放的类型,也要有上界规定。这样容易统一list中的数据。不再详细描述。

1,数据进行格式化,将对象转换为字符串

public class DataEncoder<T, V> implements Encoder<T, V> {

        private StringBuilder dataEncode(T o, String pattern) throws IllegalAccessException {
                StringBuilder sb = new StringBuilder();
                Field[] fields = o.getClass().getDeclaredFields();
                for (Field field : fields) {
                        field.setAccessible(true);
                                if (field.get(o) == null) {
                                        sb.append("");
                                } else if ("java.util.Date".equals(field.getType().getName())) {
                                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                                        sb.append(sdf.format(field.get(o)));
                                } else {
                                        sb.append(field.get(o));
                                }
                        sb.append(pattern);
                }
                //sb.deleteCharAt(sb.lastIndexOf(pattern));
                return sb;
        }

        public String requestEncode(V o,String k) throws IllegalAccessException {
                StringBuilder sb = new StringBuilder();
                Field[] fields = o.getClass().getDeclaredFields();
                for (Field field : fields) {
                                field.setAccessible(true);
                                if (field.get(o) == null) {
                                        sb.append("");
                                } else if ("java.util.List".equals(field.getType().getName())) {
                                        StringBuilder sb2 = new StringBuilder();
                                        List<T> obj = (List) field.get(o);
                                        for (T o1 : obj) {
                                                StringBuilder stringBuilder = dataEncode(o1,"|");
                                                stringBuilder.deleteCharAt(stringBuilder.lastIndexOf("|"));
                                                //sb2.append(dataEncode(o1, "|").toString());
                                                sb2.append(stringBuilder.toString());
                                                sb2.append(";");
                                        }
                                        sb2.deleteCharAt(sb2.lastIndexOf(";"));
                                        sb.append(sb2.toString());
                                } else {
                                        sb.append(field.get(o));
                                }
                        sb.append("&");
                }
                System.out.println("Pre data:"+sb.toString());
                if (!"".equals(k) &&  k != null){
                        signSb(sb,k);
                }
                //sb.deleteCharAt(sb.lastIndexOf("&"));
                return sb.toString();
        }

        public String responseEncode(T t,String k) throws IllegalAccessException {
                StringBuilder sb = dataEncode(t, "&");
                if (!"".equals(k) &&  k != null){
                        signSb(sb,k);
                }
                return sb.toString();
        }

        //为字符串增加签名
        private void signSb(StringBuilder data,String k){
                String s = data.toString();
                String sign = MD5.sign(s, k, "utf-8");
                data.append(sign);
        }

        //参数为string的签名
        public String sign(String s,String k){
                return MD5.sign(s+"&key="+k,k,"utf-8");
        }
}

2,数据转换,将字符串数据解析,转换为对象

public class DataDecoder implements Decoder {
        public MsgDecoder deReq(String data) throws NoSuchFieldException, IllegalAccessException {
                MsgDecoder decoder = new MsgDecoder();
                String[] outer = data.split("&");
                decoder.setServiceName(outer[0]);
                decoder.setCommuCode(outer[1]);

                List<MsgData> inner = new ArrayList<MsgData>();
                String datas = outer[2];
                String[] inners = datas.split(";");
                for (String s : inners) {
                        MsgData msgData = new MsgData();
                        String[] sa = s.split("\\|");
                        for (int i = 0; i < sa.length; i++) {
                                Field field = msgData.getClass().getDeclaredField("arg" + i);
                                field.setAccessible(true);
                                field.set(msgData, sa[i]);
                        }
                        inner.add(msgData);
                }
                decoder.setDatas(inner);
                decoder.setSign(outer[3]);
                return decoder;
        }

        public RespDecoder deResp(String data) {
                RespDecoder decoder = new RespDecoder();
                String[] strings = data.split("&");
                decoder.setCode(Integer.parseInt(strings[0]));
                decoder.setDesc(strings[1]);
                //异常数据中,第三个字段会为空
                if (strings.length >2){
                        decoder.setSign(strings[2]);
                }
                return decoder;
        }
}

字符串转对象的时候,需要自建几个对象,去接收这些数据。不再详述。

posted @ 2015-06-29 11:47  薛定谔的猫_  阅读(2090)  评论(0编辑  收藏  举报