由于spring mvc自带的枚举解析器无法解析ordinal,所以自己写了一个,方便以后其他项目中用到
一:创建一个controller方法中的参数上使用的注解
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 这个注解用于标记在Controller方法的参数上,表示该参数是个枚举,此时会将前端传递的字符串或者ordinal转换成该枚举类
*
* @author shiwentian
* @since 7.6.2023
**/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
二:实现参数解析器
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
/**
* 解析Controller方法中标记{@link EnumParam}注解的参数
*
* @author shiwentian
* @since 07.06.2023
*/
@Component
public class EnumArgumentResolver implements HandlerMethodArgumentResolver, WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(this);
}
@Override
public boolean supportsParameter(MethodParameter parameter) {
Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation annotation : annotations) {
if (annotation.annotationType() == EnumParam.class) {
return true;
}
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest httpRequest = webRequest.getNativeRequest(HttpServletRequest.class);
if (httpRequest == null) {
return null;
}
Parameter enumParam = parameter.getParameter();
EnumParam enumAnnotation = parameter.getParameterAnnotation(EnumParam.class);
String queryStringName = enumAnnotation.value();
String queryStringValue = httpRequest.getParameter(queryStringName);
if (queryStringValue.matches("^[0-9]+$")) {
int ordinal = Integer.parseInt(queryStringValue);
Object[] enumObjects = enumParam.getType().getEnumConstants();
for (Object enumObject : enumObjects) {
Method ordinalMethod = enumObject.getClass().getMethod("ordinal");
int ordinalIndex = (int) ordinalMethod.invoke(enumObject);
if (ordinal == ordinalIndex) {
return enumObject;
}
}
return null;
} else {
Object[] enumObjects = enumParam.getType().getEnumConstants();
for (Object enumObject : enumObjects) {
Method nameMethod = enumObject.getClass().getMethod("name");
Object enumName = nameMethod.invoke(enumObject);
if (enumName.equals(queryStringValue)) {
return enumObject;
}
}
return null;
}
}
}
三:使用示例(我只实现了get请求)
@GetMapping("xxx/xxx")
public 返回类型 test(@EnumParam("type") UserType userType) {
System.out.print(userType);
return XXX;
}