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給客戶端調用即可;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM