129 votes

Conversion de type MVC du printemps : PropertyEditor ou convertisseur ?

Je suis à la recherche de la méthode la plus simple et la plus simple façon de lier et de convertir des données dans Spring MVC. Si possible, sans faire aucune configuration xml.

Jusqu'à présent, j'ai été en utilisant PropertyEditors comme suit :

public class CategoryEditor extends PropertyEditorSupport {

    // Converts a String to a Category (when submitting form)
    @Override
    public void setAsText(String text) {
        Category c = new Category(text);
        this.setValue(c);
    }

    // Converts a Category to a String (when displaying form)
    @Override
    public String getAsText() {
        Category c = (Category) this.getValue();
        return c.getName();
    }

}

et

...
public class MyController {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Category.class, new CategoryEditor());
    }

    ...

}

Il en est simple : la conversion sont définis dans la même classe, et la liaison est simple. Si je voulais faire une liaison générale dans tous mes contrôleurs, je pourrais encore ajouter les 3 lignes dans mon xml de config.


Mais Le Printemps 3.x introduit une nouvelle façon de faire, à l'aide de Convertisseurs :

Au sein d'un Printemps conteneur, ce système peut être utilisé comme une alternative pour PropertyEditors

Donc, disons que je veux utiliser les Convertisseurs parce que c'est "la dernière alternative". Je dois créer deux convertisseurs :

public class StringToCategory implements Converter<String, Category> {

    @Override
    public Category convert(String source) {
        Category c = new Category(source);
        return c;
    }

}

public class CategoryToString implements Converter<Category, String> {

    @Override
    public String convert(Category source) {
        return source.getName();
    }

}

Premier inconvénient : je dois faire deux classes. Avantage : pas besoin de cast grâce à genericity.

Alors, comment puis-je simplement lier des données les convertisseurs ?

Deuxième inconvénient : je n'ai pas trouvé de moyen simple (annotations ou d'autres programmes installations) de le faire dans un contrôleur : rien de tel someSpringObject.registerCustomConverter(...);.

Les seuls moyens que j'ai trouvé serait fastidieux, pas simple, et seulement environ général de la croix-contrôleur de liaison :

  • XML de config :

    <bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="somepackage.StringToCategory"/>
                <bean class="somepackage.CategoryToString"/>
            </list>
        </property>
    </bean>
    
  • Java config (seulement au Printemps 3.1+) :

    @EnableWebMvc
    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        protected void addFormatters(FormatterRegistry registry) {
            registry.addConverter(new StringToCategory());
            registry.addConverter(new CategoryToString());
        }
    
    }
    

Avec tous ces inconvénients, pourquoi utiliser des Convertisseurs ? Ai-je raté quelque chose ? Il existe d'autres astuces que je ne suis pas au courant ?

Je suis tenté d'aller sur l'aide de PropertyEditors... Liaison est beaucoup plus facile et plus rapide.

55voto

Biju Kunjummen Points 20258

Avec tous ces inconvénients, pourquoi utiliser des Convertisseurs ? Ai-je raté quelque chose ? Il existe d'autres astuces que je ne suis pas au courant ?

Non, je pense que vous avez très décrites de manière exhaustive à la fois PropertyEditor et Converter, comment chacun est déclaré et enregistré.

Dans mon esprit, PropertyEditors sont de portée limitée - ils aider à convertir en Chaîne de caractères à un type, et cette chaîne vient généralement à partir de l'INTERFACE utilisateur, et donc l'enregistrement d'un PropertyEditor à l'aide de @InitBinder et à l'aide de WebDataBinder de sens.

Convertisseur sur l'autre main est plus générique, il est prévu pour la conversion dans le système, pas seulement pour l'INTERFACE utilisateur liées conversions(String le type de cible). Par exemple, Spring Integration utilise un convertisseur largement pour la conversion d'une charge utile du message à un type désiré.

Je pense que pour l'INTERFACE utilisateur connexes flux de PropertyEditors sont toujours appropriées, en particulier pour le cas où vous avez besoin de faire quelque chose de personnalisé pour une commande spécifique de la propriété. Pour les autres cas, je prendrais la recommandation du Printemps de référence et d'écrire un convertisseur à la place(par exemple, pour convertir une Longue identification d'une entité dire, comme un exemple).

15voto

Alexander Points 121
  1. Pour/à partir de la conversion en Chaîne usage des formateurs (mettre en œuvre org.springframework.format.Formateur) au lieu de les convertisseurs. Il a l'impression(...) et analyser(...) les méthodes, si vous avez besoin d'une seule classe, au lieu de deux. Pour vous inscrire, utilisez FormattingConversionServiceFactorybean, qui peut enregistrer à la fois les convertisseurs et les formateurs, au lieu de ConversionServiceFactoryBean.
  2. Le nouveau module de Formatage des trucs a quelques avantages supplémentaires:
    • Formateur interface fournit les paramètres Régionaux de l'objet dans son impression(...) et analyser(...) les méthodes, de sorte que votre chaîne de conversion peuvent être sensibles aux paramètres régionaux
    • En plus de la pré-enregistré formateurs, FormattingConversionServiceFactorybean est livré avec un couple de pratique préinscrits AnnotationFormatterFactory objets, qui vous permettent de spécifier d'autres paramètres de mise en forme via l'annotation. Par exemple: @RequestParam @DateTimeFormat(pattern="MM-jj-aa") LocalDate baseDate ... Il n'est pas très difficile de créer votre propre AnnotationFormatterFactory classes, voir du Printemps NumberFormatAnnotationFormatterFactory pour un exemple simple. Je pense que ceci élimine le besoin spécifique de contrôleur des formateurs/éditeurs. Utiliser un ConversionService pour tous les contrôleurs et personnaliser la mise en forme via des annotations.
  3. Je suis d'accord que si vous avez encore besoin de quelques contrôleur spécifique de la chaîne de conversion, le plus simple est encore d'utiliser l'éditeur de propriétés personnalisées. (J'ai essayé d'appeler"binder.setConversionService(...)"in my @InitBinder méthode, mais il ne parvient pas, depuis l'objet de classeur est livré avec le "global" service de conversion déjà. Semble par-contrôleur de conversion les classes de décourager les au Printemps 3).

7voto

Boris Treukhov Points 5564

Le plus simple (en supposant que vous utilisez une persistance cadre), mais pas la meilleure façon est de mettre en œuvre un générique de l'entité convertisseur via ConditionalGenericConverter interface qui vous permet de convertir les entités à l'aide de leurs métadonnées.

Par exemple, si vous êtes en utilisant JPA, ce convertisseur peut regarder si la classe spécifiée a @Entity d'annotation, et utiliser @Id annoté champ à extraire des informations et effectuer la recherche automatiquement à l'aide de la fonction de la Chaîne de valeur de l'Id pour la recherche.

public interface ConditionalGenericConverter extends GenericConverter {
    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}

ConditionalGenericConverter est une "arme ultime" du Printemps de conversion de l'API, mais le fait d'être mises en œuvre une fois qu'il sera en mesure de traiter la plupart de l'entité conversions, en économisant le temps du développeur - c'est un grand soulagement quand vous venez de spécifier les classes d'entité en tant que paramètres de votre contrôleur et de ne jamais penser à la mise en œuvre d'un nouveau convertisseur(à l'exception de la coutume et non des types d'entité, bien sûr).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X