Ho il seguente (semplificata) forma in uno dei mio punto di vista:Quali sono le migliori strategie di conversione Spring nel caso di una stringa da convertire in un insieme di oggetti?
<form:form commandName="entry" method="POST">
<form:input type="text" path="name"/>
<form:input type="text" path="tags" />
<input type="submit" value="Submit"/>
</form:form>
che sta per essere legano al seguente JavaBean:
public class Entry {
private String name;
private List<Tag> tags = new LinkedList<Tag>();
// setters and getters omitted
}
perché voglio prendere uso tutti i nuovi fantasia caratteristiche di Spring 3, che sto utilizzando controller di annotazioni-driven per ricevere la richiesta POST:
@Controller
@RequestMapping("/entry")
public class EntryController {
@RequestMapping(method = RequestMethod.GET)
public ModelAndView show() {
ModelAndView mav = new ModelAndView("entry");
mav.addObject(new Entry());
return mav;
}
@RequestMapping(method = RequestMethod.POST)
public String add(@ModelAttribute("entry") @Valid Entry entry,
BindingResult result) {
// check validation from Binding result
// execute method on business beans: adding this entry to the system
// return a view if correct
}
}
Come potete vedere, ho bisogno di convertire il mio testo di input (che loo k come tag1, tag2, tag3
) come una lista di tag, definiscono in questo modo:
public class Tag {
private String name;
// setter and getter omitted
}
C'è diverse strategie per fare questo con la Primavera 3.0:
( spiacenti palo lungo, le domande sono in grassetto)
Il più semplice
Programmazione di una nuova proprietà tagsAsText
avere un getter/setter come String:
public class Entry {
// ...
public void setTagsAsText(String tags) {
// convert the text as a list of tags
}
public String getTagsAsText() {
// convert list of tags to a text
}
}
Questo approccio presenta due inconvenienti:
- ho includono la logica di conversione nel mio oggetto di dominio, è un problema?
- Dove posso accedere allo
BindingResult
in caso di errore nella stringa?
Utilizzando BeanInfo
posso anche utilizzare un BeanInfo per il mio fagiolo:
public class EntryBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
@Override
PropertyDescriptor tagsDescriptor = new PropertyDescriptor("tags", Entry.class) {
@Override
public PropertyEditor createPropertyEditor(Object bean) {
return new EntryTagListEditor(Integer.class, true);
};
};
// omitting others PropertyDescriptor for this object (for instance name)
return new PropertyDescriptor[] { tagListDescriptor };
}
catch (IntrospectionException ex) {
throw new Error(ex.toString());
}
}
}
E dichiarare un convertitore
public class EntryTagListEditor extends PropertyEditorSupport {
public void setAsText(String text) {
// convert the text to a list of Tag
}
public String getAsText() {
// convert the list of Tag to a String
}
}
Questo approccio ha anche due svantaggi:
- Ho bisogno di modificare il mio BeanInfo ogni volta che aggiungo/cambio la mia classe Entry. o c'è un modo per avere un modo semplice per definire il mio BeanInfo (come "per questa proprietà, utilizzare questo, il resto basta fare come al solito")
- Dove posso accedere alla
BindingResult
in caso di errore nella stringa?
Utilizzando Converter
Converter utilizza il meccanismo generico di Java 5:
final class StringToTagList implements Converter<String, List<Tag>> {
public List<Tag> convert(String source) {
// convert my source to a list of Tag
}
}
Questo approccio sembra più elegante, ma ancora due inconvenienti:
- Sembra che io ridefinire tutti i convertitori predefiniti se configuro questo convertitore nella proprietà di
ConversionServiceFactoryBean
, è c'è un modo per mantenere i convertitori di default? - (di nuovo) Dove posso accedere allo
BindingResult
in caso di errore nella stringa?
Mi spiace essere così lungo, ma questa potrebbe essere una discussione interessante sulla conversione in primavera – Kartoch