【问题标题】:Spring Boot Controller - Enum parameter as ValueSpring Boot Controller - 枚举参数作为值
【发布时间】:2017-09-01 06:30:45
【问题描述】:

我有一个弹簧启动控制器,我的参数之一是枚举。枚举有一个字符串值。我想将枚举的值和控制器作为参数传递给我枚举。这个可以吗?

 @RequestMapping(value = "/")
public MyResponse getResponse ( @RequestParam(value = "version") final ProjectVersion version ) {
   ...bla bla bla...
}

public enum ProjectVersion {
    VERSION_1 ("1.00")
    VERSION_2 ("2.00")

    private final String version;

    ProjectVersion ( String version ) {
        this.version = version;
    }

     @Override
     public String toString() {
        return this.version;
     }

}

我希望能够提出如下请求:

http://myhost.com/mypath?version=1.00

并在控制器中获取 ProjectVersion.VERSION_1

有什么想法吗?

【问题讨论】:

  • 是的,使用自定义序列化程序。看看这个,正是你的情况:stackoverflow.com/questions/7766791/…
  • 如果你传递VERSION_1它会工作,如果你传递内部值它不会那么你需要自己创建一个自定义转换器。

标签: spring spring-boot enums jackson


【解决方案1】:

这是不可能的。您必须创建自定义转换器才能将 String 转换为 ProjectVersion

例如首先定义从StringProjectVersion的转换器:

public class ProjectVersionConverter implements ConditionalGenericConverter {

  @Override
  public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
    return targetType.getType().equals(ProjectVersion.class);
  }

  @Override
  public Set<ConvertiblePair> getConvertibleTypes() {
    return Collections.singleton(new ConvertiblePair(String.class , ProjectVersion.class));
  }

  @Override
  public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
    return ProjectVersion.findByVersion((String)source);
  }
}

然后注册:

@Configuration
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {

  @Override
  public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new ProjectVersionConverter());
  }
}

如果将ProjectVersionConverter 定义为Spring bean,则可以跳过注册。 (此代码未经测试)。

【讨论】:

  • 使用参数解析器是更干净、更好的方法。
  • 我不同意。转换器不应该打扰该值作为请求参数或路径变量传递。只要使用正确的注释,使用不可知的转换器,它应该可以工作。
【解决方案2】:

因为您需要(对于每个请求)将参数传递给Controller 方法,所以干净的解决方案是使用HandlerMethodArgumentResolver,这样 Spring 容器可以将您的 ProjectVersion 参数动态注入到 Controller 方法中,如下所示:

ProjectVersionArgumentResolver类:

public class ProjectVersionArgumentResolver implements 
                                    HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType().equals(ProjectVersion.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter,
                   ModelAndViewContainer modelAndViewContainer,
                   NativeWebRequest nativeWebRequest,
                   WebDataBinderFactory webDataBinderFactory) throws Exception {

        return ProjectVersion.fromString(nativeWebRequest.getParameter("version"));
    }
}

Spring-boot ApplicationLauncher 类:

public class MyProjectApplicationLauncher extends WebMvcConfigurerAdapter {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> 
                                           argumentResolvers) {
        //add the new resolver
        argumentResolvers.add(new MyMethodArgumentResolver());
    }

    public static void main(String[] args) {
        SpringApplication.run(MyProjectApplicationLauncher.class, args);
    }
} 

ProjectVersion类:

public enum ProjectVersion {

    //add your existing code

    //Add fromString method to convert string to enum 
    public static ProjectVersion fromString(String input) {
        for (ProjectVersion projectVersion : ProjectVersion.values()) {
          if (projectVersion.version.equals(input)) {
            return projectVersion;
          }
        }
        return null;
     }
}

【讨论】:

  • 最好使用 methodParameter.getParameterName() 而不是硬编码的字符串“版本”。所以 ProjectVersion.fromString(nativeWebRequest.getParameter(methodParameter.getParameterName()));
猜你喜欢
  • 2019-10-07
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 2020-04-15
  • 2011-05-30
  • 2011-04-24
  • 1970-01-01
相关资源
最近更新 更多