输入字段的Spring Formatter

时间:2014-12-10 12:48:08

标签: java spring spring-boot thymeleaf formatter

我对Spring中的格式化程序有疑问。

我的选择框有一个Formatter,例如:

public class SportTypeFormatter implements Formatter<SportType> {

    @Autowired
    private SportTypeRepository sportTypeRepository;

    @Override
    public String print(SportType sportType, Locale locale) {
        return String.valueOf(sportType.getTypeId());
    }

    @Override
    public SportType parse(String sportTypeId, Locale locale) throws ParseException {
        return sportTypeRepository.findSportTypeByTypeId(Long.valueOf(sportTypeId));
    }
}
在百里香的像这样:

<select class="form-control" name="sportTypeId" th:field="*{person.sport.sportType}">
    <option th:each="spoType : ${allSportTypes}" th:value="${spoType.typeId}" th:selected="${spoType.typeId == person.sport.sportType}" th:text="#{${'login.sport.sportType.' + spo.typeId}}" >Sporttype</option>
</select>

这很简单,因为我只需要一个值(id),而且我会选择选择框。

但是,如果我需要两个值,那该怎么办?

建议我有电子邮件,我需要id和值(邮件地址)。我可以为电子邮件构建Formatter,但我没有机会同时传输电子邮件和id。

在打印方法中我可以这样:

@Override
public String print(Email email, Locale locale) {
    return email.getId() + email.getEmail();
}
在百里香中

<input id="email" type="text" class="form-control" th:field="*{{person.email}}" th:placeholder="#{login.email}" />

但是用户可以看到id。

如果我执行绑定“标准”Spring方式,我会得到以下异常(这就是我使用格式化程序的原因):

{timestamp=Wed Dec 10 11:14:47 CET 2014, status=400, error=Bad Request, exception=org.springframework.validation.BindException, 
 errors=[Field error in object 'person' on field 'email': rejected value [com.sample.persistence.user.model.Email@0]; 
 codes [typeMismatch.person.email,typeMismatch.person.institutionEmployees.email,
        typeMismatch.email,typeMismatch.email,
        typeMismatch.email,typeMismatch.com.sample.persistence.user.model.Email,typeMismatch]; 
 arguments [org.springframework.context.support.DefaultMessageSourceResolvable: 
            codes [person.email,email]; 
            arguments []; 
            default message [email]]; 
            default message [Failed to convert property value of type 'com.sample.persistence.user.model.Email' 
                             to required type 'com.sample.persistence.user.model.Email' 
                             for property 'email'; 
                             nested exception is org.springframework.core.convert.ConversionFailedException: 
                             Failed to convert from type com.sample.persistence.user.model.Email 
                             to type @javax.persistence.OneToOne @javax.persistence.JoinColumn @com.google.gson.annotations.Expose 
                                     com.sample.persistence.user.model.Email for value 
                                     'com.sample.persistence.user.model.Email@0'; 
                            nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: 
                                     Provided id of the wrong type for class com.sample.persistence.user.model.Email. 
                                     Expected: class java.lang.Long, got class java.lang.String; 
                            nested exception is java.lang.IllegalArgumentException: 
                                     Provided id of the wrong type for class com.sample.persistence.user.model.Email. 
                                     Expected: class java.lang.Long, got class java.lang.String]], 
                                     message=Validation failed for object='person'. Error count: 1, path=/manageUsers/Ab-Soul/edit}

欢迎任何建议。

提前致谢。

1。编辑:

控制器方法

@RequestMapping(value = "/{login}/edit", method = RequestMethod.GET)
public ModelAndView editUserByLogin(@PathVariable("login") final String login) {
    final User currentUser = UserRepository.findPersonByLogin(login);

    ModelAndView mav = new ModelAndView(URL_EDIT_USER);
    mav.addObject(MODEL_USER, currentUser);

    return mav;
}

该场景,'admin'获取所有当前用户的列表,如果他点击该表,将使用他点击的用户的名称调用requestmapping-method。

电子邮件类:

@Entity(name="Email")
public class Email implements Serializable
{
    private static final long serialVersionUID = 6891079722082340011L;

    @Id()
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Expose
    protected Long emailId;
    @Expose
    protected String value;

    //getter/setter

    @Override
    public boolean equals(Object obj)
    {
        if(obj instanceof Email){
            return value.equals(((Email) obj).getValue());
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        return value.hashCode();
    }
}

2。编辑:

现在我已将child的电子邮件字段更改为emailChild

org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'person' on field 'child[0].emailChild': 
rejected value [com.sample.persistence.user.model.Email@0]; 
codes [typeMismatch.person.child[0].emailChild,
       typeMismatch.person.child.emailChild,
       typeMismatch.child[0].emailChild,
       typeMismatch.child.emailChild,
       typeMismatch.emailChild,
       typeMismatch.com.sample.persistence.user.model.Email,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: 
    codes [person.child[0].emailChild,child[0].emailChild]; 
arguments []; 
default message [child[0].emailChild]]; 
default message [Failed to convert property value of type 'com.sample.persistence.user.model.Email' to required type 'com.sample.persistence.user.model.Email' 
       for property 'child[0].emailChild'; 
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type com.sample.persistence.user.model.Email
to type @javax.persistence.OneToOne @javax.persistence.JoinColumn @com.google.gson.annotations.Expose com.sample.persistence.user.model.Email 
for value 'com.sample.persistence.user.model.Email@0'; 
nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Provided id of the wrong type for class com.sample.persistence.user.model.Email. Expected: class java.lang.Long, got class java.lang.String; 
nested exception is java.lang.IllegalArgumentException: Provided id of the wrong type for class com.sample.persistence.user.model.Email. Expected: class java.lang.Long, got class java.lang.String]

第3。编辑:

为帖子添加控制器方法:

@RequestMapping(value = "/{login}/edit", method = RequestMethod.POST)
public ModelAndView updateUser(@PathVariable("login") final String login, @ModelAttribute(MODEL_USER) final Person person, BindingResult bindingResult,  final Model model) {
    Person repositoryPerson = personRepository.findPersonByLogin(login);

    repositoryPerson = repositoryPerson.updateWith(person);
    manageUserService.updatePerson(repositoryPerson);

    model.asMap().clear();
    return new ModelAndView("redirect:" + URL_USERS_OVERVIEW, MODEL, model);
}

1 个答案:

答案 0 :(得分:0)

我已经回答了我自己的问题。

我们应该记住

  • 注册过程正常,它会很好地绑定

编辑过程只发生问题,因此我在数据库中有一个有效的电子邮件对象,使用有效的子对象绑定,并使用有效的用户对象进行绑定。

我决定使用以下实现构建EmailFormatter

public class EmailFormatter implements Formatter<Email> {

    @Override
    public String print(Email email, Locale locale) {
        return email.getValue();
    }

    @Override
    public Email parse(String mailAddress, Locale locale) throws ParseException {
        return new Email(mailAddress);
    }

}

有了这个,我在我的Child-Instance中获得了一个新的Email-Object(没有id)。现在我在有效的子对象中有一个有效的电子邮件对象。看一下后方法:

@RequestMapping(value = "/{login}/edit", method = RequestMethod.POST)
public ModelAndView updateUser(@PathVariable("login") final String login, @ModelAttribute(MODEL_USER) final Person person, BindingResult bindingResult,  final Model model) {
    Person repositoryPerson = personRepository.findPersonByLogin(login);

    repositoryPerson = repositoryPerson.updateWith(person);
    manageUserService.updatePerson(repositoryPerson);

    model.asMap().clear();
    return new ModelAndView("redirect:" + URL_USERS_OVERVIEW, MODEL, model);
}

此时我有来自用户的登录名,我得到了#34; old&#34;来自db的(有效)user-Object。我写了一个&#34; merge&#34;方法,我给'老'&#34; user对象修改后的用户对象。

在这里,我可以获取带有ID的旧电子邮件对象,并将电子邮件地址设置为:

this.emailChild.setValue(modifiedChild.getemailChild().getValue());

在此之后我看看这个解决方案,我注意到这很简单。

但是如果绑定问题是由一个&#34;复杂的&#34; (然后,多一个相关领域)对象,我认为,你会更好地解决PatrickLC建议的解决方案:

@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
    dataBinder.setDisallowedFields("emailId");
}