一:场景描述
1.场景描述: 在标准产品中,有功能A,前端页面是a.jsp. 目前:客开发现,当前a.jsp ,不满足客户需求,需要自定义:前端界面,并且前端界面名称为:b.jsp.
- 致远公司代码现状:
/** * controller * @author chenxb * @desc cap4日志 * @date 2018-10-10 13:37 * @since A8+ seeyon.com */ public class CapLogController extends BaseController { private static final Log LOGGER = CtpLogFactory.getLog(CapLogController.class); @Override public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView("cap4/monitor/capRunningLog"); List<Enums.CapLogType> capLogTypeList = Enums.CapLogType.getLogTypeListByOwnerType(FormConstant.CAPLOG_TYPEOWNER_RUNNING); List<Map<Integer, String>> capLogTypeMapList = new ArrayList<Map<Integer, String>>(); for (Enums.CapLogType capLogType : capLogTypeList) { // 暂时屏蔽掉自定义触发 if (capLogType == Enums.CapLogType.CUSTOMTRIGGER) { continue; } Map<Integer, String> map = new HashMap<Integer, String>(); map.put(capLogType.getKey(), capLogType.getText()); capLogTypeMapList.add(map); } mav.addObject("capLogType", JSONUtil.toJSONString(capLogTypeMapList)); mav.addObject("formId", request.getParameter("formId")); mav.addObject("bizId", request.getParameter("bizId")); mav.addObject("dataId", request.getParameter("dataId")); return mav; } .... .... }
二:操作步骤
1.第一步:(客开组) bean 替换代码实现。
1.1 创建业务项目
1.2 引入jar 包
<!-- bean 覆盖包 --> <dependency> <groupId>com.seeyon.infra</groupId> <artifactId>spring-sdk-core</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
1.3 找到需要替换的bean 及beanName:
如下代码:
/** * controller * @author chenxb * @desc cap4日志 * @date 2018-10-10 13:37 * @since A8+ seeyon.com */ public class CapLogController extends BaseController { private static final Log LOGGER = CtpLogFactory.getLog(CapLogController.class); @Override public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView("cap4/monitor/capRunningLog"); List<Enums.CapLogType> capLogTypeList = Enums.CapLogType.getLogTypeListByOwnerType(FormConstant.CAPLOG_TYPEOWNER_RUNNING); List<Map<Integer, String>> capLogTypeMapList = new ArrayList<Map<Integer, String>>(); for (Enums.CapLogType capLogType : capLogTypeList) { // 暂时屏蔽掉自定义触发 if (capLogType == Enums.CapLogType.CUSTOMTRIGGER) { continue; } Map<Integer, String> map = new HashMap<Integer, String>(); map.put(capLogType.getKey(), capLogType.getText()); capLogTypeMapList.add(map); } mav.addObject("capLogType", JSONUtil.toJSONString(capLogTypeMapList)); mav.addObject("formId", request.getParameter("formId")); mav.addObject("bizId", request.getParameter("bizId")); mav.addObject("dataId", request.getParameter("dataId")); return mav; } .... .... }
如下:beanName=/cap4/capLog.do
1.5 继承CapLogController,并且带上覆盖标签。
@Replace(beanName = "/cap4/capLog.do") public class CapLogTest2Controller extends CapLogController { /** * bean 覆盖 * 重写逻辑 */ @Override public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView("b"); .... .... return mav; } }
1.6 注册bean:
按照致远开放平台,注册bean,我们将此xml,命名为:spring-demo-manager.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <!--bean 注册 --> <bean name="/cap4/capLog2.do" class="com.seeyon.cap4.form.modules.log.CapLogTest2Controller" </beans>
到此:客开开发完成。
2.第二步:(客开组) bean 替换部署。
2.1 将代码打成jar ,进行部署:
如下图:
三:适用场景
1.特殊客开场景:不通用场景,被标准产品经理判断,不适合提升为:标准接口的场景。 2 过渡场景: 被标准产品经理判断可被定义为通用需求,但业务组实现该需求,需要较长时间,不满足客开交付时间。此时:可使用bean 替换的方式,完成客开, 待标准接口完成后,进行集成。 3 当标准产品中,一个方法有:40%以上的代码,需要被修改或者大部分的流程需要被修改的场景。
四:标准产品升级与客开升级关注点
1.bean 替换在如下的场景,会产生代码合并成本:
在重写父类方法的时候,抄写了父类方法的部分代码。因为标准产品升级,父类方法被修改,此时客开代码无法复用父类功能。若客开想复用此时的父类方法,就会产生 代码合并。
需要说明的是,有复用需求的时候,才会产生代码合并成本。并且这个成会因标准产品方法职责越不单一,成本越高(特别是在那些上千行的方法中)。
2. 标准产品升级(如从1.0.0 升级到2.0.0 ),客开关注点:
2.1 通用业务场景:标准产品业务将自动升级,使用新的业务逻辑。 2.2 定制化业务:即上述为了复用,从父类抄写的那部分代码。 2.2.1 若:定制化业务即使标准产品升级后,任然使用自己定制化代码,那么此时:客开不需要关注 2.2.1 若:定制化业务需要使用标准产品新的功能,那么:需要客开从新抄写这部分代码,然后重写编写定制化代码。 2.3 部署: 请按照部署规范,各自打包独立部署: [部署规范](./模块化设计.md)
3.客开产品升级(如从1.0.0 升级到2.0.0 ),标准产品关注点:
没有。
4.为了减少合并成本,我们有如下几种方式:
1 使用继承,巧用super 调用:
如下代码:
/** * 测试replace order 的值 * * @author Lenovo */ @Replace(beanName = "/cap4/capLog.do",order = 100) public class CapLogTest2Controller extends CapLogController { private static final Log LOGGER = CtpLogFactory.getLog(CapLogTest2Controller.class); @Override public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { ........ // 使用super.index 复用 父类能力。 ModelAndView superIndex = super.index(request, response); //..... return superIndex; } }
如上代码:通过super.index 复用 父类能力。此时:标准产品升级,不会出现合并代码的情况。
2 bean 调用(bean 组合模式):
/** * 测试replace order 的值 * * @author Lenovo */ @Replace(beanName = "/cap4/capLog.do",order = 100) public class CapLogTest2Controller extends CapLogController { private static final Log LOGGER = CtpLogFactory.getLog(CapLogTest2Controller.class); //第一步:声明bean 调用 @Inject private IA a; @Override public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { ........ //方法调用:复用能力 a.index(); ModelAndView superIndex = super.index(request, response); //..... return superIndex; } }