1

所以我们使用的可能是相当老的 Spring 属性转换方式。基本上,当页面加载时,它会将实体对象转换为其 id 值,然后当页面提交时,它会获取 id 值,通过该 id 查找实体对象并将其填充回来。

示例如下;

import org.springframework.binding.convert.converters.StringToObject;

public class StringToExamVO extends StringToObject {

    private VerifyService verifyService;

    public StringToExamVO(VerifyService verifyService) {
        super(ExamVO.class);
        this.verifyService = verifyService;
    }

    @Override
    public String toString(Object object) {
        ExamVO spec = (ExamVO) object;
        return (spec != null && spec.getId() != null ? spec.getId().toString() : null);
    }

    @Override
    public Object toObject(String string, Class targetClass) {
        if (string != null && string.length() > 0 && targetClass.equals(ExamVO.class)) {
            String id = StringUtils.trimToNull(string);
            return verifyService.loadExam(Integer.decode(id));
        }
        return null;
    }
}

现在,如果我们的表单支持命令具有单个实体属性,这将非常有用;

private ExamVO exam;

public void setExam(ExamVO exam) {
  this.exam = exam;
}

public ExamVO getExam() {
  return this.exam;
}

但是,如果属性是实体的列表,它似乎不起作用,例如;

private List<ExamVO> exams;

public void setExams(List<ExamVO>exam) {
  this.exams = exams;
}

public List<ExamVO> getExams() {
  return this.exams;
}

通过单一属性类型的调试器(第一个示例),我可以看到 toString 和 toObject 分别在页面加载和页面提交时被调用。

但是,当属性是 LIST 时进行调试,只会调用 toString(重复地因为它是一个列表)。在页面提交时,没有调用 toObject,这意味着我猜它甚至没有尝试将字符串 id 转换回实体对象。

在列表属性 getter 中放置一个断点getExams我什至可以看到,尽管列表被定义为在其索引槽中List<ExamVO>ExamVO对象被覆盖Strings

Spring 转换框架是否无法检测到,因为它填充了一个then 它可能应该为每个插槽List<ExamVO>调用转换器的 toObject 方法?StringToExamVO

4

1 回答 1

0

再想一想,关于我在底部的问题,基本上是这样的;

“Spring可以检测到它填充一个列表,即具有泛型类型的列表,因此调用转换器将字符串转换为ExamVO泛型类型”

我相信答案是否定的,因为泛型类型在运行时被剥离了。所以在运行时 List 只是一个没有类型的 List,这就是为什么 Spring 可以将 Strings 插入其中而不是 ExamVOs 的原因,也是为什么不调用转换服务的原因,因为没有通用类型,框架不知道该列表假设包含 ExamVO。

我现在已经改变了我的代码的工作方式,但做了以下想法的简单玩具;

@SuppressWarnings("unchecked")
public List<ExamVO> getExams() {
    if(Exams == null) {
        exams = new ArrayList() {

            @Override
            public ExamVO set(int index, Object element) {
                // TODO if element is a String, 
                // call the verifyService.loadExam(Integer.decode(element));
                // to get the ExamVO and set that to element
                return (ExamVO)super.set(index, element);
            }
        };
    }
    return exams;
}

这在理论上是可行的,但是从命令/表单支持对象调用服务层对我来说似乎很不确定。

于 2013-03-01T10:30:32.150 回答