一、前言
最近由于因接口标准化的项目需求,实现业务产品的接口层面的抽象标准化设计,需解决每次新产品渠道业务扩展造成接口层面对接调试(不同产品属性的差异化比较大,原有的接口都是面向具体化产品的),减少开发工作量,重复流程代码量。
二、重构目标
1.定义通用产品化接口文档 - 解决产品差异带来了开发新接口的重复代码
2.开发流程优化,提供抽象通用层和具体化代码解耦(实现差异化开发XML、DB配置),降低些重复代码,代码间耦合度
三、设计资料
1.接口文档
2.开发设计
重构前:接口联调、controller接口定义逻辑实现、servces层接口服务
重构后:xml用例报文配置、services服务层差异性开发
3.类设计
四、关键代码
1.GenericAssistServiceFactory 服务工厂类
public class GenericAssistServiceFactory { @b@@b@ private String sarName;@b@@b@ private ConcurrentMap<String, Appscene<?>> appscenemapping = new ConcurrentHashMap<String, Appscene<?>>();@b@@b@ protected Log logger = LogFactory.getLog(this.getClass());@b@@b@ private GenericAssistServiceFactory() {@b@ }@b@@b@ {@b@ List<Appscene<?>> _cfg_datas = new GenericXmlIFConfigure().getConfigures();@b@ for (Appscene<?> app : _cfg_datas) {@b@ if (app == null || StringUtils.isEmpty(app.getId())@b@ || appscenemapping.containsKey(app.getId())) {@b@ logger.error("GenericConfigureException error,cause cfg appsecne id is null or id repeated;detail>"@b@ + app != null ? app.toString() : "app is null");@b@ continue;@b@ }@b@ logger.info("instance appscene;detail>" + app);@b@ appscenemapping.put(app.getId(), app);@b@ }@b@@b@ i @b@@b@ }@b@@b@ public static GenericAssistServiceFactory getEntry() {@b@ return InitialzationHolder.instance;@b@ }@b@@b@ public Appscene<?> getGuide(String accessId)@b@ throws GenericServiceInstanceException {@b@ return appscenemapping.get(accessId);@b@ }@b@@b@ @SuppressWarnings("rawtypes")@b@ public GenericAssistService getBean(String accessId)@b@ throws GenericServiceInstanceException {@b@ Appscene _appscene = appscenemapping.get(accessId);@b@ GenericAssistService serviceObj = null;@b@ try {@b@@b@ if (_appscene.getIsMock()) {@b@ serviceObj=new GenericAssistMockHooker(JSONStringUtils.filterChars(_appscene.getResBody()));@b@ logger.error("GenericAssistService instance @GenericAssistMockHooker"@b@ );@b@ } else {@b@ serviceObj = (GenericAssistService) PApp.getInstance()@b@ .getSARContext(sarName).getSpringContext()@b@ .getBean(Class.forName(_appscene.getServiceObj()));@b@ logger.error("GenericAssistService instance success@"@b@ + serviceObj.getClass().getName());@b@ }@b@@b@ } catch (Exception e) {@b@ logger.error("GenericConfigureException error,cause cfg appsecne id is null or id repeated;detail> "@b@ + e.getMessage());@b@ throw new GenericServiceInstanceException(e.getMessage());@b@ }@b@ return serviceObj;@b@ }@b@@b@ protected static class InitialzationHolder {@b@ public static GenericAssistServiceFactory instance = new GenericAssistServiceFactory();@b@@b@ }@b@ @b@@b@}
2.GenericAssistService标准化服务接口
public interface GenericAssistService<T extends GenericVO> {@b@ @b@ public DataResult<?> getList(T valueObj) throws Exception;@b@ @b@ public DataResult<?> getList(String valueObj) throws Exception;@b@ @b@ public DataResult<?> getList(Map<String,?> valueObj) throws Exception;@b@ @b@ public DataResult<?> createOrUpdate(String valueObj) throws Exception;@b@ @b@ public DataResult<?> createOrUpdate(Map<String,?> valueObj) throws Exception;@b@ @b@@b@}
3.GenericAssistController通用接口定义
@Controller@b@public class GenericAssistController extends BaseController{@b@ @b@ @ResponseBody @b@ @RequestMapping("/getAccessGuide.do")@b@ public ModelMap getAccessGuide(@Valid GenericAssistGuideForm form) {@b@ logger.info("getAccessGuide_GenericAssistForm=" + form);@b@ ModelMap model=new ModelMap();@b@ try {@b@ model.put("responseCode", Constants.GENERIC_SUCCESS_CODE);@b@ model.put("responseMsg", toGuideString(form.getAccessId()));@b@ }catch (Exception e) {@b@ model.put("responseCode", Constants.GENERIC_ERR_UNDEFINED_CODE);@b@ model.put("responseMsg", Constants.GENERIC_ERR_UNDEFINED_MSG);@b@ model.put("data", "");@b@ logger.error("getGenericArchiveData_error=" + e.getMessage(), e);@b@ }@b@ logger.info("getAccessGuide_result=" + model);@b@ return model;@b@ }@b@ @b@ @b@ @ResponseBody @b@ @RequestMapping("/getGenericData.do")@b@ public ModelMap getGenericData(@Valid GenericAssistForm form) {@b@ logger.info("getGenericArchiveData_GenericAssistForm=" + form);@b@ ModelMap model=new ModelMap();@b@ try {@b@ DataResult<?> dataResult=null;@b@ if(GenericReqTypes.getType(form.getReqType())==GenericReqTypes.t1){@b@ dataResult =GenericAssistServiceFactory.getEntry().getBean(form.getAccessId()).getList(toGenericJson(form));@b@ }else if(GenericReqTypes.getType(form.getReqType())==GenericReqTypes.t2){@b@ dataResult =GenericAssistServiceFactory.getEntry().getBean(form.getAccessId()).getList(toGenericString(form));@b@ }@b@ model.put("responseCode", Constants.GENERIC_SUCCESS_CODE);@b@ model.put("responseMsg", Constants.GENERIC_SUCCESS_MSG);@b@ model.put("data", JSON.toJSONString(dataResult, SerializerFeature.WriteNullStringAsEmpty));@b@ }catch (Exception e) {@b@ model.put("responseCode", Constants.GENERIC_ERR_UNDEFINED_CODE);@b@ model.put("responseMsg", Constants.GENERIC_ERR_UNDEFINED_MSG);@b@ model.put("data", "");@b@ logger.error("getGenericArchiveData_error=" + e.getMessage(), e);@b@ }@b@ logger.info("getGenericArchiveData_result=" + model);@b@ return model;@b@ }@b@ @b@ @b@ @ResponseBody @b@ @RequestMapping("/postGenericData.do")@b@ public ModelMap postGenericData(@Valid GenericAssistForm form) {@b@ logger.info("postGenericData_GenericAssistForm=" + form);@b@ ModelMap model=new ModelMap();@b@ try {@b@ DataResult<?> dataResult=null;@b@ if(GenericReqTypes.getType(form.getReqType())==GenericReqTypes.t1){@b@ dataResult =GenericAssistServiceFactory.getEntry().getBean(form.getAccessId()).createOrUpdate(toGenericJson(form));@b@ }else if(GenericReqTypes.getType(form.getReqType())==GenericReqTypes.t2){@b@ dataResult =GenericAssistServiceFactory.getEntry().getBean(form.getAccessId()).createOrUpdate(toGenericString(form));@b@ }@b@ model.put("responseCode", Constants.GENERIC_SUCCESS_CODE);@b@ model.put("responseMsg", Constants.GENERIC_SUCCESS_MSG);@b@ model.put("data", JSON.toJSONString(dataResult, SerializerFeature.WriteNullStringAsEmpty));@b@ }catch (Exception e) {@b@ model.put("responseCode", Constants.GENERIC_ERR_UNDEFINED_CODE);@b@ model.put("responseMsg", Constants.GENERIC_ERR_UNDEFINED_MSG);@b@ model.put("data", "");@b@ logger.error("postGenericData_error=" + e.getMessage(), e);@b@ }@b@ logger.info("postGenericData_result=" + model);@b@ return model;@b@ }@b@ @b@ private Map<String,?> toGenericJson(GenericAssistForm form){@b@ return (Map<String,?>)JSONObject.parseObject(form.getReqBody());@b@ }@b@ @b@ private String toGenericString(GenericAssistForm form){@b@ return form.getReqBody();@b@ }@b@ @b@ @b@}
4.配置化xml模板
<?xml version="1.0" encoding="UTF-8"?>@b@<appscenes>@b@ <appscene id="gs00001" name="产品A获取列表接口" desc="产品A" serviceObj="com.xwood.service.impl.GenericAssistServiceImpl" requestType="json" responseType="json" isMock="true" >@b@ <requestBody>@b@ <![CDATA[@b@ {@b@ "startTime":"2017-09-10",@b@ "endTime":"2017-11-10",@b@ "source":"",@b@ "managerCode":"",@b@ "status:"10",@b@ "limit":"20",@b@ "page":"1"@b@ } @b@ ]]>@b@ </requestBody>@b@ <responseBody>@b@ <![CDATA[@b@ {@b@ @b@ "productType":"产品A",@b@ "mobile":"1562365263",@b@ "name":"测试test",@b@ "realCityName":"上海",@b@ "globalId":"41048245656239564"@b@ } @b@ ]]>@b@ </responseBody> @b@ </appscene>@b@</appscenes>