添加枚举字段注解扫描注入

This commit is contained in:
2025-05-12 18:14:38 +08:00
parent a872e4e1d1
commit 410cd565da
4 changed files with 198 additions and 1 deletions

View File

@@ -0,0 +1,113 @@
package quant.rich.emoney.interceptor;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AliasFor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.*;
import jakarta.servlet.http.*;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.*;
import java.util.*;
import java.util.Map.Entry;
import java.lang.annotation.*;
@Component
@Slf4j
public class EnumOptionsInterceptor implements HandlerInterceptor {
@Autowired
Reflections reflections;
private Map<String, Map<String, Enum<?>>> options = null;
private Map<String, String> optionNameMap = new HashMap<>();
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 只在 ControllerHandlerMethod里才做注入
if (!(handler instanceof HandlerMethod)) {
// 静态资源、图片、css、js 都会被 ResourceHttpRequestHandler 处理,
// 这里一律跳过
return true;
}
// 排除 @ResponseBody/json 接口
HandlerMethod hm = (HandlerMethod) handler;
if (hm.hasMethodAnnotation(ResponseBody.class)
|| hm.getBeanType().isAnnotationPresent(RestController.class)) {
return true;
}
if (options == null) {
options = new HashMap<>();
Set<Field> enumOptionFields = reflections.getFieldsAnnotatedWith(EnumOptions.class);
for (Field f : enumOptionFields) {
if (!f.isAnnotationPresent(EnumOptions.class)) continue;
if (!Enum.class.isAssignableFrom(f.getType())) continue;
// 拿到注解和名前缀
EnumOptions anno = f.getAnnotation(EnumOptions.class);
String prefix = anno.value().isBlank() ?
f.getName() + "Enum" :
anno.value();
prefix = prefix.toUpperCase().charAt(0) + prefix.substring(1);
if (optionNameMap.containsKey(prefix)) {
log.warn("EnumOption name {}:{} has already been taken by {}, please check",
prefix, f.getType().getName(), optionNameMap.get(prefix));
continue;
}
optionNameMap.put(prefix, f.getType().getName());
// enum 值列表
@SuppressWarnings("unchecked")
Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) f.getType();
Enum<?>[] constants = enumType.getEnumConstants();
// 构造 Map<name, constant>
Map<String, Enum<?>> optionsMap = new LinkedHashMap<>();
for (Enum<?> c : constants) {
optionsMap.put(c.name(), c);
}
// 放到 Model 里
options.put(prefix, optionsMap);
}
}
for (Entry<String, Map<String, Enum<?>>> entry : options.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
log.debug("Inject enums {}: {} to request {}",
entry.getKey(), optionNameMap.get(entry.getKey()),
request.getRequestURI());
}
return true;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public static @interface EnumOptions {
/**
* 注入到 Model 时用的属性名前缀,
* 默认:字段名 + "Options"
*/
String value() default "";
}
}