帮助文档与常见问题
SoFast 内置了 Apache、Hutool 等常用工具类集合,可以满足日常业务开发的需求,非必要情况下,不要在业务服务中编写工具类.
# 通用工具类
通用工具类提供了针对字符、数值、日期、对象等数据结构的常用处理方法
# Apache commons-lang3、Hutool 的所有工具类均可直接使用,如:
// 字符串为空判断
StrUtil.isEmpty(str);
// 获取当前DateTime
DateUtil.date();
// 数值计算(加运算,支持浮点型和BigDecimal)
NumberUtil.add(val1, val2);
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 另外,SoFast 还提供了一些增加工具类
SolDateUtils:基于 JDK8 的时区日期处理 API,如:
// 基于当前时区,获取当前日期+时间
SolDateUtils.now();
// 基于当前时区,获取当前日期
SolDateUtils.getDate();
// 基于当前时区,获取当前时间
SolDateUtils.getTime();
2
3
4
5
6
7
8
2
3
4
5
6
7
8
SolObjUtil:对象判断工具类
// 可判断对象或集合是否为空或Null
SolObjUtils.isEmpty(args);
2
2
SolStringUtils:字符串增强工具类
// 截取字符串前N位,后面部分用{...}表示
SolStringUtils.cutEnd(str, count);
// 截取字符串,中间部分用{...}表示
SolStringUtils.cutMiddle(str, count);
// 同时将多个指定字符替换为空
SolStringUtils.replaceEmpty(str, replaceStr1, replaceStr2...);
2
3
4
5
6
7
8
2
3
4
5
6
7
8
SolUriMatchUti:正则匹配工具类
// 匹配资源列表中是否包含指定资源,支持正则。
SolUriMatchUtil.matchUri(String uri, List<String> uriList)
2
2
SolImgUtils:图像处理工具类
// 剪裁图片,根据传入的矩形框进行剪裁
SolImgUtils.cut(String srcPath, String destPath, int x, int y, int width, int height)
// 剪裁图片,从(0,0)坐标起始点进行剪裁
SolImgUtils.cut(String srcPath, String destPath, int width, int height)
// 缩放图片
SolImgUtils.scale(String srcPath, String destPath, float scale)
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 用户上下文信息获取
SoFast 对登录用户的上下文信息进行了封装,提供了一键获取的方式。
# LoginUserContextHolder
LoginUserContextHolder 是基于线程安全模型封装的用户上下文信息持有器。 用户上下文信息来自于 JWT 令牌的解析内容,在 Token 模式下开发人员可直接在各服务中通过该 Holder 直接获取,不需要解析 Token。
// 获取当前登录用户ID
LoginUserContextHolder.getUserId();
// 获取当前登录用户名
LoginUserContextHolder.getUserName();
// 获取当前登录用户组织机构ID
LoginUserContextHolder.getOrgId();
// 获取当前登录用户角色列表
LoginUserContextHolder.getRoleList();
// 判断当前用户是否为管理员用户
LoginUserContextHolder.isAdmin();
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 操作日志
SoFast 对记录操作日志提供了便捷的方式。
# 开发
SoFast 提供了注解 @LogOperator 用于记录日志。
使用注解 @LogOperator 需要设置两个参数:
title:操作的业务描述(通常是对该方法或业务的描述)
type:操作的类型(查询、插入、更新、删除、上传、下载)
Constants.SELECT_OPERATOR
Constants.INSERT_OPERATOR
Constants.UPDATE_OPERATOR
Constants.DELETE_OPERATOR
Constants.UPLOAD_OPERATOR
Constants.DOWNLOAD_OPERATOR
@LogOperator(title = "更新xxxx", type = Constants.UPDATE_OPERATOR)
@PostMapping(value = "/update")
public R<Boolean> update(@RequestBody SettingsMail params) {
// 编写业务代码
return R.code(MsgConstants.MSG_C002);
}
2
3
4
5
6
7
2
3
4
5
6
7
# 配置
SoFast 支持通过动态配置设置收集日志的级别,方便同一套代码在不同的环境中收集不同级别的日志
log:
operator:
types: insert,update,delete
2
3
2
3
配置支持以下六种分类
select insert update delete upload download
# Message 说明
SoFast 的 Message 支持国际化,可通过配置资源文件实现。 SoFast 内置了大量通用 message,业务开发可选择使用,也可自定义业务的独立 Message。
# Message 定义规范
Level 标识。业务类别标识.MessageId
通用 Message 可省略业务类别标识
如通用Message:
Err.E001=Login Fail.
业务Message:
Err.PL.EXT001=the certificate is bound.
2
3
4
5
2
3
4
5
# SoFast 内置了以下 Message,可直接复制到资源文件中使用
##### 英文Message,可放入该文件messages.properties
Err.E001=Login Fail.
Err.E002=Not Allow Access.
Err.E003=Token Expired.
Err.E004=Login user name already exists, please re-enter.
Err.E005=Please select the user's organization.
Err.E006=User can only specify a single organization.
Err.E007=Please enter the correct parameters.
Err.E008=The original password is wrong.
Err.E009=Only the administrator can reset someone else\u2019s information.
Err.E010=Please enter correct verify code.
Err.E011=Verification code has expired.
Err.E012=Permission value already exists, please re-enter.
Err.E013=Role code already exists, please re-enter.
Err.E014=The account is not bound to a user.
Err.E015=Under the same organization, the organization name cannot be duplicate.
Err.E016=The subordinate organization already exists and cannot be deleted.
Err.E017=The user is bound and cannot be deleted.
Err.E018=Default data, cannot be modified.
Err.E019=Position code already exists, please re-enter.
Err.E020=The menu permission code already exists. Please re-enter it.
Err.E021=API permission code already exists. Please re-enter.
Err.E022=Data permission code already exists. Please re-enter.
Err.E023=The default organization has been bound and cannot be unbound.
Err.E024=Dictionary data has been bound. Dictionary type cannot be modified.
Err.E095=User is already logged in, repeated login is prohibited.
Err.E096=User is locked, login is prohibited.
Err.E097=Request method not supported.
Err.E098=IllegalArgumentException,please confirm request parameters.
Err.E099=An unknown error occurred in the system.
Err.E100=Duplicate primary key or unique index.
Err.E101=Data not exists or delete error.
Err.E102=System is busy, Please try later.
####### \u6587\u4EF6\u64CD\u4F5C\u63D0\u793A\u4FE1\u606F #######
Err.F001=The file name {0} is too long, please make sure the file name is less than {1}.
Err.F002=File format [{0}] is not supported, please upload the file format required by this system.
Err.F003=File download failed, please download again or contact the administrator.
Err.F004=The file you downloaded {0} does not exist.
Err.F005=File upload error.
Err.F006=The size of the uploaded file is too large.
### \u901A\u7528\u6210\u529F\u63D0\u793A\u4FE1\u606F ######
Msg.C001=Inserted successfully.
Msg.C002=Update successfully.
Msg.C003=Deleted successfully.
## 中文Message,可放入该文件:messages_zh_CN.properties
Err.E001=\u767B\u9646\u5931\u8D25,\u8BF7\u786E\u8BA4\u7528\u6237\u540D\u53E3\u4EE4.
Err.E002=\u8BBF\u95EE\u53D7\u9650,\u8BF7\u786E\u8BA4\u6743\u9650.
Err.E003=TOKEN\u975E\u6CD5\u6216\u5DF2\u8FC7\u671F.
Err.E004=\u767B\u5F55\u7528\u6237\u540D\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E005=\u8BF7\u9009\u62E9\u7528\u6237\u6240\u5C5E\u7EC4\u7EC7.
Err.E006=\u7528\u6237\u53EA\u80FD\u6307\u5B9A\u5355\u4E00\u7EC4\u7EC7.
Err.E007=\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u53C2\u6570.
Err.E008=\u539F\u5BC6\u7801\u9519\u8BEF.
Err.E009=\u53EA\u6709\u7BA1\u7406\u5458\u80FD\u91CD\u7F6E\u4ED6\u4EBA\u4FE1\u606F.
Err.E010=\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u9A8C\u8BC1\u7801.
Err.E011=\u9A8C\u8BC1\u7801\u5DF2\u8FC7\u671F.
Err.E012=\u6743\u9650\u503C\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E013=\u89D2\u8272\u7F16\u7801\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E014=\u8BE5\u8D26\u6237\u672A\u7ED1\u5B9A.
Err.E015=\u540C\u4E00\u7EC4\u7EC7\u673A\u6784\u4E0B,\u673A\u6784\u540D\u79F0\u4E0D\u80FD\u91CD\u590D.
Err.E016=\u4E0B\u7EA7\u7EC4\u7EC7\u673A\u6784\u5DF2\u5B58\u5728,\u4E0D\u53EF\u5220\u9664.
Err.E017=\u5DF2\u7ED1\u5B9A\u7528\u6237,\u4E0D\u53EF\u5220\u9664.
Err.E018=\u9ED8\u8BA4\u6570\u636E,\u4E0D\u53EF\u4FEE\u6539.
Err.E019=\u804C\u4F4D\u7F16\u7801\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E020=\u83DC\u5355\u6743\u9650\u7F16\u7801\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E021=API\u6743\u9650\u7F16\u7801\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E022=\u6570\u636E\u6743\u9650\u7F16\u7801\u5DF2\u5B58\u5728\u8BF7\u91CD\u65B0\u8F93\u5165.
Err.E023=\u5DF2\u7ED1\u5B9A\u9ED8\u8BA4\u7EC4\u7EC7,\u4E0D\u53EF\u89E3\u9664\u7ED1\u5B9A.
Err.E024=\u5DF2\u7ED1\u5B9A\u5B57\u5178\u6570\u636E,\u4E0D\u53EF\u4FEE\u6539\u5B57\u5178\u7C7B\u578B.
Err.E095=\u7528\u6237\u5DF2\u767B\u5F55,\u7981\u6B62\u91CD\u590D\u767B\u5F55.
Err.E096=\u7528\u6237\u5DF2\u9501\u5B9A,\u7981\u6B62\u767B\u5F55.
Err.E097=\u9519\u8BEF\u7684\u8BF7\u6C42\u65B9\u6CD5.
Err.E098=\u975E\u6CD5\u6570\u636E\u5F02\u5E38,\u8BF7\u786E\u8BA4\u8BF7\u6C42\u53C2\u6570\u662F\u5426\u6B63\u786E.
Err.E099=\u7CFB\u7EDF\u53D1\u751F\u672A\u77E5\u9519\u8BEF.
Err.E100=\u4E3B\u952E\u6216\u552F\u4E00\u7D22\u5F15\u91CD\u590D.
Err.E101=\u6570\u636E\u4E0D\u5B58\u5728\u6216\u5220\u9664\u5931\u8D25.
Err.E102=\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5.
####### \u6587\u4EF6\u64CD\u4F5C\u63D0\u793A\u4FE1\u606F #######
Err.F001=\u6587\u4EF6\u540D{0}\u8FC7\u957F,\u8BF7\u786E\u4FDD\u6587\u4EF6\u540D\u5C0F\u4E8E{1}.
Err.F002=\u6587\u4EF6\u683C\u5F0F[{0}]\u4E0D\u652F\u6301,\u8BF7\u4E0A\u4F20\u672C\u7CFB\u7EDF\u8981\u6C42\u7684\u6587\u4EF6\u683C\u5F0F.
Err.F003=\u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u4E0B\u8F7D\u6216\u8054\u7CFB\u7BA1\u7406\u5458.
Err.F004=\u60A8\u4E0B\u8F7D\u7684\u6587\u4EF6{0}\u4E0D\u5B58\u5728.
Err.F005=\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25.
Err.F006=\u4E0A\u4F20\u6587\u4EF6\u7684size\u8FC7\u5927,\u8BF7\u8C03\u6574\u6587\u4EF6\u5927\u5C0F\u540E\u91CD\u65B0\u4E0A\u4F20.
### \u901A\u7528\u6210\u529F\u63D0\u793A\u4FE1\u606F ######
Msg.C001=\u63D2\u5165\u6210\u529F.
Msg.C002=\u66F4\u65B0\u6210\u529F.
Msg.C003=\u5220\u9664\u6210\u529F.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# 白名单
如何设置 api 访问白名单.
# 白名单
在本地开发或者对外提供 api 服务场景下,在未登陆的情况,我们期望能访问 api 服务,这时可以通过 sofast 的白名单功能实现。
# 本地开发场景
v2.x 版本,开发微服务时,不启动网关和认证服务的情况下,可,以直接调试微服务,不需要白名单配置。 v1.x 版本,需要在在微服务的配置文件 [application-dev.yml] 中添加白名单配置。例如:
#安全配置
sofast:
security:
white-list: "/demo/**"
2
3
4
2
3
4
# 外部 api 调用
当我们开发的接口需要提供给匿名用户使用时, v2.x 版本只需要在网关中配置白名单,就可以正常访问。 v1.x 版本需要在微服务和网关中都配置白名单,才可以正常访问。例如:
so-fast-gateway 的 application.yml
sofast:
token:
whiteList:
- /v2/api-docs
- /**/swagger-ui/index.html
- /so-fast-uaa/login/**
- /webjars/**
2
3
4
5
6
7
2
3
4
5
6
7
微服务的 application-dev.yml
#安全配置
sofast:
security:
white-list: "/demo/**"
2
3
4
2
3
4
开放白名单意味着将接口直接暴露,安全性较为薄弱,在生产环境中,必须添加其他认证手段来阻挡非正常请求的攻击。建议:
1. 将开放接口的微服务进行隔离部署,不要同内部微服务部署在同一区。
2. 调用双方约定识别因子,用于寻源;请求参数采用加密处理,防止篡改。
# Token 有效期
如何设置令牌的有效期.
# OAuth2
SOFAST 框架中的令牌实现是基于 OAuth2 规范,因此 OAuth2 的所有设置在 SOFAST 中均有效。
# Access Token
OAuth2 通过 sys_oauth_client_detail 表进行客户端控制,其表结构如下所示:
其中黄色部分为令牌的默认有效期(单位:秒)
# Refresh Token
OAuth2 也支持 Refresh Token,在某些业务场景下,如果用户希望自动进行令牌续期时,可通过 Refresh Token 来自动刷新 Access Token,以达到令牌续签能力。
SOFAST 也支持该扩展,开发人员可根据业务需求进行扩展开发。 Refresh Token 的有效期必须要大于 Access Token,通常可设置为 2 倍时间。
其中红色部分为 refresh token 的默认有效期(单位:秒)
← 生产部署