Подтвердить что ты не робот

ConversionService в Spring

Я следую этой схеме в приложении Spring.

  • Запрос отправляется на сервер с идентификатором объекта и некоторыми другими параметрами, которые будут заполнены в этом объекте
  • Объект с этим идентификатором загружается из базы данных
  • getters и seters вызывается в этом объекте для заполнения значений
  • объект затем сохраняется

Я спросил в этом другом вопросе, что было лучшим способом подготовить объект перед заполнением параметров запроса. Ответ заключался в том, что лучшим способом было использовать службу преобразования вместо того, чтобы делать это в аннотированном методе @ModelAtribute или с редактором в initBinder,

Итак, я попытался использовать конвертер, но я не нашел подобного примера, и я немного застрял. Я написал код, подобный приведенному ниже: В связывании init я регистрирую службу преобразования. Поэтому перед заполнением значений метода User object convert() вызывается для загрузки объекта из базы данных. Проблема заключается в том, что эта конфигурация не работает, потому что она преобразует идентификатор (имя пользователя) объекта Object в пользователя Object, но затем он пытается создать setUsername() с объектом, поэтому я получаю "java.lang.IllegalArgumentException: несоответствие типа аргументов".

Может ли кто-нибудь дать мне подсказку или пример способа использования ConversionService для получения желаемого поведения?

Спасибо.

@Autowired
private ConversionService conversionService;

@InitBinder("user")
public void initBinder(@RequestParam("username")String username, WebDataBinder binder){
    binder.setConversionService(conversionService);
}

@RequestMapping(value="/user/save", method=RequestMethod.POST)
public String save(@ModelAttribute("user") User user, Model model) {        
    ...
}

с чем-то вроде:

@Component
public class UserConversionService implements ConversionService{
    ...        
    @Override
    public Object convert(Object name, TypeDescriptor arg1, TypeDescriptor arg2) {
        return userService.find((String)name); 
    }
}
4b9b3361

Ответ 1

Вы пытаетесь реализовать ConversionService для преобразования между объектами Strings и User. Тем не менее, это Converter реализации, которые выполняют эту роль. Что вы хотите сделать:

  • Записать конвертер
  • Зарегистрируйте этот конвертер с помощью ConversionService
  • Используйте ConversionService.

Ваш конвертер будет примерно таким:

final class UserConverter implements Converter<String, User> {
    ...
    public User convert(String username) {
        return userService.find(username);
    }

}

Затем вам необходимо зарегистрировать этот конвертер. Вы можете либо написать свой собственный ConversionServiceFactoryBean, либо переопределить значение по умолчанию:

<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="example.UserConverter"/>
        </list>
    </property>
</bean>

Если вы хотите явно использовать ConversionService, как и у вас, просто оставьте его как что-то, что можно сделать autwired. Spring, и это определение фабрики позаботится об остальном.

Если, однако, вы уже используете тег <mvc:annotation-driven> в своем контексте, вы можете использовать его атрибут conversion-service для ссылки на свой ConversionServiceFactoryBean. Вам тогда не нужно иметь InitBinder или ConversionService в вашем классе вообще: просто имея параметр @RequestMapping, ваш целевой тип, Пользователь, преобразование будет выполнено без вмешательства.

Ответ 2

Я сделал то, что Гэри говорит выше, и это сработало:

Я хочу добавить дополнительную информацию в решение. В соответствии с Spring документацией здесь переменная шаблона URI переходит к целевому объекту с помощью программы Converter/ConversionService. Я попытался использовать @RequestParam("id") @ModelAttribute("contact") Contact contact, но я получил IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute для того, чтобы не иметь объект модели contact в моем представлении edit.jsp. Это можно легко решить, объявив a Model model и model.addAttribute(contact);. Однако есть еще лучший способ; используя переменную шаблона URI. Странно, почему @RequestParam не работает.

НЕ РАБОТАЕТ

@RequestMapping("edit") //Passing id as .. edit?id=1
public String editWithConverter(@RequestParam("id") @ModelAttribute("contact") Contact contact){
    logger.info("edit with converter");
     return "contact/edit";
}

ЧТО РАБОТАЕТ

@RequestMapping("edit/{contact}") //Passing id as .. edit/1
public String editWithConverter(@PathVariable("contact") @ModelAttribute("contact") Contact contact){ // STS gave a warning for using {contact} without @PathVariable 
    logger.info("edit with converter");
     return "contact/edit";
}

Итак, что делает эта вещь.. ссылка вроде ...edit/1 неявно вызывает преобразователь для преобразования String '1' в Contact id '1' и приносит этот контактный объект в представление. Нет необходимости в @InitBinder, и поскольку его a Converter, зарегистрированный с помощью ConversionService, я могу использовать эту везде, где хочу - неявно или явно.