添加枚举字段注解扫描注入
This commit is contained in:
@@ -8,6 +8,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||||||
|
|
||||||
|
|
||||||
import quant.rich.emoney.interceptor.BaseInterceptor;
|
import quant.rich.emoney.interceptor.BaseInterceptor;
|
||||||
|
import quant.rich.emoney.interceptor.EnumOptionsInterceptor;
|
||||||
import quant.rich.emoney.service.ConfigService;
|
import quant.rich.emoney.service.ConfigService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,6 +24,9 @@ public class EmoneyAutoConfig implements WebMvcConfigurer {
|
|||||||
@Autowired
|
@Autowired
|
||||||
BaseInterceptor baseInterceptor;
|
BaseInterceptor baseInterceptor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
EnumOptionsInterceptor enumOptionsInterceptor;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
ConfigService configService;
|
ConfigService configService;
|
||||||
|
|
||||||
@@ -34,5 +38,6 @@ public class EmoneyAutoConfig implements WebMvcConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
registry.addInterceptor(baseInterceptor).addPathPatterns("/**");
|
registry.addInterceptor(baseInterceptor).addPathPatterns("/**");
|
||||||
|
registry.addInterceptor(enumOptionsInterceptor).addPathPatterns("/**");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ public class ReflectionsConfig {
|
|||||||
@Bean("reflections")
|
@Bean("reflections")
|
||||||
Reflections reflections() {
|
Reflections reflections() {
|
||||||
return new Reflections(new ConfigurationBuilder()
|
return new Reflections(new ConfigurationBuilder()
|
||||||
.addScanners(Scanners.MethodsAnnotated, Scanners.SubTypes, Scanners.TypesAnnotated)
|
.addScanners(
|
||||||
|
Scanners.MethodsAnnotated,
|
||||||
|
Scanners.SubTypes,
|
||||||
|
Scanners.FieldsAnnotated,
|
||||||
|
Scanners.TypesAnnotated)
|
||||||
.forPackages("quant.rich.emoney"));
|
.forPackages("quant.rich.emoney"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package quant.rich.emoney.entity.config;
|
||||||
|
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import quant.rich.emoney.entity.config.DeviceInfoConfig.DeviceInfo;
|
||||||
|
import quant.rich.emoney.interceptor.EnumOptionsInterceptor.EnumOptions;
|
||||||
|
import quant.rich.emoney.interfaces.ConfigInfo;
|
||||||
|
import quant.rich.emoney.interfaces.IConfig;
|
||||||
|
import quant.rich.emoney.interfaces.ValidEmoneyRequestConfig;
|
||||||
|
import quant.rich.emoney.patch.okhttp.PatchOkHttp;
|
||||||
|
import quant.rich.emoney.util.EncryptUtils;
|
||||||
|
import quant.rich.emoney.util.SpringContextHolder;
|
||||||
|
import quant.rich.emoney.util.TextUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 独立出来一个代理设置的原因是后续可能需要做一个代理池,这样的话独立配置比较适合后续扩展
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@Slf4j
|
||||||
|
@ValidEmoneyRequestConfig
|
||||||
|
@ConfigInfo(field = "proxy", name = "代理设置", initDefault = true)
|
||||||
|
public class ProxyConfig implements IConfig<ProxyConfig> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代理类型
|
||||||
|
*/
|
||||||
|
@EnumOptions("ProxyTypeEnum")
|
||||||
|
private Proxy.Type proxyType = Proxy.Type.DIRECT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代理主机
|
||||||
|
*/
|
||||||
|
private String proxyHost = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代理端口
|
||||||
|
*/
|
||||||
|
private Integer proxyPort = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否忽略 HTTPS 证书校验
|
||||||
|
*/
|
||||||
|
private Boolean ignoreHttpsVerification = false;
|
||||||
|
|
||||||
|
public void afterBeanInit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ProxyConfig() {}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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