热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词专为Java开发场景设计,能够根据具体业务需求生成规范的枚举值定义。通过分析应用场景、枚举用途和业务约束,提供符合Java编码标准的枚举结构,包括合理的命名规范、完整的枚举值列表以及必要的文档注释,帮助开发者快速构建高质量的枚举类型,提升代码的可读性和可维护性。适用于权限管理、状态机、配置选项等多种Java开发场景。
枚举概述
枚举定义
package com.example.security;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import org.springframework.security.core.GrantedAuthority;
import java.util.*;
import java.util.stream.Collectors;
/**
* 系统统一角色模型。
*
* 设计约束:
* 1) code 全局唯一且长期稳定;仅以 code 进行序列化/持久化;严禁使用 ordinal。
* 2) 常量命名使用 UPPER_SNAKE_CASE;code 以 ROLE_ 前缀兼容 Spring Security。
* 3) priority 数值越小代表级别越高(如系统管理员 < 租户管理员)。
* 4) defaultPermissionTags 为角色的默认权限标签集合,可用于菜单/数据域/API/审批/审计等快速判定与灰度开关。
*
* 国际化建议:
* - displayName 为默认回退展示名;
* - messageKey 可交由 Spring MessageSource 或前端 i18n 解析为本地化文案。
*/
public enum Role implements GrantedAuthority {
/**
* 系统管理员(平台级),具备平台范围的全局管理能力。
*/
SYSTEM_ADMIN(
"ROLE_SYSTEM_ADMIN",
"System Administrator",
"role.system_admin",
10,
Set.of("MENU_ALL", "DATA_ALL", "API_ALL", "APPROVAL_ALL", "AUDIT_ALL", "XSRV_ALL")
),
/**
* 租户管理员(租户级),管理本租户的用户、项目与配置。
*/
TENANT_ADMIN(
"ROLE_TENANT_ADMIN",
"Tenant Administrator",
"role.tenant_admin",
20,
Set.of("MENU_TENANT_ADMIN", "DATA_TENANT_ALL", "API_TENANT_ALL", "APPROVAL_TENANT", "AUDIT_TENANT")
),
/**
* 项目管理员(项目级),管理项目成员、资源与发布。
*/
PROJECT_ADMIN(
"ROLE_PROJECT_ADMIN",
"Project Administrator",
"role.project_admin",
30,
Set.of("MENU_PROJECT_ADMIN", "DATA_PROJECT_ALL", "API_PROJECT_ALL", "APPROVAL_PROJECT", "AUDIT_PROJECT")
),
/**
* 成员(可写),参与日常研发/运营,具备项目写权限。
*/
MEMBER(
"ROLE_MEMBER",
"Member",
"role.member",
50,
Set.of("MENU_MEMBER", "DATA_PROJECT", "API_WRITE", "AUDIT_SELF")
),
/**
* 只读访客(最小权限),仅可查看。
*/
READONLY_GUEST(
"ROLE_READONLY_GUEST",
"Readonly Guest",
"role.readonly_guest",
90,
Set.of("MENU_READONLY", "DATA_READONLY", "API_READONLY")
);
private final String code;
private final String displayName;
private final String messageKey;
private final int priority;
private final Set<String> defaultPermissionTags;
Role(String code,
String displayName,
String messageKey,
int priority,
Set<String> defaultPermissionTags) {
this.code = Objects.requireNonNull(code, "code");
this.displayName = Objects.requireNonNull(displayName, "displayName");
this.messageKey = Objects.requireNonNull(messageKey, "messageKey");
this.priority = priority;
this.defaultPermissionTags = Collections.unmodifiableSet(new LinkedHashSet<>(defaultPermissionTags));
}
// ------- Jackson 兼容:以 code 序列化/反序列化 -------
/**
* 返回稳定的全局唯一 code,用于 JSON 序列化/持久化。
*/
@JsonValue
public String getCode() {
return code;
}
/**
* 通过 code 进行 JSON 反序列化。
*/
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static Role fromJson(String code) {
return fromCode(code);
}
// ------- Spring Security 兼容:作为 GrantedAuthority -------
/**
* Spring Security 所需的权限标识,直接返回 code。
*/
@Override
public String getAuthority() {
return code;
}
// ------- 业务属性 -------
/**
* 默认回退显示名(若未做 i18n 替换时使用)。
*/
public String getDisplayName() {
return displayName;
}
/**
* 国际化消息键(示例:role.system_admin)。
*/
public String getMessageKey() {
return messageKey;
}
/**
* 角色优先级,数值越小权限级别越高。
*/
public int getPriority() {
return priority;
}
/**
* 该角色的默认权限标签集合(不可变)。
*/
public Set<String> getDefaultPermissionTags() {
return defaultPermissionTags;
}
/**
* 简单权限判断:当前角色是否包含给定权限标签(大小写敏感,按完全匹配)。
* 如需通配/前缀匹配,请在业务层扩展。
*/
public boolean hasPermission(String permissionTag) {
if (permissionTag == null || permissionTag.isEmpty()) {
return false;
}
return defaultPermissionTags.contains(permissionTag);
}
/**
* 比较当前角色是否高于另一个角色(优先级数字越小越高)。
*/
public boolean higherThan(Role other) {
return this.priority < other.priority;
}
// ------- code 查找与唯一性保障 -------
private static final Map<String, Role> CODE_LOOKUP;
static {
Map<String, Role> map = Arrays.stream(values())
.collect(Collectors.toMap(
Role::getCode,
r -> r,
(a, b) -> {
// 理论上不会发生,若发生说明 code 冲突
throw new IllegalStateException("Duplicated role code: " + a.getCode());
},
LinkedHashMap::new
));
CODE_LOOKUP = Collections.unmodifiableMap(map);
}
/**
* 根据稳定 code 获取角色;若 code 无效则抛出异常。
*
* @throws IllegalArgumentException 如果 code 未匹配到任何角色
*/
public static Role fromCode(String code) {
Role role = (code == null) ? null : CODE_LOOKUP.get(code);
if (role == null) {
throw new IllegalArgumentException("Unknown role code: " + code);
}
return role;
}
/**
* 尝试根据 code 查找角色;未匹配时返回 Optional.empty(),便于向后兼容处理。
*/
public static Optional<Role> tryFromCode(String code) {
return Optional.ofNullable(code).map(CODE_LOOKUP::get);
}
}
使用示例
// 1) 反序列化与序列化(Jackson)
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(Role.MEMBER); // 输出: "ROLE_MEMBER"
Role role = mapper.readValue("\"ROLE_PROJECT_ADMIN\"", Role.class); // Role.PROJECT_ADMIN
// 2) 安全框架(Spring Security):作为 GrantedAuthority 使用
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
Authentication auth = new UsernamePasswordAuthenticationToken(
"alice",
null,
Set.of(Role.TENANT_ADMIN) // 直接传入枚举,GrantedAuthority = code
);
// hasRole('TENANT_ADMIN') 与 hasAuthority('ROLE_TENANT_ADMIN') 均可配合使用
// 3) 业务判断:菜单 / 数据域 / API 开关
if (role.hasPermission("MENU_PROJECT_ADMIN")) {
// 展示项目管理员菜单
}
if (Role.SYSTEM_ADMIN.higherThan(Role.MEMBER)) {
// 系统管理员级别高于成员
}
// 4) 枚举查找:向后兼容地处理未知值
Role parsed = Role.tryFromCode("ROLE_UNKNOWN")
.orElse(Role.READONLY_GUEST); // 优雅降级
// 5) 国际化显示
// Spring MessageSource: messageKey -> 本地化名称;若找不到则使用 displayName 回退
String i18nName = messageSource.getMessage(role.getMessageKey(), null, role.getDisplayName(), locale);
// 6) Switch 使用
switch (role) {
case SYSTEM_ADMIN:
// 平台级操作
break;
case TENANT_ADMIN:
// 租户级操作
break;
default:
// 常规或只读
break;
}
注意事项
枚举概述
枚举定义
package com.example.order;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
// 如使用 Jackson 做 JSON 序列化/反序列化,可启用以下注解。
// 非 Jackson 环境可忽略或替换为自定义序列化策略。
// import com.fasterxml.jackson.annotation.JsonCreator;
// import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
// import com.fasterxml.jackson.annotation.JsonValue;
/**
* 订单状态(全链路)
* - 使用字符串 code(ORDER_ 前缀)作为稳定标识以便序列化、日志与跨系统对账。
* - 禁止依赖 ordinal;toString 与 JSON 序列化仅输出 code。
* - nextStates 包含自环(自身)以支持异常重试/幂等。
* - UNKNOWN 用于向后兼容未来新增状态码。
*/
public enum OrderStatus {
/**
* 未知状态(向后兼容占位)
* 解析到未识别的 code 时使用本状态,正常流程不应设置为 UNKNOWN。
*/
// @JsonEnumDefaultValue
UNKNOWN(
"ORDER_UNKNOWN",
"未知状态",
"unknown",
"order.status.unknown",
false,
false
),
/**
* 已创建:下单成功,等待支付
*/
CREATED(
"ORDER_CREATED",
"已创建",
"created",
"order.status.created",
false,
false
),
/**
* 待支付:已发起支付等待结果
*/
PENDING_PAYMENT(
"ORDER_PENDING_PAYMENT",
"待支付",
"pending_payment",
"order.status.pending_payment",
false,
false
),
/**
* 已支付:待仓配拣货
*/
PAID(
"ORDER_PAID",
"已支付",
"paid",
"order.status.paid",
false,
true // 已支付允许发起退款
),
/**
* 拣货中:仓内处理
*/
PICKING(
"ORDER_PICKING",
"拣货中",
"picking",
"order.status.picking",
false,
true // 支持退款(拣货未出库)
),
/**
* 已出库/已发货
*/
SHIPPED(
"ORDER_SHIPPED",
"已发货",
"shipped",
"order.status.shipped",
false,
true // 支持拦截退款/拒收退款策略(由业务网关控制)
),
/**
* 已签收/已送达(交易完成)
*/
DELIVERED(
"ORDER_DELIVERED",
"已签收",
"delivered",
"order.status.delivered",
true, // 终态
false // 默认不支持退款(售后另行处理,不纳入此主流程)
),
/**
* 已取消(未履约完成即终止)
*/
CANCELED(
"ORDER_CANCELED",
"已取消",
"canceled",
"order.status.canceled",
true, // 终态
false
),
/**
* 已退款(全额或最终退款)
*/
REFUNDED(
"ORDER_REFUNDED",
"已退款",
"refunded",
"order.status.refunded",
true, // 终态
false
);
// code 为唯一外部标识,序列化与日志仅输出此字段
private final String code;
// 面向用户/前端的文案
private final String label;
// 报表聚合使用的稳定 key(与数仓/指标对齐)
private final String reportKey;
// 消息主题(topic 或路由键),用于状态事件推送
private final String messageTopic;
// 是否为终态
private final boolean terminal;
// 是否可退款(在本状态下是否允许发起退款流程)
private final boolean refundable;
OrderStatus(String code,
String label,
String reportKey,
String messageTopic,
boolean terminal,
boolean refundable) {
this.code = code;
this.label = label;
this.reportKey = reportKey;
this.messageTopic = messageTopic;
this.terminal = terminal;
this.refundable = refundable;
}
// Jackson 序列化时仅输出 code;非 Jackson 环境可使用自定义序列化器
// @JsonValue
public String getCode() {
return code;
}
public String getLabel() {
return label;
}
public String getReportKey() {
return reportKey;
}
public String getMessageTopic() {
return messageTopic;
}
public boolean isTerminal() {
return terminal;
}
public boolean canRefund() {
return refundable;
}
/**
* 允许的迁移集合(包含自环,用于异常重试/幂等)。
* 例如:PENDING_PAYMENT -> {PENDING_PAYMENT, PAID, CANCELED}
*/
public Set<OrderStatus> nextStates() {
Set<OrderStatus> set = TRANSITIONS.get(this);
return set != null ? set : Collections.singleton(this);
}
/**
* 是否允许从当前状态迁移到目标状态。
* 迁移合法包括自环(幂等处理)。
*/
public boolean canTransitionTo(OrderStatus target) {
if (target == null) return false;
return nextStates().contains(target);
}
/**
* 基于 code 的解析(向后兼容:未知 code 映射为 UNKNOWN)。
*/
// @JsonCreator
public static OrderStatus fromCode(String code) {
if (code == null || code.isEmpty()) return UNKNOWN;
OrderStatus s = BY_CODE.get(code);
return s != null ? s : UNKNOWN;
}
/**
* 静态工具:检查 from -> to 是否允许。
*/
public static boolean canTransition(OrderStatus from, OrderStatus to) {
return from != null && from.canTransitionTo(to);
}
/**
* toString 仅输出 code,便于统一日志/审计。
*/
@Override
public String toString() {
return code;
}
// ---- 内部映射:code -> enum,用于高效解析 ----
private static final Map<String, OrderStatus> BY_CODE;
static {
EnumMap<OrderStatus, String> tmp = new EnumMap<>(OrderStatus.class);
for (OrderStatus s : OrderStatus.values()) {
tmp.put(s, s.code);
}
Map<String, OrderStatus> map = new java.util.HashMap<>();
for (Map.Entry<OrderStatus, String> e : tmp.entrySet()) {
String c = e.getValue();
if (map.put(c, e.getKey()) != null) {
throw new IllegalStateException("Duplicate order status code: " + c);
}
}
BY_CODE = Collections.unmodifiableMap(map);
}
// ---- 迁移关系:包含自环(幂等) ----
private static final EnumMap<OrderStatus, Set<OrderStatus>> TRANSITIONS = new EnumMap<>(OrderStatus.class);
static {
// 辅助:生成不可变集合
java.util.function.Function<OrderStatus[], Set<OrderStatus>> setOf =
(arr) -> Collections.unmodifiableSet(EnumSet.of(arr[0], arr));
// 说明:每个集合都包含自环(第一个参数即 from)
put(CREATED,
CREATED, PENDING_PAYMENT, CANCELED);
put(PENDING_PAYMENT,
PENDING_PAYMENT, PAID, CANCELED);
put(PAID,
PAID, PICKING, CANCELED, REFUNDED);
put(PICKING,
PICKING, SHIPPED, CANCELED, REFUNDED);
put(SHIPPED,
SHIPPED, DELIVERED, REFUNDED);
put(DELIVERED,
DELIVERED /* 终态,自环仅为幂等等价重复上报 */);
put(CANCELED,
CANCELED /* 终态 */);
put(REFUNDED,
REFUNDED /* 终态 */);
put(UNKNOWN,
UNKNOWN /* 不建议使用,作为占位 */);
}
private static void put(OrderStatus from, OrderStatus... allows) {
// 构造包含自环的集合(确保 allows 已包含 from;若未包含则自动加入)
EnumSet<OrderStatus> set = EnumSet.noneOf(OrderStatus.class);
if (allows == null || allows.length == 0) {
set.add(from);
} else {
Collections.addAll(set, allows);
set.add(from);
}
TRANSITIONS.put(from, Collections.unmodifiableSet(set));
}
}
使用示例
import com.example.order.OrderStatus;
import java.util.Set;
public class OrderStatusDemo {
// 事件到达时的状态迁移校验(包含幂等自环)
public static boolean tryTransition(String orderId, OrderStatus current, OrderStatus target) {
if (!OrderStatus.canTransition(current, target)) {
// 非法迁移,记录并拒绝
System.out.printf("Reject transition %s -> %s for order %s%n", current, target, orderId);
return false;
}
// 持久化 target 状态(若 target == current 则为幂等重试)
System.out.printf("Apply transition %s -> %s for order %s%n", current, target, orderId);
// persist(orderId, target.getCode());
// 发送状态事件(使用 messageTopic 与 code)
// messageBus.publish(target.getMessageTopic(), Map.of("orderId", orderId, "status", target.getCode()));
return true;
}
// 前端提示 / 文案展示
public static String prompt(OrderStatus status) {
switch (status) {
case CREATED:
return "订单已创建,请尽快支付";
case PENDING_PAYMENT:
return "支付处理中,请稍候";
case PAID:
return "支付成功,等待拣货";
case PICKING:
return "仓库拣货中,请耐心等待";
case SHIPPED:
return "包裹已发出,注意查收";
case DELIVERED:
return "包裹已签收,感谢您的购买";
case CANCELED:
return "订单已取消";
case REFUNDED:
return "已完成退款";
case UNKNOWN:
default:
return "状态更新中";
}
}
// 对账与报表统计:聚合 reportKey
public static void report(OrderStatus status) {
String key = status.getReportKey(); // 如 "shipped"
// metrics.counter("order_status", "key", key).increment();
System.out.printf("Report increment for key=%s%n", key);
}
public static void main(String[] args) {
OrderStatus cur = OrderStatus.fromCode("ORDER_PAID");
Set<OrderStatus> next = cur.nextStates();
System.out.println("Next allows from PAID: " + next); // 输出 code 集合(toString 即 code)
// 示例迁移:PAID -> PICKING
tryTransition("O202501010001", cur, OrderStatus.PICKING);
// 幂等重试:PICKING -> PICKING
tryTransition("O202501010001", OrderStatus.PICKING, OrderStatus.PICKING);
// 非法迁移:PENDING_PAYMENT -> DELIVERED
tryTransition("O202501010002", OrderStatus.PENDING_PAYMENT, OrderStatus.DELIVERED);
// 报表统计
report(OrderStatus.SHIPPED);
// 前端提示
System.out.println(prompt(OrderStatus.SHIPPED));
// 序列化(示意):status.getCode() 或 Jackson @JsonValue
System.out.println("Serialize: " + OrderStatus.SHIPPED.getCode()); // "ORDER_SHIPPED"
}
}
注意事项
枚举概述
枚举定义
package com.example.config;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* 统一的应用配置键定义。所有键:
* 1) 必须以 "app." 前缀开头;
* 2) 使用 kebab-case(如: feature-toggle.enabled);
* 3) 按作用域进行隔离:GLOBAL(全局)、TENANT(租户级)、SERVICE(服务级)。
*
* 作用域派生键(用于多租户/多服务隔离)约定:
* - TENANT 作用域:app.tenants.{tenantId}.<suffix>
* - SERVICE 作用域:app.services.{serviceName}.<suffix>
* 其中 <suffix> 为 canonical key 去掉 "app." 前缀后的部分。
*
* 示例:
* - Canonical: app.payment.enabled
* - TENANT: app.tenants/acme/payment.enabled 或 app.tenants.acme.payment.enabled(推荐用点分隔)
* 约定采用点分隔:app.tenants.acme.payment.enabled
* - SERVICE: app.services.order-service.payment.enabled
*
* 注意:派生键仅用于区分作用域;如无匹配,则回退到 canonical key(GLOBAL)。
*/
public enum AppConfigKey {
/**
* 是否启用风控开关(租户级)。
* 默认 false,确保在未明确开启时不影响正常放行策略。
*
* 示例:
* - Canonical: app.feature.risk-control.enabled
* - Tenant: app.tenants.acme.feature.risk-control.enabled
*/
FEATURE_RISK_CONTROL_ENABLED(
"app.feature.risk-control.enabled",
"false",
"租户级风控功能开关;关闭时仅执行基础校验。",
ConfigScope.TENANT
),
/**
* 风控策略(租户级)。
* 取值示例:conservative / balanced / aggressive(默认 conservative 更安全)。
*/
FEATURE_RISK_CONTROL_STRATEGY(
"app.feature.risk-control.strategy",
"conservative",
"租户级风控策略模式。",
ConfigScope.TENANT
),
/**
* 默认缓存过期时间(秒)(服务级)。
* 默认 600 秒,安全且可回滚,避免缓存穿透。
*/
CACHE_DEFAULT_TTL_SECONDS(
"app.cache.default-ttl-seconds",
"600",
"服务级默认缓存 TTL(秒)。",
ConfigScope.SERVICE
),
/**
* 是否启用布隆过滤器(服务级)。
* 默认 false,避免对内存/CPU产生未评估的额外开销。
*/
CACHE_BLOOM_FILTER_ENABLED(
"app.cache.bloom-filter.enabled",
"false",
"启用布隆过滤器以降低缓存穿透。",
ConfigScope.SERVICE
),
/**
* 支付开通(租户级)。
* 默认 false,确保未开通租户不暴露支付能力。
*/
PAYMENT_ENABLED(
"app.payment.enabled",
"false",
"租户级支付能力是否启用。",
ConfigScope.TENANT
),
/**
* 支付服务提供方(租户级)。
* 默认 none,避免误接入;具体值由集成时约定(如: stripe/alipay/wechat/…)。
*/
PAYMENT_PROVIDER(
"app.payment.provider",
"none",
"租户级支付提供方标识。",
ConfigScope.TENANT
),
/**
* 日志级别(服务级)。
* 默认 INFO。建议仅在排障期间提升日志级别。
*/
LOGGING_LEVEL(
"app.logging.level",
"INFO",
"服务级日志级别(TRACE/DEBUG/INFO/WARN/ERROR)。",
ConfigScope.SERVICE
),
/**
* 是否输出 JSON 日志(服务级)。
* 默认 false,避免在未准备聚合/分析时影响可读性。
*/
LOGGING_JSON_ENABLED(
"app.logging.json.enabled",
"false",
"服务级 JSON 日志输出开关。",
ConfigScope.SERVICE
),
/**
* 服务级限流(每秒请求数)。
* 默认 100,提供基础保护能力。
*/
SERVICE_RATE_LIMIT_PPS(
"app.service.rate-limit-pps",
"100",
"服务级每秒请求限流阈值。",
ConfigScope.SERVICE
),
/**
* 熔断开关(服务级)。
* 默认 true,更安全,避免级联故障。
*/
SERVICE_CIRCUIT_BREAKER_ENABLED(
"app.service.circuit-breaker.enabled",
"true",
"服务级熔断器开关。",
ConfigScope.SERVICE
),
/**
* 灰度发布比例(服务级)。
* 默认 0;单位为百分比 0-100。
*/
FEATURE_GRAY_RELEASE_PERCENTAGE(
"app.feature.gray-release.percentage",
"0",
"服务级灰度流量占比(0-100)。",
ConfigScope.SERVICE
),
/**
* 维护模式(全局)。
* 默认 false;开启后可降级非关键路径(由各服务自行解释该开关)。
*/
FEATURE_MAINTENANCE_MODE_ENABLED(
"app.feature.maintenance-mode.enabled",
"false",
"全局维护模式开关。",
ConfigScope.GLOBAL
);
public static final String APP_PREFIX = "app.";
private static final String TENANTS_SEGMENT = "tenants";
private static final String SERVICES_SEGMENT = "services";
private static final Pattern SEGMENT_PATTERN = Pattern.compile("[a-z0-9]+(-[a-z0-9]+)*");
private static final Map<String, AppConfigKey> BY_KEY;
private final String key; // canonical key
private final String defaultValue; // safe, rollback-friendly
private final String description; // brief doc
private final ConfigScope scope;
AppConfigKey(String key, String defaultValue, String description, ConfigScope scope) {
this.key = Objects.requireNonNull(key, "key");
this.defaultValue = Objects.requireNonNull(defaultValue, "defaultValue");
this.description = Objects.requireNonNull(description, "description");
this.scope = Objects.requireNonNull(scope, "scope");
}
static {
Map<String, AppConfigKey> map = new HashMap<>();
for (AppConfigKey k : values()) {
validateNaming(k.key);
if (map.put(k.key, k) != null) {
throw new IllegalStateException("Duplicated config key: " + k.key);
}
}
BY_KEY = Collections.unmodifiableMap(map);
}
/**
* 返回 canonical key(全局键,形如 app.xxx.yyy)。
*/
public String key() {
return key;
}
/**
* 返回默认值(字符串形式)。调用方可据需要转换为具体类型。
*/
public String getDefaultValue() {
return defaultValue;
}
/**
* 返回键的作用域。
*/
public ConfigScope getScope() {
return scope;
}
/**
* 返回简单说明,便于界面/审计展示。
*/
public String getDescription() {
return description;
}
/**
* 根据 canonical key 查找枚举常量。
* @throws IllegalArgumentException 不存在时抛出
*/
public static AppConfigKey fromKey(String key) {
AppConfigKey k = BY_KEY.get(key);
if (k == null) {
throw new IllegalArgumentException("Unknown config key: " + key);
}
return k;
}
/**
* 生成租户级派生键(TENANT)。
* 约定格式:app.tenants.{tenantId}.<suffix>
* @throws IllegalStateException 如果该键的作用域不是 TENANT
*/
public String keyForTenant(String tenantId) {
if (scope != ConfigScope.TENANT) {
throw new IllegalStateException("Key " + key + " is not TENANT-scoped.");
}
requireNonBlank(tenantId, "tenantId");
return APP_PREFIX + TENANTS_SEGMENT + "." + tenantId + "." + suffix();
}
/**
* 生成服务级派生键(SERVICE)。
* 约定格式:app.services.{serviceName}.<suffix>
* @throws IllegalStateException 如果该键的作用域不是 SERVICE
*/
public String keyForService(String serviceName) {
if (scope != ConfigScope.SERVICE) {
throw new IllegalStateException("Key " + key + " is not SERVICE-scoped.");
}
requireNonBlank(serviceName, "serviceName");
return APP_PREFIX + SERVICES_SEGMENT + "." + serviceName + "." + suffix();
}
/**
* 作用域校验:用于在写入/覆盖时确保使用了正确的作用域。
* @throws IllegalArgumentException 不匹配时抛出
*/
public void validateScope(ConfigScope expected) {
if (this.scope != expected) {
throw new IllegalArgumentException(
"Scope mismatch for key " + key + ": expected " + expected + ", actual " + scope);
}
}
private String suffix() {
return key.substring(APP_PREFIX.length()); // strip "app."
}
private static void validateNaming(String k) {
if (!k.startsWith(APP_PREFIX)) {
throw new IllegalStateException("Key must start with 'app.': " + k);
}
String[] parts = k.substring(APP_PREFIX.length()).split("\\.");
if (parts.length == 0) {
throw new IllegalStateException("Key missing segments: " + k);
}
for (String p : parts) {
if (!SEGMENT_PATTERN.matcher(p).matches()) {
throw new IllegalStateException("Key segment not kebab-case: " + k + " -> " + p);
}
}
if (!k.equals(k.toLowerCase())) {
throw new IllegalStateException("Key must be lowercase: " + k);
}
}
private static void requireNonBlank(String s, String name) {
if (s == null || s.trim().isEmpty()) {
throw new IllegalArgumentException(name + " must not be blank");
}
}
}
/**
* 配置作用域。
* - GLOBAL:全局默认配置;
* - TENANT:租户级配置(可覆盖 GLOBAL);
* - SERVICE:服务级配置(可覆盖 GLOBAL)。
*
* 注意:TENANT 与 SERVICE 互相独立,最终生效策略由业务约定(例如:优先使用更具体的作用域)。
*/
enum ConfigScope {
GLOBAL,
TENANT,
SERVICE
}
使用示例
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;
public class ConfigReader {
private final Environment env;
public ConfigReader(Environment env) {
this.env = env;
}
/**
* 读取配置:根据作用域拼接派生键,找不到则回退到 canonical key,最后使用默认值。
* 仅演示常见类型转换(String/Boolean/Integer/Long/Double);更复杂类型可自行扩展。
*/
public <T> T read(AppConfigKey key, Class<T> type, String tenantId, String serviceName) {
Binder binder = Binder.get(env);
// 1) 按作用域尝试读取(优先更具体的作用域)
String[] candidates = buildCandidates(key, tenantId, serviceName);
for (String candidate : candidates) {
if (candidate == null) continue;
T v = binder.bind(candidate, Bindable.of(type)).orElse(null);
if (v != null) return v;
}
// 2) 未命中则使用默认值
return convertDefault(key.getDefaultValue(), type);
}
private static String[] buildCandidates(AppConfigKey k, String tenantId, String serviceName) {
switch (k.getScope()) {
case TENANT:
return new String[] {
k.keyForTenant(tenantId), // tenant override
k.key() // fallback: global canonical
};
case SERVICE:
return new String[] {
k.keyForService(serviceName), // service override
k.key() // fallback: global canonical
};
case GLOBAL:
default:
return new String[] { k.key() };
}
}
@SuppressWarnings("unchecked")
private static <T> T convertDefault(String raw, Class<T> type) {
if (type == String.class) return (T) raw;
if (type == Boolean.class || type == boolean.class) return (T) Boolean.valueOf(raw);
if (type == Integer.class || type == int.class) return (T) Integer.valueOf(raw);
if (type == Long.class || type == long.class) return (T) Long.valueOf(raw);
if (type == Double.class || type == double.class) return (T) Double.valueOf(raw);
// 如需 Duration、Enum 等,可在此补充解析逻辑
throw new IllegalArgumentException("Unsupported type for default conversion: " + type);
}
}
// 1) 风控开关(租户级)
boolean rcEnabled = new ConfigReader(env).read(
AppConfigKey.FEATURE_RISK_CONTROL_ENABLED, Boolean.class, "acme", null);
// 2) 风控策略(租户级)
String rcStrategy = new ConfigReader(env).read(
AppConfigKey.FEATURE_RISK_CONTROL_STRATEGY, String.class, "acme", null);
// 3) 缓存 TTL(服务级)
int ttl = new ConfigReader(env).read(
AppConfigKey.CACHE_DEFAULT_TTL_SECONDS, Integer.class, null, "order-service");
// 4) 支付开通(租户级),scope 校验(写入/覆盖前)
AppConfigKey.PAYMENT_ENABLED.validateScope(ConfigScope.TENANT);
String tenantKey = AppConfigKey.PAYMENT_ENABLED.keyForTenant("acme"); // app.tenants.acme.payment.enabled
// 5) 日志级别(服务级)
String logLevel = new ConfigReader(env).read(
AppConfigKey.LOGGING_LEVEL, String.class, null, "billing-service");
// 6) fromKey(由配置中心或审计日志回溯枚举)
AppConfigKey key = AppConfigKey.fromKey("app.feature.maintenance-mode.enabled");
注意事项
把“枚举怎么设计”这件事从耗时的经验活,变成标准化、可复制的高效流程。一键生成符合团队规范的枚举定义与使用示例,覆盖权限角色、订单状态、系统配置等常见业务场景;减少漏项与命名混乱,提升可读性与可维护性;缩短评审与联调时间,让试用用户在真实项目中快速见效,促成团队从试用到付费的转化。
快速生成订单、支付、权限等枚举;统一命名与注释,一次成型,减少返工与代码评审时间。
制定团队枚举规范与模板,审视业务状态覆盖度,确保跨模块一致性,降低维护与版本冲突成本。
根据输出的枚举清单梳理用例边界与数据准备,及时发现缺失状态,减少漏测与回归风险。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
半价获取高级提示词-优惠即将到期