2012-04-04 12 views
5

Mvc de la última primavera, utilizando freemarker.Confundido en cuanto a cómo validar la forma mvc de primavera, ¿cuáles son mis opciones?

Esperando que alguien pueda decirme cuáles son mis opciones en términos de validación de un formulario con spring mvc, y cuál es la forma recomendada de hacerlo.

Tengo un formulario que no se asigna directamente a un modelo, tiene campos de entrada que cuando se publiquen, se utilizarán para inicializar 2 objetos modelo que luego necesitaré validar, y si pasan los guardaré. .

Si fallan, quiero volver al formulario, rellenar los valores con lo que el usuario ingresó y mostrar los mensajes de error.

He leído aquí y allá unos 2 métodos, una vez de que he hecho y comprender como funciona:

@RequestMapping(...., method = RequestMethod.POST) 
public ModelAndView myMethod(@Valid MyModel, BindingResult bindingResult) { 
    ModelAndView mav = new ModelAndView("some/view"); 
    mav.addObject("mymodel", myModel); 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

} 

Ahora bien, esto funcionó si mi forma mapea directamente a la forma, pero en mi situación tener:

  1. forman campos que no se asignan a ningún modelo específico, tienen algunas propiedades de 2 modelos.

  2. antes occurrs validación, Necesito crear los 2 modelos de forma manual, establezca los valores del formulario y establezca manualmente algunas propiedades también:

    validar
  3. de llamadas en ambos modelos (Model1, model2), y anexar estos mensajes de error a la colección de errores que necesito devolver a la misma página de vista si las cosas no funcionan.

  4. Cuando el formulario se publica, tengo que hacer algunas llamadas a la base de datos, y en función de esos resultados puede ser necesario agregar mensajes adicionales a la colección de errores.

¿Alguien me puede decir cómo hacer este tipo de validación?

Pseudo código de abajo:

Model1 model1 = new Model1(); 
    Model2 model2 = new Model2(); 

    // manually or somehow automatically set the posted form values to model1 and model2. 

    // set some fields manually, not from posted form 
    model1.setProperty10(GlobalSettings.getDefaultProperty10()); 
    model2.setProperty11(GlobalSettings.getDefaultProperty11()); 

    // db calls, if they fail, add to errors collection 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

    // validation passed, save 
    Model1Service.save(model1); 
    Model2Service.save(model2); 

    redirect to another view 

actualización

he utilizando los JSR 303 anotaciones en mis modelos en este momento, y sería grande si puedo usar los que siguen.

Actualización II

Por favor leer la descripción de recompensas a continuación un resumen de lo que yo estoy buscando.

Respuesta

8

Basado en una experiencia similar, propongo lo siguiente y, por el lado, tengo un comentario sobre el último paso en el enfoque que desea tomar. Uso su lista numerada de pasos.

Paso 1: Formulario de frijol

Hay dos maneras para esto.El enfoque sencillo es definir un bean de formulario (que supongo que ya has hecho):

class MyModel { 
    private Model1 model1; 
    private Model2 model2; 
    // standard Java bean stuff 
} 

Una forma más precisa es definir realmente MyModel tales que sólo tome prestados los campos que requieren de Model1 y Model2 pero No estoy seguro si esto se adapta a tu manera.

Paso 2: Enlace de datos

la primavera hace esto para usted si usted tiene tales form estructura en su opinión:

<form:form modelAttribute="myModel"> 
    <form:input path="model1.somePropertyToBeSet" /> 
</form:form> 

Paso 3: Validación

Usando Spring custom validations, puede definir cust restricciones OM:

@interface Model1Constraint {} 
@interface Model2Constraint {} 

class MyModel1 { 

    @Model1Constraint 
    private Model1 model1; 

    @Model2Constraint 
    private Model2 model2; 

    // ... 

} 

luego registrar sus validadores personalizados para las restricciones personalizadas:

class Model1ConstraintValidator implements ConstraintValidator<Model1Constraint, Model1> { 
// implementation of isValid and initalize 
} 

y lo mismo para Model2Constraint. Con los validadores personalizados, puede verificar qué lógica necesita para asegurarse de que MyModel pase al método de procesamiento de solicitudes. También supongo que ha usado <mvc:annotation-driven /> para que Spring registre los validadores; de lo contrario, debe configurarlos.

Paso 4: Modelo de procesamiento personalizado antes de procesar la solicitud

Su idea original es utilizar algún aglutinante de datos para este trabajo. En su descripción, también menciona que este procesamiento de datos no se basa en en los datos provenientes de los datos del formulario.

En cuanto al diseño y la modularidad, no creo que una carpeta de datos sea un buen lugar para tal fin. En segundo lugar, dado que no hay dependencia de datos con el formulario, la razón principal para usted es permitir el procesamiento de errores de enlace de datos.

Por lo tanto, mi sugerencia es que digamos que ahora estás en public ModelAndView myMethod(@Valid MyModel model, BindingResult bindingResult). Presumiblemente, tiene acceso a otros beans de servicio aquí. Entonces, puede tener un método en algún bean de servicio que pueda refine o prepare (solo nombres) el model que ha llenado en este punto. Basado en excepciones o cualquier otro mecanismo que le convenga, puede usar bindingResult para devolver los errores nuevamente.

Como otra sugerencia, también puede aprovechar Spring interceptors si desea una forma más DI/IoC para hacerlo. Pero de esta manera, debe extraer MyModel del ModelAndView en intercepción y continuar.

Espero que esto ayude.

0

Hibernate Validator 4.2 admite la validación del nivel de método. Puede refactorizar su código un poco para pasar los dos modelos en un método y validarlos.

http://java.dzone.com/articles/method-validation-spring-31

se puede tener algo como esto

public void persistUser(@NotNull @Valid Model1 model1, @NotNull @Valid Model2 model2) { 

     //continue ... 
} 
0

Este es un problema poco común, ya que por lo general tiene más sentido para validar la entrada del usuario, ya que es la información que no puede controlar. Dicho eso, y ya que estoy seguro de que ya lo sabía ...

Una opción sería usar la API de validación JSR 303 directamente para validar los objetos de su modelo una vez que se hayan llenado desde la entrada del usuario, base de datos , etc ..

He aquí un ejemplo:

@RequestMapping(value=...) 
public String myMethod(MyForm form, Model m) { 

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
    Validator validator = factory.getValidator(); 

    Model1 model1 = createModel1FromUserInput(form); 
    Model2 model2 = createModel2FromUserInput(form); 

    Set<ConstraintViolation<?>> modelViolations = validator.validate(model1); 
    modelViolations.add(validator.validate(model2)); 
    if(modelViolations.size() != 0) { 
     m.addAttribute("violations", modelViolations); 
     m.addAttribute("form", myForm); // add the form back to the model so it is populated 
     return "formPage"; 
    } 
    return "successPage"; 
} 

es posible que prefiera para unirse a una BindingResult primavera o una colección de errores. No he probado el siguiente código, y no estoy muy cómodo trabajando directamente con BindingResult, por lo que requieren ajustes:

BindingResult result = ... // not sure about the constructor 
for(ConstraintViolation<?> violation : modelViolations) { 
     result.addError(new ObjectError(violation.getPropertyPath().toString(),violation.getMessage())); 
} 

Si usted está tratando de escupir los errores en la JSP, a continuación, utilizando un Set<ConstraintViolation> puede funcionar lo suficientemente bien como para sus necesidades:

<c:forEach items="${violations}" var="violation"> 
    ${violation.propertyPath}: ${violation.message} <br/> 
</c:forEach> 

Si usted está tratando de utilizar la etiqueta de primavera <form:errors>, tendrá que utilizar el resultado de la unión.

HTH! Avísame si tienes más preguntas. O si me perdí completamente la marca en esta respuesta, intentaré aclarar.

Cuestiones relacionadas