在项目中,我们经常会使用到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给客户端调用即可;
时间: 2024-10-19 05:14:42