DigitalHainan Spring 微服务框架脚手架与集成指南,覆盖 POM、缓存、MyBatis、认证、OSS 等核心模块。

本文档用于指导在目标项目中完成
digitalhainan-security和digitalhainan-user模块集成。 两个模块配合使用,security 负责认证鉴权,user 负责用户上下文管理。执行顺序:
- 先完成「7.1.2 快速集成」的全部步骤(必须)
- 根据业务需求,查阅「功能集成决策索引」选择对应路径,逐项实现
- 遇到配置问题时参考「7.1.3 配置属性参考」
- 出现异常时查阅「7.1.6 常见问题」
代码约定: 所有代码示例均包含完整
import路径和类声明,可直接用于代码生成。
security-spring-boot-starter 提供微服务认证鉴权能力:
code2Token 接口,授权码换 TokenRestSecurityAuthFilter 拦截请求,解析 Token,设置 SecurityContextexcludePath / includePath 路径白名单/黑名单LogoutHandler 清除 Token 缓存Maven 坐标:
<dependency>
<groupId>cn.com.digitalhainan</groupId>
<artifactId>security-spring-boot-starter</artifactId>
</dependency>user-spring-boot-starter 提供用户信息管理能力:
Maven 坐标:
<dependency>
<groupId>cn.com.digitalhainan</groupId>
<artifactId>user-spring-boot-starter</artifactId>
</dependency>前置依赖:
| 依赖 | 说明 |
|---|---|
digitalhainan-pom | 父 POM |
digitalhainan-ms-common | 微服务公共组件 |
digitalhainan-cache(可选) | Redis 缓存(分布式缓存场景) |
apione-client | ApiOne 网关客户端 |
当前版本: 3.1.0-SNAPSHOT
<parent>
<groupId>cn.com.digitalhainan</groupId>
<artifactId>digitalhainan-pom</artifactId>
<version>3.1.0-SNAPSHOT</version>
</parent><dependencies>
<!-- 认证鉴权 -->
<dependency>
<groupId>cn.com.digitalhainan</groupId>
<artifactId>security-spring-boot-starter</artifactId>
</dependency>
<!-- 用户上下文 -->
<dependency>
<groupId>cn.com.digitalhainan</groupId>
<artifactId>user-spring-boot-starter</artifactId>
</dependency>
</dependencies>digitalhainan:
security:
# 登出 URL
logout-url: /api/auth/logout
# 默认请求客户端
default-req-client: uaa
# 免认证路径
exclude-path:
- /api/auth/oauth2/code2Token
- /service/health
- /doc.html
- /swagger-resources/**
- /v3/api-docs/**
# 需认证路径
include-path:
- /api/**
# 构建类型(MOCK / CUSTOM)
build-type: CUSTOM
# Token 缓存
cache:
enable: true
cache-type: CAFFEINE # 或 REDIS
cache-time: 3600 # 缓存时间(秒)
prefix: "token:"
caffeine:
initial-capacity: 100
maximum-size: 100000
# 用户模块
user:
cache:
enable: true
cache-type: CAFFEINE
cache-time: 3600
uaa:
app-key: ""
# Token 策略
hnjt:
token:
token-type: uuid/service/health)无需 Token@LoginUser 标注的 Controller 可获取用户信息| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
digitalhainan.security.logout-url | String | /api/auth/logout | 登出 URL |
digitalhainan.security.exclude-path | List | [] | 免认证路径列表 |
digitalhainan.security.include-path | List | ["/**"] | 需认证路径列表 |
digitalhainan.security.build-type | Enum | — | 构建类型:MOCK(测试)/ CUSTOM(生产) |
digitalhainan.security.default-req-client | String | uaa | 默认请求客户端:uaa / hyb / ucs |
digitalhainan.security.cache.enable | Boolean | true | 是否启用 Token 缓存 |
digitalhainan.security.cache.cache-type | Enum | CAFFEINE | 缓存类型:CAFFEINE / REDIS |
digitalhainan.security.cache.cache-time | Long | 3600 | 缓存时间(秒) |
digitalhainan.security.cache.prefix | String | token: | 缓存 Key 前缀 |
digitalhainan.security.cache.caffeine.initial-capacity | Integer | 100 | Caffeine 初始容量 |
digitalhainan.security.cache.caffeine.maximum-size | Long | 100000 | Caffeine 最大容量 |
| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
digitalhainan.user.cache.enable | Boolean | true | 是否启用用户信息缓存 |
digitalhainan.user.cache.cache-type | Enum | CAFFEINE | 缓存类型:CAFFEINE / REDIS |
digitalhainan.user.cache.cache-time | Long | 3600 | 缓存时间(秒) |
digitalhainan.user.cache.caffeine.initial-capacity | Integer | 100 | Caffeine 初始容量 |
digitalhainan.user.cache.caffeine.maximum-size | Long | 100000 | Caffeine 最大容量 |
digitalhainan.user.uaa.app-key | String | "" | UAA 应用 Key |
| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
hnjt.token.token-type | String | uuid | Token 生成策略:uuid(默认) |
| 需求场景 | 参考章节 |
|---|---|
| Token 认证流程 | 4.1 认证流程 |
| 配置免认证路径 | 4.2 路径白名单 |
| 获取当前用户信息 | 4.3 用户上下文 |
| @LoginUser 注解 | 4.4 @LoginUser |
| 角色权限校验 | 4.5 权限校验 |
| 自定义认证方式 | 4.6 自定义认证 |
| OAuth2 授权码换 Token | 4.7 OAuth2 |
| 自定义 Token 策略 | 4.8 Token 策略 |
| 自定义用户管理 | 4.9 UserManager |
Authorization: Bearer {token})RestSecurityAuthFilter 拦截请求,解析 Tokenrequest-client Header 选择认证方式(UAA/HYB/UCS/Local)SecurityContext 和 AccessContext@LoginUser 获取用户信息请求 → RestSecurityAuthFilter → Authentication → SecurityContext → Controllerdigitalhainan:
security:
exclude-path:
- /api/auth/login # 登录接口
- /api/auth/oauth2/code2Token
- /service/health # 健康检查
- /doc.html # Swagger
- /swagger-resources/**
- /v3/api-docs/**
- /webjars/**package com.example.controller;
import cn.com.digitalhainan.user.context.UserInfoContext;
import cn.com.digitalhainan.user.model.BaseUserInfo;
import cn.com.digitalhainan.user.model.UserAccount;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户上下文使用示例
* 通过 UserInfoContext 获取当前登录用户信息
*/
@RestController
public class UserContextDemoController {
@GetMapping("/api/demo/current-user")
public String getCurrentUser() {
// 获取当前用户账号
UserAccount account = UserInfoContext.getCurrentUserAccount();
if (account == null) {
return "未登录";
}
// 获取基础用户信息
BaseUserInfo userInfo = account.getUserInfo(BaseUserInfo.class);
String userId = userInfo.getUserId();
String nickName = userInfo.getNickName();
String phone = userInfo.getPhone();
String userAccount = userInfo.getAccount();
return "当前用户: " + nickName + " (" + userId + ")";
}
}package com.example.controller;
import cn.com.digitalhainan.user.annotation.LoginUser;
import cn.com.digitalhainan.user.context.UserInfoContext;
import cn.com.digitalhainan.user.model.BaseUserInfo;
import cn.com.digitalhainan.user.model.UserAccount;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @LoginUser 注解使用示例
* 标注在方法或类上,自动加载用户信息到 UserInfoContext
*/
@RestController
public class LoginUserDemoController {
/**
* 基础用法:加载用户基本信息
*/
@LoginUser
@GetMapping("/api/demo/profile")
public String getProfile() {
UserAccount account = UserInfoContext.getCurrentUserAccount();
BaseUserInfo userInfo = account.getUserInfo(BaseUserInfo.class);
return userInfo.getNickName();
}
/**
* 加载用户角色权限
*/
@LoginUser(getRoleAndPermission = true)
@GetMapping("/api/demo/roles")
public String getRoles() {
UserAccount account = UserInfoContext.getCurrentUserAccount();
return account.getRoleAndPermission().toString();
}
/**
* 加载用户所有组织信息
*/
@LoginUser(getAllOrgInfo = true)
@GetMapping("/api/demo/orgs")
public String getOrgs() {
UserAccount account = UserInfoContext.getCurrentUserAccount();
return account.getAllOrg(Object.class).toString();
}
/**
* 跳过用户缓存(实时查询)
*/
@LoginUser(skipUserCache = true)
@GetMapping("/api/demo/realtime")
public String getRealtimeInfo() {
UserAccount account = UserInfoContext.getCurrentUserAccount();
return account.getUserInfo(BaseUserInfo.class).getAccount();
}
}@LoginUser 注解参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
getAllOrgInfo | boolean | false | 是否加载所有组织信息 |
getCurrenAppOrgInfo | boolean | false | 是否加载当前应用组织信息 |
getRoleAndPermission | boolean | false | 是否加载角色权限 |
skipUserCache | boolean | false | 是否跳过用户缓存 |
skipAllOrgCache | boolean | false | 是否跳过组织缓存 |
skipCurrentAppOrgCache | boolean | false | 是否跳过当前应用组织缓存 |
skipRoleAndPermissionCache | boolean | false | 是否跳过角色权限缓存 |
package com.example.controller;
import cn.com.digitalhainan.user.annotation.LoginUser;
import cn.com.digitalhainan.user.utils.AuthorizeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 权限校验使用示例
*/
@RestController
public class AuthDemoController {
@Autowired
private AuthorizeUtils authorizeUtils;
@LoginUser(getRoleAndPermission = true)
@GetMapping("/api/demo/admin")
public String adminOnly() {
if (!authorizeUtils.hasRole("ADMIN")) {
return "无权访问";
}
return "管理员操作";
}
}实现 Authentication 接口注册为 Spring Bean:
package com.example.auth;
import cn.com.digitalhainan.ms.common.web.security.auth.AccessParameters;
import cn.com.digitalhainan.security.auth.AbstractAuthentication;
import cn.com.digitalhainan.security.auth.AuthInfo;
import jakarta.servlet.http.HttpServletRequest;
/**
* 自定义认证实现示例
*/
public class CustomAuthentication extends AbstractAuthentication {
@Override
public AuthInfo doAuthentication(HttpServletRequest request, AccessParameters accessParameters) {
// 自定义认证逻辑:解析 Token,查询用户信息
AuthInfo authInfo = new AuthInfo();
String token = parseToken(request);
// ... 验证 token 并填充 authInfo
authInfo.setUserId("user-id");
authInfo.setAccount("username");
authInfo.setNickName("昵称");
return authInfo;
}
@Override
public void doLogout(HttpServletRequest request) {
// 登出清理逻辑
}
}# 授权码换 Token
curl -X POST http://host:port/api/rest/oauth2/code2Token \
-H "Content-Type: application/json" \
-d '{"code": "授权码", "authType": "认证类型"}'实现 TokenStrategy 接口:
package com.example.token;
import cn.com.digitalhainan.security.auth.token.strategy.TokenStrategy;
/**
* 自定义 Token 生成策略
*/
public class CustomTokenStrategy implements TokenStrategy {
@Override
public String generateToken() {
// 自定义 Token 生成逻辑
return "custom-token-" + System.currentTimeMillis();
}
}配置使用自定义策略:
hnjt:
token:
token-type: custom # 对应 Bean 名称实现 UserManager 接口:
package com.example.user;
import cn.com.digitalhainan.user.manager.UserManager;
import cn.com.digitalhainan.user.model.BaseUserInfo;
import cn.com.digitalhainan.user.model.RoleAndPermission;
/**
* 自定义用户管理实现
*/
public class CustomUserManager implements UserManager {
@Override
public <T extends BaseUserInfo> T getUserInfoById(String userId) {
// 从自定义数据源获取用户信息
return null;
}
@Override
public Object getUserAllOrg(String userId) {
return null;
}
@Override
public Object getUserOrgByAppKey(String userId) {
return null;
}
@Override
public RoleAndPermission getRolesAndPermissions(String userId) {
return null;
}
}原因: excludePath 未配置登录接口和公共接口。 解决: 在 digitalhainan.security.exclude-path 中添加免认证路径。
原因: 未引入 user-spring-boot-starter 依赖,或请求未经过认证过滤器。 解决: 确保同时引入 security-spring-boot-starter 和 user-spring-boot-starter。
原因: Controller 方法未标注 @LoginUser,或认证未通过。 解决: 在 Controller 或方法上添加 @LoginUser 注解。
原因: 未引入 cache-spring-boot-starter 或 Redis 未配置。 解决: 添加缓存依赖并配置 Redis 连接,或将 cache-type 改为 CAFFEINE。
原因: 默认使用 UAA 认证。 解决: 请求 Header 中设置 request-client: hyb 或 request-client: ucs,或修改 digitalhainan.security.default-req-client。
| security/user | Spring Boot | Spring Security | JDK | 说明 |
|---|---|---|---|---|
| 3.1.0-SNAPSHOT | 3.x | 6.x | 21 | 当前版本 |
| 3.0.0 | 3.x | 6.x | 21 | Spring Boot 3.x |
| 2.0.0 ~ 2.1.0 | 2.x | 5.x | 8/11 | javax 命名空间 |