添加枚举字段注解扫描注入
This commit is contained in:
@@ -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 {
|
||||
|
||||
// 只在 Controller(HandlerMethod)里才做注入
|
||||
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 "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user