logo资料库

泛微E9后台开发指南.pdf

第1页 / 共25页
第2页 / 共25页
第3页 / 共25页
第4页 / 共25页
第5页 / 共25页
第6页 / 共25页
第7页 / 共25页
第8页 / 共25页
资料共25页,剩余部分请下载后查看
概述
架构图
目录结构
标准开发指南
开发说明
1、建立Action类
2、建立Service类
3、Service对象实例化方式
4、建立Command类
5、规范
异常处理
日志处理
无侵入开发指南
类级别(Command)动态代理
方法级(Service-Method)动态代理
概述 架构图 目录结构 标准开发指南 开发说明 1、建立Action类 2、建立Service类 3、Service对象实例化方式 4、建立Command类 5、规范 异常处理 日志处理 无侵入开发指南 类级别(Command)动态代理 方法级(Service-Method)动态代理 概述 新架构与现行的架构能够很好的结合,前后端分离的同时,对后端增加了分层、AOP、IOC、interceptor的支持。 新架构要求service和Command层必须面向接口编程, 同时通过IOC和命令委托方式进行各层的解耦(具体参加下 方示例); 另外,新架构还提供全局interceptor和局部interceptor、SERVICE-AOP、COMMAND-AOP的支持,可以进行比如 日志记录、声明性事务、安全性,和缓存等等功能的实现和无侵入二开。 新架构采用命令模式和职责链模式作为基础开发模式,提供一系列的公共实现,用于规范开发过程。 架构图
目录结构 总体目录结构
目录说明: 目录 command core workflow hrm email ... 说明 公共模块 核心框架 流程模块 人力资源模块 邮件模块 其他 注意:每一个模块在该目录下都应该有一个对应的目录 内部文件结构 目录说明:
说明 模块内公共业务类目录 常量类目录 业务Command类目录 实体类目录 业务Service服务类目录 工具类目录 Action类目录 目录 biz constant cmd entity service util web   标准开发指南 开发说明 1、建立Action类 Action类需要在web目录下建立,web目录位于模块文件夹下; 每一个功能都应有一个与之对应的Action类,用于 对外提供接口服务,Action中不建议包含业务逻辑的处理,业务逻辑请放到Command层(见后文)。 Action类作 为边界类,对外提供接口服务, 对内做业务调用,并负责将内部返回的数据做JSON格式的转换,返回给接口的调 用者,这里需要注意的是:数据格式的转换尽量的放到Action中, 不要放到业务层(Service、Command层), 这样做的好处是有利于维护和二开。 示例 1 建立action类, 并配置方法的Path,以及返回数据的类型(注意:类并没有配置Path) package com.engine.workflow.web.workflowPath; /** * 标题设置action * */ public class TitleSetListAction { private TitleSetService getService(){ //实例化Service类 return ServiceUtil.getService(TitleSetServiceImpl.class); } /** * 标题设置 * */ @GET @Path("/getCondition") @Produces(MediaType.TEXT_PLAIN) public String getCondition(@Context HttpServletRequest request,@Context HttpServletResponse response){
Map apidatas = new HashMap(); try{ User user = HrmUserVarify.getUser(request, response); //实例化Service 并调用业务类处理 apidatas = getService().getTitleSetCondition(ParamUtil.request2Map(request), user); }catch(Exception e){ //异常处理 e.printStackTrace(); apidatas.put("api_status", false); apidatas.put("api_errormsg", "catch exception : " + e.getMessage()); } //数据转换 return JSONObject.toJSONString(apidatas); } } com.engine目录是核心业务逻辑类所在目录,不允许直接暴露对外服务接口,对外服务接口请暴露在com.api下 (专门提供API服务的目录)。 具体操作是(见示例 1 和 2): 在com.api.模块.web目录下建立对外接口类,然后 通过extends(继承)的方式暴露RESTful服务接口。 示例 1中的Action建立后还不能被前端调用,因为类没有暴露 出来,还差一步,见示例 2 示例 2 在api目录下暴露接口,直接extens之前写好的action package com.api.workflow.web.workflowPath; import javax.ws.rs.Path; /** * 标题设置action * */ @Path("/workflow/nodeSet/titleSet") public class TitleSetAction extends TitleSetListAction{ }   2、建立Service类 Service类需要在service目录下建立,service目录位于模块文件夹下; 每一个功能都应有一个与之对应的Service接口和impl实现类, 注意:Service中不允许有具体的业务实现,仅作为 服务的提供者,具体业务委托给具体的Command。 Service接口不需要继承任何类,但需要将其中的服务接口描述清楚 Service接口示例 /** * 后台流程监控service * @author luosy 2017/12/20
* @version 1.0 * */ public interface WorkflowMonitorSettingService { /** * 获取监控类型sessionkey 列表数据 * @param params 参数列表 * @param user 用户 * @return sessionKey */ public Map getMonitorTypeSessionkey(Map params); } Service实现类需要实现Service业务接口, 并继承框架中的Service类; Service实现类需要在impl目录下建立,impl目录位于service文件夹下; Service实现类示例 /** * 后台流程监控service 实现类 * @author luosy 2017/12/20 * @version 1.0 * */ public class WorkflowMonitorSettingServiceImpl extends Service implements WorkflowMonitorSettingService { @Override public Map getMonitorTypeCondition(Map params, String method) { return commandExecutor.execute(new GetConditionCmd(params,user,method)); } } 3、Service对象实例化方式 Action中不能够通过new的形式实例化Service类,需要调用新架构提供的API来实例化 示例 LoadWorkflowTreeService lwtService = ServiceUtil.getService(LoadWorkflowTreeServiceImpl.class) 4、建立Command类
Command采用单一职责原则,一个类,只做一件事。 如果一个类承担的职责过多,就等于把这些职责耦合在一起了。 一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。 这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。而如果想要避免这种现象的发生,就 要尽可能的遵守单一职责原则。此原则的核心就是解耦和增强内聚性,增加复用和可维护性; Command需要在相应的CMD目录下建立XXXCmd(cmd目录位于模块文件夹下), 实现Command接口即可(实 现execute方法), 如果需要记录日志,兼容一些公共处理,可以直接继承: com.engine.common.biz.AbstractCommonCommand, 该抽象类默认包含user 、params和get set方法 , 另外也包含了日志的。 示例 public class GetSearchConditionCmd extends AbstractCommonCommand>{ public GetSearchConditionCmd(Map params, User user) { this.user = user; this.params = params; } @Override public Map execute(CommandContext commandContext) { return result; } } 5、规范 1. 入参最好使用Map或者Entity对象,尽可能的与Http对象解耦 2. 出参最好使用Map或者Entity对象,不要直接返回单一数据或者String类型的JSON格式数据; 3. 不同功能的服务封装在不同的Service中,用户可以非常清晰地使用特定的Service 4. Service中定义的各个方法都有相应的命令对象(XXCmd) 5. 日志记录尽可能的对本次修改的情况进行详细的记录,比如对一个人员的信息进行了修改, 日志中,要能够 体现出修改的项目, 如果是重要功能,要在之前的基础上增加所修改项目的原值和新值,以便能够追溯到修 改的内容。 6. Command按照功能进行分类,不要按照Command的类型(增删改查)进行分类,这样即使是新人, 也能 够很快的定位到相关的类; 7. Command的设计要符合单一职责原则,不要做过多的事,如果不能把握住这个度, 请按照前端功能接口进 行设计, 一个接口, 对应一个Command; 8. Command中尽可能不要直接调用Service, 如果需要是公共类,请放到Biz目录下; 9. Service必须有一个接口和一个实现类; 10. Service中不能包含具体的业务逻辑, 业务逻辑委托给具体的Command类; 11. Command中不允许直接调用Service方法, 如需要可以调用Biz包下的类; 12. Command中的参数必须要包含Getting和Setting方法,方便无侵入二开获取相关的参数; 13. 前端展示的项和内容不要写死, 一定要根据后端接口数据进行动态展现,这样方便二开,仅修改后端接口即 可;  
异常处理 业务Command对象中不允许抛出非运行时异常,如需要对异常处理, 请先捕捉,然后转成ECException进行抛 出,并对异常发生的情况添加大家可理解的说明。 示例: try { //TODO } catch (Exception e) { throw new ECException(command.getClass().getName() + "执行过程中异常", e); } 日志处理 com.engine.common.biz.AbstractCommonCommand 已经包含了日志接口, 大家只需要实现对应方法, 作成日志对象返回即可, 该抽象类包含单日志记录和批量日志 记录两个方法,大家需要根据自身情况进行选择性实现。 批量日志记录方法: public List getLogContexts() 为了方便记录批量 和 更新操作,增加了一个日志处理类,仅需要少量的代码即可完成日志的记录,且可做到与业 务代码解耦。 该类的实现方式是在业务更新前后去DB中查询,做数据做对比,区分出新建、更新、删除动作,其 对性能可能会有稍微的影响(具体视功能SQL的执行效率而定),对于性能有严苛要求的功能,请酌情使用。 示例 1 使用SimpleBizLogger进行日志主从日志记录 package com.engine.workflow.cmd.workflowPath.node.operatorSetting; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import weaver.conn.RecordSetTrans; import weaver.general.Util; import weaver.hrm.HrmUserVarify; import weaver.hrm.User; import weaver.systeminfo.SystemEnv; import weaver.workflow.workflow.WfRightManager; import weaver.workflow.workflow.WorkflowComInfo; import com.engine.common.biz.AbstractCommonCommand; import com.engine.common.biz.SimpleBizLogger; import com.engine.common.biz.SimpleBizLogger.SubLogInfo; import com.engine.common.constant.BizLogSmallType4Workflow;
分享到:
收藏