1.1. 依赖注入
新写代码使用以下方式进行依赖注入。不再使用@Autowire或@Inject annotation进行注入。
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
1.2. Profiles
- 通用配置需要添加至application.yml。例如 server.port, server.contextPath
- Git中只能提交公共环境的application-xxx.yml
- 反例: application-markfred.yml
- 本地需要添加application-local.yml,并在.gitignore文件是添加application-local.yml的忽略项。
- 新加配置项:
- 需要对所有公共环境application-xxx.yml添加新配置。
- 环境IP相关需要和Leader确认
1.3. 数据库结构规范
1.3.1. 表
- 表名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。
- 表名不使用复数名词
- “mid_”开头
1.3.2. 列
- 表达是与否概念的字段,必须使用 is_xxx 的方式命名。
- liquibase数据类型是boolean
- 数据库类型为bit
- 示例: is_enabed
- 使用被动词。例如: enabled, activated, locked
- 字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。
- 正例:getter_admin, task_config, level3_name
- 反例:GetterAdmin, taskConfig, level_3_name
- 禁用保留字,如desc、range、match、delayed等。具体保留字参阅MySQL Keywords
- 金额字段使用decimal类型。禁止使用float和double。
- 每张实体表必须包含以下字段
- id BIGINT PK
- is_enabled BIT NOT NULL
- is_deleted BIT NOT NULL
- created_by UUID NOT NULL
- created_date TIMESTAMP NOT NULL DEFAULT getDate()
- last_updated_by UUID NOT NULL
- last_updated_date TIMESTAMP NOT NULL DEFAULT getDate()
1.4. Liquibase 使用规范
- 严禁修改已有changeset
- changeset中只包含表结构和系统默认数据的修改。
- 反例:UPDATE art_user SET login = 'xxx' WHERE id = 100000
- changeset
- id: [日期时间][序号] 例如: 201705101200001
- author: 署名
- column需要加入remarks对列进行描述
- 如果column没有constraint,则以 /> 结束column tag
- 每次对表结构的修改需要Leader进行Review
1.5. 异常处理
当下游接口属于Rest接口时,中间件可能需要自定义实现RestService封装,实现过程可以参考SampleRestService和ArtemisRestService。当HttpClientErrorException出现异常处理时,需要进行错误记录与异常上报。上报时抛出ServiceUnavailableException。任务调度器会捕捉该异常,并触发任务重试。
1.6. 开放外部接口使用规范
中间件需要开放接口供外部调用时,需要对外部的请求进行合法性验证,以确保请求的安全性。我们使用url签名的安全策略。供外部使用的接口请求链接统一以 /integration开头,系统会对以此链接开头的请求进行拦截验证,对合法的请求予以放行,非法的链接做驳回处理并给予请求错误返回值提示。
请求参数示例:
{domain}/integration/{apiName}?signature={signature}
signature生成代码见下述代码示例,SignatureCryptUtil工具类参见SDK
package com.helioscloud.middleware.util.CryptUtil;
import java.net.URLEncoder;
import java.util.Date;
public class Signature {
public static void main(String[] args){
//这两个值取自配置文件
String signatureToken = "abccba";
String signatureEncodingAesKey = "cdvsdfvsdfvvbfvf";
Long now = System.currentTimeMillis();
String signature = SignatureCryptUtil.Encrypt(signatureToken+"&"+now,signatureEncodingAesKey);
try {
signature = URLEncoder.encode(signature,"UTF-8");
}catch (Exception e){
System.out.println("URLEncode错误");
}
System.out.println(signature);
}
}
1.6.1. 参数说明
请求参数中的signature为外部接口请求中间件必须携带的验证参数,生成规则如下:
1.将中间件预置的signatureToken及发送请求时的时间戳组合,中间用&连接。 示例:
signatureToken:abccba
时间戳:1508812760463
请求文本:abccba&1409659589
2.将上述组合的报文作为文本,中间件预置的signatureEncodingAesKey作为对称密匙进行AES加密,加密后得到加密后的密文。signatureEncodingAesKey必须为16位字符,AES加密算法采用ECB加密模式,PKCS5Padding补码方式,数据块为128位,最后使用将Base64编码,uft-8的编码集输出,得到加密后的密文。 示例:
signatureEncodingAesKey:cdvsdfvsdfvvbfvf
加密后的密文:SCz3jeKeBIhOKPhGpWQakhycrmbiVYPQabaCDXDvEjw=
3.将上述加密后的密文再做URL编码得到所需要的参数signature。 示例:
SCz3jeKeBIhOKPhGpWQakhycrmbiVYPQabaCDXDvEjw%3D
4.在中间件与集成方维护相同的signatureToken与signatureEncodingAesKey
系统中添加了默认的配置属型如下:
signatureToken: abccba
signatureEncodingAesKey: cdvsdfvsdfvvbfvf
companyId: 2ec774f5-7aba-486c-bd48-cf2ae74c9d9f
signatureValid: 360
如需更改,请在启用的yml文件中添加配置属性覆盖,格式如下:
integration:
crypt:
signatureToken: yourToken
signatureEncodingAesKey: yourKey
companyId: 2ec774f5-7aba-486c-bd48-cf2ae74c9d9f
signatureValid: 720
5.发送的密文解密后的timestamp需要进行实时性校验,默认的时间为10分钟,如需修改,同上步。
1.6.2. 返回值说明:
encodingAesKey为空或者不为16位:
{
"returnCode": 1001,
"returnMessage": "encodingAesKey不合法"
}
传入的signature为空:
{
"returnCode": 1002,
"returnMessage": "签名为空"
}
解密失败:
{
"returnCode": 1003,
"returnMessage": "解密异常,检查签名或者encodingAESKey是否正确"
}
解密后的签名验证错误:
{
"returnCode": 1004,
"returnMessage": "签名验证错误"
}
时间戳格式错误:
{
"returnCode": 1005,
"returnMessage": "时间戳格式异常"
}
签名过期:
{
"returnCode": 1006,
"returnMessage": "签名过期,请在10min内完成验证"
}
1.7. 产品回调加密Service运用
在接收产品推送的加密信息后,三方系统需要进行数据解密工作。数据推送的级别分为公司级别和租户级别两种,对用的解密也分为公司和租户级别。
系统中添加了默认的配置属型如下:
token = "wqeqa";
encodingAesKey = "jWmYm7qr5nMoAUwZRjGtB1";
companyId = "2ec774f5-7aba-486c-bd48-cf2ae74c9d9f";
tenantId = 943460749499830273L;
如启用公司推送的则tenantId可为空,如启用租户推送的companyId可为空。
如需更改,请在启用的yml文件中添加配置属性覆盖,格式如下:
artemis:
crypt:
token: wqeqa111111111111111111111
encodingAesKey: jWmYm7qr5nMoAUwZRjGtB1
signatureAesKey:
companyId: 2ec774f5-7aba-486c-bd48-cf2ae74c9d9f
tenantId: 943460749499830273
三方系统根据推送的数据级别获取相应的解密工具进行数据解密:
租户级解密工具注入: TenantDefaultMsgCryptService
公司级解密工具注入: DefaultMsgCryptService
1.8. 调度任务开发规范
实现接口com.helioscloud.middleware.service.ITaskService
@Service
public class DemoTaskService implements ITaskService {
@Override
public void execute(String startDate, String endDate) {
}
}
将demoTaskService.execute添加到任务列表中即可。