如果将String转换为一组对象,最好的Spring转换策略是什么? [英] What are the best Spring converter strategies in the case of a String to convert to a set of object?

查看:54
本文介绍了如果将String转换为一组对象,最好的Spring转换策略是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的一种视图中,我具有以下(简化的)形式:

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

将绑定到以下JavaBean:

 公共类条目{
private字符串名称;
私人列表< Tag>标签=新的LinkedList< Tag>();

//省略了setter和getters
}

要使用Spring 3的所有新功能,我正在使用注释驱动的控制器来接收POST请求:

  @Controller 
@RequestMapping( / entry)
公共类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){
//从绑定结果中检查验证
//在bean上执行方法:将此条目添加到系统中
//返回正确的视图
}
}

如您所见,我需要转换输入文本(看起来像 tag1,tag2,tag3 )作为Tag列表,定义如下:

 公共类标记{
专用字串名称;

//省略了setter和getter
}

有在Spring 3.0中,有几种策略可以做到这一点:



很长的帖子,问题都用粗体显示

b $ b

最简单的



对新属性 tagsAsText 进行编程以使getter / setter作为String:

 公共类条目{
// ...

public void setTagsAsText(String标签){
//将文本转换为标签列表
}

public String getTagsAsText(){
//将标签列表转换为文本
}
}

此方法有两个缺点:




  • 我在域对象中包含了转换逻辑,这是一个问题吗?

  • < b>如果字符串错误,我在哪里可以访问 BindingResult



使用BeanInfo



我也可以将BeanInfo用于bean:

 公共类EntryBeanInfo扩展了SimpleBeanInfo {

public PropertyDescriptor [] getPropertyDescriptors(){
试试{
@Override
PropertyDescriptor tagsDescriptor = new PropertyDescriptor( tags,Entry.class){
@Override
public PropertyEditor createPropertyEditor(Object bean){
返回新的EntryTagListEditor(Integer.class,true);
};
};
//为此对象省略其他PropertyDescriptor(例如名称)
返回new PropertyDescriptor [] {tagListDescriptor};
}
catch(IntrospectionException ex){
throw new Error(ex.toString());
}
}
}

并声明一个转换器

 公共类EntryTagListEditor扩展PropertyEditorSupport {

public void setAsText(String text){
//将文本转换为标签
的列表}

public String getAsText(){
//将标签列表转换为字符串
}
}

此方法也有两个缺点:




  • 每次添加/更改Entry类时,我都需要编辑BeanInfo。或者有什么方法可以定义我的BeanInfo(例如为此属性使用此属性,否则只需照常操作

  • 如果字符串出错,我在哪里可以访问 BindingResult



使用转换器



转换器使用Java 5的通用机制:

 最终类StringToTagList实现Converter< String,List< Tag>>。 {
public List< Tag> convert(String source){
//将我的源代码转换为标签
的列表}
}

这种方法看起来更优雅,但仍然存在两个缺点:




  • 似乎我重新定义了所有默认值转换器,如果我在 ConversionServiceFactoryBean 的属性中配置此转换器,是否可以保留默认转换器?

  • (再次)如果字符串中有错误,我在哪里可以访问 BindingResult


解决方案

一个经过深思熟虑的问题,即使这样也会吓到大多数人:)



无论如何,我认为选项(2)最接近实际解决方案。我的第一个建议是将标签列表封装到其自己的模型类中。这将为数据绑定框架提供一个要注册的具体类型,而 List String 太笼统了。 / p>

因此您将拥有模型类:

 公共类条目{ 
私有字符串名称;
private TagList tagList;
}


公共类TagList {

private final List< Tag>标签;

public TagList(List< Tag>标签){
this.tags =标签;
}

公共列表< Tag> getTags(){
返回标签;
}
}

然后您有一个 PropertyEditor 知道如何与 TagList进行转换

 公共类TagListEditor扩展PropertyEditorSupport {

@Override
public void setAsText(String text)throws IllegalArgumentException {
TagList tagList = //从文本值解析
setValue(tagList);
}

@Override
public String getAsText(){
TagList tagList =(TagList)getValue();
return tagList.toString(); //或其他
}
}

最后,您需要告诉控制器以使用转换器:

  @Controller 
公共类EntryController {

@ InitBinder
public void initBinder(WebDataBinder粘结剂){
inder.registerCustomEditor(TagList.class,new TagListEditor());
}

//在此处请求映射
}

我相当确定新的Spring 3 Converter框架会产生一个更优雅的解决方案,但我还没有弄清楚:)但是,这种方法我知道有效。


I have the following (simplified) form in one of my view:

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

Which is going to be bind to the following JavaBean:

public class Entry {
  private String name;
  private List<Tag> tags = new LinkedList<Tag>();

  // setters and getters omitted
}

because I want to take use all new fancy features of Spring 3, I'm using annotation-driven controller to receive the POST request:

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

As you can see, I need to convert my input text (which look like tag1, tag2, tag3) as a list of Tag, define like this:

public class Tag {
  private String name;

  // setter and getter omitted
}

There is several strategies to do this with Spring 3.0:

(Sorry long post, questions are in bold)

The simplest

Programming a new property tagsAsText to have a getter/setter as 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
  }
}

This approach has two drawbacks:

  • I include the conversion logic in my domain object, is it a problem ?
  • Where can i access to the BindingResult in the case of error in the string ?

Using BeanInfo

I can also use a BeanInfo for my bean:

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

And declare one converter

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

This approach has also two drawbacks:

  • I need to edit my BeanInfo every time I add / change my Entry class. or is there any way to have a simple way to define my BeanInfo (like "for this property, use this, else just do as usual")
  • Where can i access to the BindingResult in the case of error in the string ?

Using Converter

Converter uses the generic mechanism of Java 5:

final class StringToTagList implements Converter<String, List<Tag>> {
  public List<Tag> convert(String source) {
    // convert my source to a list of Tag
  }
}

This approach looks more elegant but still two drawbacks:

  • It seems I redefine all default Converters if I configure this converter in the Property of ConversionServiceFactoryBean, is there any way to keep the default Converters ?
  • (again) Where can i access to the BindingResult in the case of error in the string ?

解决方案

A well-considered question, even it'll scare most people off :)

Anyway, I think option (2) is the closest to a practical solution. My first suggestion is that you encapsulate the list of tags into its own model class. This will give the data binding framework a concrete type to register against, whereas List and String are much too general.

So you would have the model classes:

public class Entry {
  private String name;
  private TagList tagList;
}


public class TagList {

   private final List<Tag> tags;

   public TagList(List<Tag> tags) {
      this.tags = tags;
   }

   public List<Tag> getTags() {
      return tags;
   }
}

You then have a PropertyEditor that knows how to convert to and from a TagList:

public class TagListEditor extends PropertyEditorSupport {

   @Override
   public void setAsText(String text) throws IllegalArgumentException {
      TagList tagList = // parse from the text value
      setValue(tagList);
   }

   @Override
   public String getAsText() {
      TagList tagList = (TagList) getValue();
      return tagList.toString(); // or whatever
   }
}

And finally, you need to tell the controller to use the converter:

@Controller
public class EntryController {

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

   // request mappings here
}

I'm fairly sure the new Spring 3 Converter framework would produce a more elegant solution, but I haven't figured it out yet :) This approach, however, I know works.

这篇关于如果将String转换为一组对象,最好的Spring转换策略是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆