ConversionService na wiosnę

Stosuję ten schemat w aplikacji wiosennej.

  1. zapytanie jest wysyłane do serwera z identyfikatorem obiektu i kilkoma innymi paramami, które mają być wypełnione w tym obiekcie
  2. obiekt o tym id jest ładowany z bazy danych
  3. gettery i settery są wywoływane w tym obiekcie w celu wypełnienia wartości
  4. 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); 
    }
}
Author: Community, 2010-12-03

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:

  1. napisz konwerter
  2. Zarejestruj konwerter za pomocą ConversionService
  3. 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.

 39
Author: GaryF,
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 .

 4
Author: Ajay,
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