web-dev-qa-db-fra.com

Contrôleur d'amorçage Spring - Paramètre Enum en tant que valeur

J'ai un contrôleur de démarrage à ressort, l'un de mes paramètres est un Enum. L'énumération a une valeur de chaîne. Je veux passer en paramètre la valeur de l'énum et le contrôleur pour me donner l'énum. Cela peut-il être fait?

 @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;
     }

}

Je veux pouvoir faire une demande comme suit:

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

Et entrez dans le contrôleur le ProjectVersion.VERSION_1

Des idées?

7
Panos

Ce n'est pas possible tel quel. Vous devez créer votre convertisseur personnalisé pour convertir d'une String à ProjectVersion.

Par exemple, définit d’abord le convertisseur de String à ProjectVersion:

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);
  }
}

Puis enregistrez-le: 

@Configuration
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {

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

Vous pouvez ignorer l'enregistrement si vous définissez ProjectVersionConverter avec un bean Spring. (Ce code n'a pas été testé).

9
Nicolas Labrot

Étant donné que vous devez transmettre (pour chaque requête) l'argument de la méthode Controller, la solution propre consisterait à utiliser HandlerMethodArgumentResolver , de sorte que Le conteneur Spring puisse injecter dynamiquement votre argument ProjectVersion dans le dossier Méthode du contrôleur comme indiqué ci-dessous:

ProjectVersionArgumentResolver class:

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"));
    }
}

Classe ApplicationLauncher de démarrage initial:

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 class:

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;
     }
}
2
developer