2010-09-11 14 views
19

Intento escribir verificaciones para el play-framework y veo dos posibilidades diferentes. Describí ambos y quiero saber si mi comprensión es correcta (por lo tanto, es más un tutorial que una pregunta, especialmente porque no recibí ninguna respuesta y me perdí algo). Entonces, ¿qué posibilidades hay?Cómo escribir comprobaciones/validación personalizadas para el marco de juego

  1. La forma más sencilla: Ampliación de la clase Check:
    Ventajas: fácil de escribir, más fácil de leer
    Desventajas: No se puede parametrizar el control, sólo se puede definir el mensaje.
  2. La manera avanzada: escribir un cheque basado en OVal AbstractAnnotationCheck.
    Ventajas: Puede parametrizar el cheque y tener una anotación más fácil de usar
    Desventajas: Un poco más complicado.

Antes de echar un vistazo a la implementación, quiero explicar los mensajes. Siempre puede configurar el mensaje directamente o usar una tecla para referir el mensaje en un mensaje-propiedades. El último es la manera más limpia y recomendada. Cada validación obtiene al menos 1 parámetro: el nombre de la propiedad que no es válido. Por lo tanto, los parámetros específicos de validación o verificación siempre se refieren al %i$s donde i> 1. El formato de la cadena del mensaje debe seguir las reglas de Formatter, pero no estoy seguro si todas las características son compatibles. Por lo que sé, solo se admiten% s,% d y% f para crear un posicionamiento. Entonces %[argument_index$][flags]conversion donde la conversión solo podría ser s, d o f.

Vamos a echar un vistazo a dos ejemplos: La forma más sencilla que he usado en mi módulo para el bloqueo optimista:

/** 
* Check with proof if the version of the current edited object is lesser 
* than the version in db. 
* Messagecode: optimisticLocking.modelHasChanged 
* Parameter: 1 the request URL. 
* Example-Message: The object was changed. <a href="%2$s">Reload</a> and do your changes again. 
* 
*/ 
static class OptimisticLockingCheck extends Check { 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    public boolean isSatisfied(Object model, Object optimisiticLockingViolatedValue) { 
     //The comparision of version was made in the setter. Here 
     //we only have to check the flag. 
     if (((VersionedModel) model).optimisiticLockingViolated) { 
      final Request request = Request.current(); 
      //The following doesn't work in 1.0 but in 1.1 see https://bugs.launchpad.net/play/+bug/634719 
      //http://play.lighthouseapp.com/projects/57987-play-framework/tickets/116 
      //setMessage(checkWithCheck.getMessage(), request != null ? request.url : ""); 
      setMessage("optimisticLocking.modelHasChanged", request != null ? request.url : ""); 

     } 
     return !((VersionedModel) model).optimisiticLockingViolated; 
    } 
} 

Se utiliza esta Comprobar con la anotación @CheckWith(value=OptimisticLockingCheck.class, message="optimisticLocking.modelHasChanged")

Así que vamos a echar un vistazo más de cerca cómo funciona. Lo único que tenemos que hacer es extender la clase play.data.validation. Verificar y sobrescribir el método isSatisfied. Allí obtienes tu modelo y el valor de las propiedades. Todo lo que tienes que hacer es regresar verdadero si todo está bien o falso de lo contrario. En nuestro caso, queremos establecer la url actual como un parámetro. Este se puede hacer fácilmente llamando a setMessage(). Le damos el mensaje o la clave de mensaje que se define en las propiedades de los mensajes y los parámetros. Recuerde que solo proporcionamos 1 parámetro, pero nos referimos a% 2 $ s, ya que el primer parámetro siempre es el nombre de la propiedad.

Ahora el complejo camino basado en el rango de comprobación de juego: Primero tenemos que definir una anotación

/** 
* This field must be lower than and greater than. 
* Message key: validation.range 
* $1: field name 
* $2: min reference value 
* $3: max reference value 
*/ 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.FIELD, ElementType.PARAMETER}) 
@Constraint(checkWith = RangeCheck.class) 
public @interface Range { 

    String message() default RangeCheck.mes; 
    double min() default Double.MIN_VALUE; 
    double max() default Double.MAX_VALUE; 
} 

y luego el Registro

@SuppressWarnings("serial") 
public class RangeCheck extends AbstractAnnotationCheck<Range> { 

    final static String mes = "validation.range"; 

    double min; 
    double max; 

    @Override 
    public void configure(Range range) { 
     this.min = range.min(); 
     this.max = range.max(); 
     setMessage(range.message()); 
    } 

    public boolean isSatisfied(Object validatedObject, Object value, OValContext context, Validator validator) { 
     requireMessageVariablesRecreation(); 
     if (value == null) { 
      return true; 
     } 
     if (value instanceof String) { 
      try { 
       double v = Double.parseDouble(value.toString()); 
       return v >= min && v <= max; 
      } catch (Exception e) { 
       return false; 
      } 
     } 
     if (value instanceof Number) { 
      try { 
       return ((Number) value).doubleValue() >= min && ((Number) value).doubleValue() <= max; 
      } catch (Exception e) { 
       return false; 
      } 
     } 
     return false; 
    } 

    @Override 
    public Map<String, String> createMessageVariables() { 
     Map<String, String> messageVariables = new TreeMap<String, String>(); 
     messageVariables.put("2-min", Double.toString(min)); 
     messageVariables.put("3-max", Double.toString(max)); 
     return messageVariables; 
    } 

} 

bien creo que la anotación Don' t debe ser explicado. Vamos a ver el cheque. En este caso, se extiende a net.sf.oval.configuration.annotation.AbstractAnnotationCheck. Tenemos que escribir un método de configuración donde obtenemos la anotación y podemos copiar los parámetros. Entonces tenemos que definir nuestro cheque. Que es análogo a la implementación del otro cheque. Entonces solo escribimos nuestra condición y devolvemos verdadero o falso, ¡excepto una línea especial! Si utilizamos un mensaje parametrizado, debemos llamar al requireMessageVariablesRecreation(); en nuestro método. Al menos debemos anular el método createMessageVariables. Aquí tenemos que obtener un littlebit play-knowlegde (todas las demás cosas se describen here).Coloca sus mensajes en un mapa con una clave y un valor, pero jugar solo toma los valores (vea ValidCheck.java en el código de la estructura). Por lo tanto, se hará referencia por posición. Esta es la razón por la que cambié la implementación de RangeCheck usando TreeMap en lugar de HashMap. Además, dejo que las teclas comiencen con el índice al que pueden referirse.

Así que espero que esto aclare más cómo escribir validaciones/verificaciones personalizadas para jugar. Espero que la descripción sea correcta. Por lo tanto, la pregunta es mi comprensión correcta?

+11

¿De qué demonios estás hablando? – user359996

+2

Cómo escribir controles personalizados/validación en el juego. El juego es un marco que puedes encontrar aquí http://www.playframework.org. No entiendo lo que no está claro para ti. – niels

+1

@niels Si funciona en la práctica de la manera en que lo espera, entonces, um, sí, su comprensión es probablemente correcta. –

Respuesta

1

Al menos su primer ejemplo parece estar en la ruta correcta. Puede compararlo con la documentación que se proporciona a continuación, pero asumo por la complejidad de su ejemplo que ya se ha referido a él.

http://www.playframework.org/documentation/1.1/validation#custom

no sé lo suficiente sobre el marco juego a comentar sobre el segundo ejemplo.

+0

Explicación adicional aquí: http://www.playframework.org/documentation/1.2.3/validation#custom – Allan

Cuestiones relacionadas