ConversionService na wiosnę
Stosuję ten schemat w aplikacji wiosennej.
- zapytanie jest wysyłane do serwera z identyfikatorem obiektu i kilkoma innymi paramami, które mają być wypełnione w tym obiekcie
- obiekt o tym id jest ładowany z bazy danych
- gettery i settery są wywoływane w tym obiekcie w celu wypełnienia wartości
- obiekt jest następnie przechowywany
Zadałem w inne pytanie jaki był najlepszy sposób przygotowania obiektu przed wypełnieniem param Prośba. Odpowiedź brzmiała, że najlepszym sposobem było użycie usługi konwersji zamiast robić to w metodzie z adnotacjami @ModelAtribute lub z edytorem w initbinderze.
Więc próbowałem użyć konwertera, ale nie znalazłem podobnego przykładu i jestem trochę zablokowany. Napisałem kod podobny do poniższego: w segregatorze init rejestruję usługę konwersji. Więc przed wypełnieniem wartości na obiekcie użytkownika metoda convert() jest wywoływana w celu załadowania obiektu z baza danych. Problem polega na tym, że ta konfiguracja nie działa, ponieważ konwertuje id (pole username) Użytkownika obiektu na użytkownika obiektu, ale potem próbuje utworzyć setusername () z obiektem, więc dostaję "java.lang.IllegalArgumentException: argument type mismatch".
Czy ktoś może mi podać wskazówkę lub przykład sposobu korzystania z usługi ConversionService, aby uzyskać pożądane zachowanie? Dzięki.@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) {
...
}
Z czymś w rodzaju:
@Component
public class UserConversionService implements ConversionService{
...
@Override
public Object convert(Object name, TypeDescriptor arg1, TypeDescriptor arg2) {
return userService.find((String)name);
}
}
2 answers
Próbujesz zaimplementować ConversionService
do konwersji między łańcuchami znaków i obiektami użytkownika. Jednak to implementacje Converter
wykonują tę część. Co chcesz zrobić to:
- napisz konwerter
- Zarejestruj konwerter za pomocą ConversionService
- skorzystaj z usługi ConversionService.
Twój konwerter będzie podobny do:
final class UserConverter implements Converter<String, User> {
...
public User convert(String username) {
return userService.find(username);
}
}
Następnie musisz zarejestrować ten konwerter. Możesz napisać własny ConversionServiceFactoryBean lub zastąp domyślną wartość:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="example.UserConverter"/>
</list>
</property>
</bean>
Jeśli chcesz używać usługi conversionservice jawnie, tak jak to zrobiłeś, po prostu zostaw ją jako coś, co może być autowirowane. Wiosna i ta definicja factorybean zajmie się resztą.
Jeśli jednak używasz już znacznika <mvc:annotation-driven>
w swoim kontekście, możesz użyć jego atrybutu conversion-service
, aby odwołać się do conversionservicefactorybean. Nie musisz wtedy mieć w swojej klasie Initbindera ani ConversionService: po prostu mając parametr @ RequestMapping miej swój typ Docelowy, użytkownik, konwersja odbędzie się bez konieczności interwencji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-03 23:36:16
Zrobiłem dokładnie to, co Gary mówi powyżej i zadziałało:
Chcę dodać więcej informacji do rozwiązania. Zgodnie z dokumentacją Spring tutaj zmienna szablonu URI jest tłumaczona na obiekt docelowy za pomocą Converter / ConversionService. Próbowałem użyć @RequestParam("id") @ModelAttribute("contact") Contact contact
, ale otrzymałem IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute
za brak obiektu Modelu contact
w moim widoku edit.jsp. Można to łatwo rozwiązać deklarując Model model
i model.addAttribute(contact);
. Jest jednak jeszcze lepszy sposób; korzystanie z Zmienna szablonu URI. To dziwne, dlaczego nie zadziałało.
NIE DZIAŁA
@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";
}
CO ZADZIAŁAŁO
@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";
}
Więc co to robi.. łącze takie jak ...edit/1
domyślnie wywołuje konwerter Dla ciągu znaków " 1 "do kontaktu konwersji id" 1 " i przenosi ten obiekt kontaktu do widoku.
Nie ma potrzeby stosowania @InitBinder
, a ponieważ jest to Converter
zarejestrowany w ConversionService
, mogę używać tego wszędzie tam, gdzie chcę - w sposób dorozumiany lub jawny .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:53:17