4.2_后端扩展参考
1、实现:
统一使用springbean实现业务逻辑,所有的接口,均存放于devops-specs项目的com.primeton.devops.specs.api构件包中
注意: 包名需要是com.primeton.devops.为前缀的,否则需要在spring.xml中配置包扫描。
1)单实现业务:
使用@Order注解实现(值越小,优先级越高,系统提供的实现为int最大值),使用@Autowired注解注入引用。示例如下:
//业务实现 @Service @Order(100) public class UserServiceExtend extends UserService { @Override public LoginResult login(String userName, String password) throws Exception { ... } ... } @Controller public class UserController implements IUserController { //引用注入 @Autowired private IUserService userService; ... }
2)多实现业务:
使用EnforcedServiceLoader方式引用加载,配置文件在构件包的META-INF/services目录下,文件名为接口名。示例如下:
配置文件com.primeton.devops.specs.api.pcm.IWorklistApprovalActionService:
#com.primeton.devops.specs.api.pcm.IWorklistApprovalActionService接口实现 com.primeton.devops.pcm.helper.ReleaseWorklistApprovalActionService,WorklistType=RELEASE_APPROVAL com.primeton.devops.pcm.helper.ReleaseConfirmWorklistApprovalActionService,WorklistType=RELEASE_CONFIRM com.primeton.devops.pcm.helper.ReleaseTaskConfirmWorklistApprovalActionService,WorklistType=RELEASE_TASK_CONFIRM com.primeton.devops.pcm.helper.CodeMergeWorklistApprovalActionService,WorklistType=CODE_MERGE_APPROVAL com.primeton.devops.pcm.helper.ProjectCreateApprovalActionService,WorklistType=PROJECT_CREATE_APPROVAL
实现使用加载示例代码:
EnforcedServiceLoader<IWorklistApprovalActionService> serviceLoader = EnforcedServiceLoader.load(IWorklistApprovalActionService.class); Map<String, String> property = new HashMap<String, String>(); property.put("WorklistType", worklistApproval.getWorklistType()); IWorklistApprovalActionService worklistApprovalActionService = serviceLoader.getService(property, false, false);
2、事务控制
如果是自己写的独立线程发起,需要调用TransitionUtil的方法进行业务处理;否则不用关心事务问题。TransitionUtil方法如下:
/** * 生成包含事务控制的固定的线程执行器 * * @param nThreads 线程数 * @param isDaemon 是否是daemon线程 * @param threadName 线程名称 * @return 线程执行器 */ public static ThreadPoolExecutorWithTx newFixedThreadPoolExecutorWithTx(int nThreads, boolean isDaemon, String threadName); /** * 生成包含事务控制的线程 * * @param isDaemon 是否是daemon线程 * @param threadName 线程名称 * @return 线程 */ public static ThreadWithTx newThreadWithTx(boolean isDaemon, String threadName); /** * 在事务中执行,没有线程的情况下 */ public static <T> T executeWithTx(Callable<T> call) throws Exception;
3、错误信息统一前后端处理,处理规范如下:
1) 定义一个实现com.primeton.devops.specs.exception.DevOps.ErrorCode接口的枚举类,错误信息由错误码、错误信息和格式化参数构成,使用异常抛出。
注意:错误信息可以有国际化,如果有国际化,前端会显示国际化后的错误信息,否则会统一显示“系统错误,请联系管理员.”。
定义示例:
//有国际化信息 PROJECT_ALREADY_EXISTED("en=>Project[{0}] already existed.", "zh_CN=>项目[{0}]已存在。"), //无国际化 LOCK_ACQUIRED_TIMEOUT("Lock acquired tomeout: [lockType={0}][lockId={1}][timeout={2}]."), ***使用示例:***
throw new DevOpsException(DevOps.PM.PROJECT_ALREADY_EXISTED, >project.getProjectCode());
扩展示例:
public enum XXX implements ErrorCode { XXXXX_ALREADY_EXISTED("en=>XXXXX[{0}] already existed.", "zh_CN=>XXXXX[{0}]已存在。"), ... ; private XXX(String... localeMessages) { setMessages(localeMessages); } }
2) 前端请求是设置head中的“Locale”信息,得到的错误信息对象格式(Json串):
{ "errorCode": "DEVOPS_PM_PROJECT_ALREADY_EXISTED", "errorLocalizedMessage": "项目[DEMOA]已存在。", "errorMessage": "Project[DEMOA] already existed." }
4、devops的后端jar包(包含所有的接口和实现类)
如果是Maven工程,可以把jar包上传到maven仓库中。GAV信息设置如下:
<groupId>com.primeton.devops</groupId> <artifactId>devops</artifactId> <version>5.5.0.0</version>