Estou procurando a maneira mais fácil e simples de vincular e converter dados no Spring MVC. Se possível, sem fazer nenhuma configuração xml.
Até agora eu tenho usado PropertyEditors assim:
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();
}
}
e
...
public class MyController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Category.class, new CategoryEditor());
}
...
}
É simples: ambas as conversões são definidas na mesma classe e a ligação é direta. Se eu quisesse fazer uma ligação geral em todos os meus controladores, ainda podia adicionar 3 linhas na minha configuração xml .
Mas o Spring 3.x introduziu uma nova maneira de fazer isso, usando os Conversores :
Dentro de um contêiner Spring, esse sistema pode ser usado como uma alternativa aos PropertyEditors
Então, digamos que eu queira usar conversores, porque é "a última alternativa". Eu teria que criar dois conversores:
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();
}
}
Primeira desvantagem: eu tenho que fazer duas aulas. Benefício: não há necessidade de lançar graças à genéricos.
Então, como eu simplesmente vinculo os dados aos conversores?
Segunda desvantagem: não encontrei nenhuma maneira simples (anotações ou outras facilidades programáticas) de fazer isso em um controlador: nada parecido someSpringObject.registerCustomConverter(...);
.
As únicas maneiras que eu encontrei seriam tediosas, não simples e apenas sobre a ligação geral entre controladores:
-
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="somepackage.StringToCategory"/> <bean class="somepackage.CategoryToString"/> </set> </property> </bean>
Configuração Java ( apenas no Spring 3.1+ ):
@EnableWebMvc @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override protected void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringToCategory()); registry.addConverter(new CategoryToString()); } }
Com todas essas desvantagens, por que usar conversores? Estou esquecendo de algo ? Existem outros truques que eu não conheço?
Estou tentado a continuar usando PropertyEditors ... A ligação é muito mais fácil e rápida.
fonte
Respostas:
Não, acho que você descreveu muito bem o PropertyEditor e o Converter, como cada um é declarado e registrado.
Na minha opinião, os PropertyEditors são limitados em escopo - eles ajudam a converter String em um tipo, e essa string geralmente vem da interface do usuário; portanto, registrar um PropertyEditor usando @InitBinder e WebDataBinder faz sentido.
O conversor, por outro lado, é mais genérico, destina-se a QUALQUER conversão no sistema - não apenas para conversões relacionadas à interface do usuário (String para o tipo de destino). Por exemplo, o Spring Integration usa um conversor extensivamente para converter uma carga útil da mensagem em um tipo desejado.
Eu acho que, para os fluxos relacionados à interface do usuário, os PropertyEditors ainda são apropriados, especialmente para o caso em que você precisa fazer algo personalizado para uma propriedade de comando específica. Para outros casos, eu aceitaria a recomendação da referência do Spring e escreveria um conversor (por exemplo, para converter de um ID longo para uma entidade, como exemplo).
fonte
fonte
A maneira mais simples (supondo que você esteja usando uma estrutura de persistência), mas não a maneira perfeita, é implementar um conversor de entidade genérico via
ConditionalGenericConverter
interface que converterá entidades usando seus metadados.Por exemplo, se você estiver usando JPA, esse conversor poderá verificar se a classe especificada possui
@Entity
anotação e usar o@Id
campo anotado para extrair informações e executar a pesquisa automaticamente usando o valor String fornecido como um ID para pesquisa.ConditionalGenericConverter
é uma "arma definitiva" da API de conversão Spring, mas está sendo implementada uma vez que será capaz de processar a maioria das conversões de entidade, economizando tempo do desenvolvedor - é um grande alívio quando você apenas especifica as classes de entidade como parâmetros do seu controlador e nunca pensa em implementar um novo conversor (exceto para tipos personalizados e não-entidades, é claro).fonte
Você pode resolver a necessidade de ter duas classes de conversor separadas, implementando os dois conversores como classes internas estáticas.
Você ainda precisará registrar os dois separadamente, mas pelo menos isso reduz o número de arquivos que você precisa modificar se fizer alguma alteração.
fonte