2013-08-06 17 views
21

Ich möchte eine benutzerdefinierte registrieren HandlerMethodArgumentResolver, das den folgenden @Controller-Handler-Methode DefinitionSpring MVC @Valid Validierung mit benutzerdefinierten HandlerMethodArgumentResolver

@RequestMapping(method = RequestMethod.POST) 
public String createDomain(@Valid Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) { 

ich meine Resolver registrieren umgehen konnte, die nur einen Parameter Domain Objekt durch Anforderung erzeugt, durch Überschreiben addArgumentResolver() von WebMvcConfigurerAdapter. Wenn Spring versucht, den Domain Parameter aufzulösen, geht es durch seine Liste von HandlerMethodArgumentResolver (es gibt eine Menge) und wählt die erste supports() es.

Im obigen Beispiel, obwohl mein Resolver ein ErrorsMethodArgumentResolver fehl, weil es eine @ModelAttribute erfordert, aufgerufen wird und meine Domain Argument initialisiert erhalten, wurde und wird die @Valid Annotation nicht verarbeitet der Resolver für BindingResult, @RequestBody oder das @RequestPart Argument in der Handler-Methode, die ich nicht habe.

Wenn ich versuche, es zu beheben, indem @ModelAttribute

@RequestMapping(method = RequestMethod.POST) 
public String createDomain(@Valid @ModelAttribute Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) { 

eine HandlerMethodArgumentResolver Implementierung Hinzufügen ModelAttributeMethodProcessor, wird zuerst mit supports() und löst das Argument erhalten geprüft (mit @ModelAttribute und @Valid) vor meinen benutzerdefinierten Resolver. Die BindingResult wird nicht fehlschlagen, aber ich habe nicht mein eigenes Erstellungsverhalten auf der Domain Instanz.

Ich könnte einfach den Code für die Validierung kopieren und einfügen, der in ModelAttributeMethodProcessor ist, aber ich hatte gehofft, es gab einen einfacheren Weg, um meine Parameter zu lösen und Validierung ohne ein Objekt in das Modell hinzuzufügen. Gibt es so einen Weg?

Antwort

8

Schöne Beschreibung des Problems, mit dem Sie konfrontiert sind.

Ich überprüfte den Code, den Sie skizziert haben und zu der gleichen Schlussfolgerung gekommen sind, die Sie haben - es gibt keinen eingebauten Weg, um sowohl eine benutzerdefinierte HandlerMethodArgumentResolver als auch @Valid zugehörige Validierung zur gleichen Zeit angewendet zu haben Die einzige Möglichkeit ist zu tun, was die ModelAttributeMethodProcessor tut, was zu überprüfen ist, ob der Parameter eine @Valid Annotation hat und den Code der Validierungslogik aufrufen.

Sie können wahrscheinlich Ihre HandlerMethodResolverArgumentResolver von ModelAttributeMethodProcessor ableiten und super.validateIfApplicable(..) aufrufen, auf diese Weise wird der vorhandene Code gehebelt.

4

Es ist vielleicht zu spät, aber Ihre HandlerMethodArgumentResolver bekommt WebDataBinderFactory Objekt als letztes Argument, dann die Validierung zu anschließen, einfach diese Implementierung zu Ihrem Resolver hinzuzufügen:

Object resolvedObject = // your logic 
if(parameter.hasParameterAnnotation(Valid.class){ 
      binderFactory.createBinder(webRequest,resolvedObject,"resolvedObjectLogicalName").validate(); 
} 
+0

Sehr sehr effizient. Vielen Dank. – Khodabakhsh

+0

Dies sollte die akzeptierte Antwort sein, da es perfekt funktioniert, ohne von 'HandlerMethodResolverArgumentResolver' abgeleitet werden zu müssen. – msparer

+0

@Alexander Ich versuchte dies, aber es wirft die java.lang.IllegalStateException, d. H. "Ein Fehler/BindingResult Argument wird erwartet, unmittelbar nach dem Modell Attributargument in der Controller-Methode Signatur". – Sankar

Verwandte Themen