• http接口服务方结合策略模式实现总结


      在项目中,我们经常会使用到http+xml的接口,而且不仅仅的是一个,可能会有多个http的接口需要实时的交互.但是http接口的接收消息的公共部分是一样的,只有每个接口的报文解析和返回报文是不同的,此时考虑到把变化和不变化的隔离出来,采取用策略模式,把公共的部分代码抽取隔离出来,每个http接口的不同的处理逻辑单独自己处理,这样也方便了后期的修改和扩展,可以很方便的修改单独的接口处理逻辑和添加新的http接口到项目中使用,而不用修改以前的设计.下面就http+xml接口的接收采用简单的策略模式实现:

    项目的基础:SSH架构

    首先实现BaseReceiveHttpIntfAction 基类,实时的接收报文动作和返回结果报文动作:具体的解析逻辑和获取返回报文逻辑抽取隔离出去:

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉 http 接收接口基类实现  父类实现为prototype  不是单例的
     * 
     * 基于策略模式  后面增加子类接收实现的方法 请参照:CrmReceiveHttpIntfAction的实现
     * 
     * @author lilin
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    @Controller
    @Scope(value = "prototype")
    public abstract class BaseReceiveHttpIntfAction extends BasicAction {
        /**
         */
        private static final long serialVersionUID = -4667071743433536439L;
    
        private IHttpMessageHandle httpMessageHandle;
    
        /**
         * 
         * 功能描述: <br>
         * 〈功能详细描述〉用于 子类 注入父类属性
         * 
         * @param httpMessageHandle
         * @see [相关类/方法](可选)
         * @since [产品/模块版本](可选)
         */
        public void setHttpMessageHandle(IHttpMessageHandle httpMessageHandle) {
            this.httpMessageHandle = httpMessageHandle;
        }
    
        public String doBusiness() {
            InputStream inputStream = null;
            try {
                inputStream = request.getInputStream();
            } catch (IOException e1) {
                logger.error("IOException: ", e1);
            }
            logger.info("@@HttpClient 解析接收报文:");
            SAXReader sb = new SAXReader();
            String returnStr = null;
            try {
                Document document = sb.read(inputStream);
                logger.info(document.asXML());
                // 保存报文信息
                Map<String, Object> map = httpMessageHandle.handleMessage(document);
                // 拼接返回报文
                returnStr = httpMessageHandle.getResponseMsg(map, document);
                logger.info("@@ 报文解析成功!");
            } catch (DocumentException e) {
                logger.info("@@HttpClient 解析报文出错!", e);
            }
            logger.info("@@ 返回报文 : " + returnStr);
            writeResponse(returnStr, response);
            return null;
        }
    
        /**
         * 
         * 功能描述: <br>
         * 〈功能详细描述〉
         * 
         * @param respXML
         * @param response
         * @throws IOException
         * @see [相关类/方法](可选)
         * @since [产品/模块版本](可选)
         */
        private void writeResponse(String respXML, HttpServletResponse response) {
            OutputStream out = null;
            try {
                byte[] data = respXML.getBytes("UTF-8");
                out = response.getOutputStream();
                out.write(data);
            } catch (IOException e) {
                logger.error("Write response error: ", e);
            } finally {
                if (out != null) {
                    try {
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        logger.error("IOException: ", e);
                    }
                }
            }
        }
    
    }

    然后:规定好子类需要注入的公共接口IHttpMessageHandle, 接口定义需要解析报文的解析方法,以及获取放回报文的方法:

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉
     * 
     * @author lilin
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    public interface IHttpMessageHandle {
    
        /**
         * 
         * 功能描述: <br>
         * 〈功能详细描述〉处理接收到的报文信息
         * 
         * @param document
         * @return
         * @see [相关类/方法](可选)
         * @since [产品/模块版本](可选)
         */
        Map<String, Object> handleMessage(Document document);
    
        /**
         * 
         * 功能描述: <br>
         * 〈功能详细描述〉获取需要返回的报文信息
         * 
         * @param map
         * @param document
         * @return
         * @see [相关类/方法](可选)
         * @since [产品/模块版本](可选)
         */
    
        String getResponseMsg(Map<String, Object> map, Document document);
    
    }

    然后:实现实际的处理报文信息的类:CrmHttpMessageHandle 实时处理CRM系统发送的xml报文信息,实时组装需要返回的报文信息:

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉
     * 
     * @author lilin
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    @Service
    public class CrmHttpMessageHandle implements IHttpMessageHandle {
    
        private Logger logger = Logger.getLogger(CrmHttpMessageHandle.class);
    
        @Resource
        private LowPriceTaskService lowPriceTaskService;
    
        @Override
        public String getResponseMsg(Map<String, Object> map, Document document) {
            logger.info("CrmHttp Get ResponseMsg:");
    
            printLogByEntry(map);
    
            Document doc = DocumentHelper.createDocument();
            // MbfService 拼接
            Element mbfService = DocumentHelper.createElement("MbfService");
            doc.add(mbfService);
            Element output1 = DocumentHelper.createElement("output1");
            mbfService.add(output1);
    
            // MbfHeader 拼接
            Element mbfHeader = DocumentHelper.createElement("MbfHeader");
            output1.add(mbfHeader);
    
            PriceCommonService.addElement(mbfHeader, "ServiceCode", (String) map.get("ServiceCode"));
            PriceCommonService.addElement(mbfHeader, "Operation", (String) map.get("Operation"));
            PriceCommonService.addElement(mbfHeader, "AppCode", (String) map.get("AppCode"));
            PriceCommonService.addElement(mbfHeader, "UId", (String) map.get("UId"));
    
            // ServiceResponse 拼接
            Element serviceResponse = DocumentHelper.createElement("ServiceResponse");
            mbfHeader.add(serviceResponse);
    
            PriceCommonService.addElement(serviceResponse, "Status", null);
            PriceCommonService.addElement(serviceResponse, "Code", null);
            PriceCommonService.addElement(serviceResponse, "Desc", null);
    
            // MbfBody 拼接
            Element mbfBody = DocumentHelper.createElement("MbfBody");
            output1.add(mbfBody);
    
            PriceCommonService.addElement(mbfBody, "reFlag", (String) map.get("reFlag"));
            PriceCommonService.addElement(mbfBody, "errorMessage", (String) map.get("errorMessage"));
    
            logger.info("CrmHttp Final ResponseMsg:" + doc.asXML());
            return doc.asXML();
        }
    
        @Override
        public Map<String, Object> handleMessage(Document document) {
            logger.info("CrmHttp Start HandleMessage:");
    
            Map<String, Object> res = new HashMap<String, Object>();
            LowPriceTask task = new LowPriceTask();
    
            Element root = document.getRootElement();
            Element outElement = root.element("input1");
    
            Element mbfHeader = outElement.element("MbfHeader");
    
            String serviceCode = mbfHeader.elementTextTrim("ServiceCode");
            res.put("ServiceCode", serviceCode);
            logger.info("## ServiceCode : " + serviceCode);
            String operation = mbfHeader.elementTextTrim("Operation");
            res.put("Operation", operation);
            logger.info("## operation : " + operation);
            String appCode = mbfHeader.elementTextTrim("AppCode");
            res.put("AppCode", appCode);
            logger.info("##  appCode : " + appCode);
            String uId = mbfHeader.elementTextTrim("UId");
            res.put("UId", uId);
            logger.info("##  uId : " + uId);
    
            // 设置返回值
            if (!StringUtils.isEmpty(serviceCode) && !StringUtils.isEmpty(operation)) {
                task.setMsg(document.asXML());
                task.setScanNum(0);
                task.setScanResult("F");
                task.setStoreTime(DateUtils.getDate2());
    
                lowPriceTaskService.saveTask(task);
    
                res.put("reFlag", "S");
                res.put("errorMessage", "S");
                logger.info("@@HttpClient 保存报文信息成功!");
            } else {
                res.put("reFlag", "E");
                res.put("errorMessage", "报文头有问题");
            }
    
            return res;
        }

    最后:实现实际的接收报文信息的子类action:继承基类,实时注入父类的接口实现,最终提供给客户端的url:http://lilin.com/lilin-web/crmReceiveHttpIntfAction.do

    /**
     * 〈一句话功能简述〉<br>
     * 〈功能详细描述〉
     * 
     * @author lilin
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    @Controller
    public class CrmReceiveHttpIntfAction extends BaseReceiveHttpIntfAction {
    
        /**
         */
        private static final long serialVersionUID = -104341558961432099L;
    
        @Resource
        private IHttpMessageHandle crmHttpMessageHandle;
    
        @PostConstruct
        public void injectHttpMessageHandle() {
            super.setHttpMessageHandle(crmHttpMessageHandle);
        }
    }

    这样,简单的http+xml报文+策略模式的实现,就完成了.后期需要扩展新的接口接口使用,只要仅仅实现自己的

    1,接收子类<参考CrmReceiveHttpIntfAction >

    2,消息处理类:<参考CrmHttpMessageHandle>

    3,提供最终的服务方的url给客户端调用即可;

  • 相关阅读:
    【Oracle】将表名与字段名连接成一行数据展示,字段名使用顿号的分隔
    【Accountancy】资产
    【FinacialKnowledge】财务报表及名词解释
    模块独立性原理
    C# this.Invoke()的作用与用法
    浅谈C#委托和事件(转载)
    C#三种定时器的实现
    一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    c++ comment
    C#使用StreamWriter类写入文件文件
  • 原文地址:https://www.cnblogs.com/lilin0719/p/5247452.html
Copyright © 2020-2023  润新知