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给客户端调用即可;
http接口服务方结合策略模式实现总结的更多相关文章
- 小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了
这里涉及到一个关键词:策略模式,那么到底什么是策略模式呢?本文就来好好给大家讲讲策略模式,大家可以带着如下几个问题来阅读本文: 1. 如何通过策略模式优化业务逻辑代码(可以根据自己从事的工作思考) ...
- C++设计模式-Strategy策略模式
Strategy策略模式作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: Strategy模式将逻辑(算法)封装到一个类(Cont ...
- Java设计模式6:策略模式
策略模式 策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 策略模式的结构 策略模式是对算法的包 ...
- 策略模式c++【转】
作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: Strategy模式将逻辑(算法)封装到一个类(Context)里面,通过组合的 ...
- 【设计模式】策略模式 (Strategy Pattern)
策略模式是一种很简单的基础模式,用于封装一系列算法,使客户端的访问独立于算法的实现.我们可以”井中取水”来形象的描述策略模式.“取水”是一个动作,完成这个动作的方式有很多中,可以直接用手提.可以用水车 ...
- 设计模式-策略模式Strategy以及消灭if else
概述 如果在开发过程中,出现大量的if else或者switch case 语句,如果这些语句块中的代码并不是包含业务逻辑,只是单纯的分流方法,那么,每一个语句块中都是一个算法或者叫策略. 背景 比如 ...
- 设计模式之策略模式的Python实现
1. 策略模式解决的是什么问题 策略模式解决的应用场景是这样的: 在业务场景中,需要用到多个算法,并且每个算法的参数是需要调整的.那么当不同的行为堆砌到同一个类中时,我们很难避免使用条件语句来选择合适 ...
- HTTP+XML接口客户端 结合策略模式实现总结
在项目中,我们经常会使用到http+xml的接口,而且不仅仅的是一个,可能会有多个http的接口需要实时的交互.但是http接口的发送消息的公共部分是一样的,只有每个接口的报文解析和返回报文是不同的, ...
- C#委托和事件?策略模式?接口回调?还不清楚的赶紧来看我扯
早前学习委托的时候,写过一点东西,今天带着新的思考和认知,再记点东西.这篇文章扯到设计模式中的策略模式,观察者模式,还有.NET的特性之一--委托.真的,请相信我,我只是在扯淡...... 场景练习 ...
随机推荐
- U盘启动盘安装Mac OS
1.下载macOS High Sierra正式版 http://www.pc6.com/mac/gj_715_1.htm http://www.pc6.com/mac/518996.html 下载ma ...
- 洛谷P1466 集合 Subset Sums_01背包水题
不多解释,适当刷刷水… Code: #include<cstdio> #include<algorithm> using namespace std; const int ma ...
- Centos 7.2 安装和卸载 MySQL 5.7
一.背景 闲暇之余在虚拟机安装了 Centos 7.2 系统,按照 <简单安装MySQL(RPM方式)> 这篇文章安装 MySQL ,发现由于包依赖的问题安装失败,于是索性在官网查询相关文 ...
- C语言提高 (5) 第五天 结构体,结构体对齐 文件
1昨日回顾 2作业讲解 3 结构体的基本定义 //1 struct teacher { int id; char name[64]; }; struct teacher t5 = { 5, " ...
- IOS - 零碎
---恢复内容开始--- 1.模拟器目录: ProjectNameApk.documents.library(cache.preference.cookies).temp 2.Edit-Refacto ...
- javascript的带操作符的赋值运算
看犀牛书发现的问题 下面两个表达式 表达式一 data[i++] *= 2; 表达式二 data[i++] = data[i++] * 2; var data = [7,8,9]; var i = ...
- 51nod-独木舟问题
n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟?分析: 一个显然的策略 ...
- BZOJ 3028 食物 (生成函数+数学题)
题面:BZOJ传送门 题目让我们求这些物品在合法范围内任意组合,一共组合出$n$个物品的方案数 考虑把每种食物都用生成函数表示出来,然后用多项式乘法把它们乘起来,第$n$项的系数就是方案数 汉堡:$1 ...
- CF876A Trip For Meal
CF876A Trip For Meal 题意翻译 小熊维尼非常喜欢蜂蜜! 所以他决定去拜访他的朋友. 小熊有三个最好的朋友:兔子,猫头鹰和小毛驴,每个人都住在自己的房子里. 每对房屋之间都有蜿蜒的小 ...
- JPEG压缩图像超分辨率重建算法
压缩图像超分辨率重建算法学习 超分辨率重建是由一幅或多幅的低分辨率图像重构高分辨率图像,如由4幅1m分辨率的遥感图像重构分辨率0.25m分辨率图像.在军用/民用上都有非常大应用. 眼下的超分辨率重建方 ...