2016-06-01 10 views
3

In meinem Controller habe ich eine Methode wie unten:Wie überprüft man die Argumentwertformatierung vor der Controllermethode?

public QueryResult<TrsAccount> listExclude(String codeAccount, String searchFilter, String order, int pageNumber, 
    int pageSize){} 

Aber bevor Sie diese Methode ausführen ich, wenn chech haben:

Assert.TRUE(codeAccount.matches("^[0-9]{1,20}$")); 

Da dies in meiner Anwendung ist sehr häufig und es ist nicht nur in diesem Fall möchte ich einen allgemeinen Ansatz, um das Argument Format zu überprüfen. So wie ich jetzt bin mit der Verwendung von AOP, in denen:

@Aspect 
public class HijackBeforeMethod { 

@Pointcut("within(@org.springframework.stereotype.Controller *)") 
public void controllerBean() { 
} 

@Pointcut("execution(* *(..))") 
public void methodPointcut() { 
} 

@Before(value = "controllerBean() && methodPointcut()", argNames = "joinPoint") 
public void before(JoinPoint joinPoint) { 

    MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 
    Object[] args = joinPoint.getArgs(); 
    String[] paramNames = signature.getParameterNames(); 
    for (int count = 0; count < paramNames.length; count++) { 
    String tempParam = paramNames[count]; 
    Object tempValue = args[count]; 
    if (tempParam.toLowerCase().equalsIgnoreCase("codeAccount") && Assert.isNotNull(tempValue) 
      && Assert.isNotEmpty((String) tempValue)) { 
     Assert.TRUE(((String) tempValue).matches("^[0-9]{1,20}$")); 
    } 
    } 
} 
} 

Wie Sie sehen können, ist dies sehr rudimentär und fehleranfällig Code-Schnipsel. Gibt es bessere Lösungen?

+0

Nur nicht ... Verwenden Sie ein Objekt und validieren Sie das mit JSR303-Validierung oder einem benutzerdefinierten Validator. –

Antwort

1

Die Verwendung von AOP in Controllern wird nicht wirklich empfohlen. Ein besserer Ansatz wäre to use JSR 303/JSR 349 Bean Validation, aber das würde wahrscheinlich das Umbrechen der Zeichenfolge in einem Wertobjekt erfordern, das dann entsprechend mit Anmerkungen versehen wird.

Wenn Sie mit AOP auf die Lösung dieser bestehen, you'll probably need a ControllerAdvice

+0

Wie kann ich das mit ControllerAdvice machen? Vielen Dank. – Khodabakhsh

0

Genau wie @Sean Patrick Floyd sagte, mit Bean Validation ratsamer ist.

Erstens eine Klasse definieren, die wie von org.springframework.validation.Validator erweitert:

@Component 
public class CodeAccountValidator implements Validator { 

    @Override 
    public boolean supports(Class<?> clazz) { 
     return String.class.equals(clazz); 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     if (Assert.isNotNull(target) && Assert.isNotEmpty((String) target)) { 
      Assert.TRUE(((String) target).matches("^[0-9]{1,20}$")); 
     } 
    } 
} 

Dann fügen Sie @Validated Anmerkung zu Ihrem Controller wie:

public QueryResult<TrsAccount> listExclude(
    @Validated(CodeAccountValidator.class)String codeAccount, 
    String searchFilter, 
    String order, int pageNumber, 
    int pageSize) { 
    ... ... 
} 
+0

Interessant, aber 'CodeAccountValidator' funktioniert nicht. – Khodabakhsh

+0

Kann der Parameter 'codeAccount' @RequestParam Annotation verwenden? – Blank

+0

Vielleicht, aber hier ist es nicht. macht es irgendwelche Unterschiede? – Khodabakhsh

0

Der Versuch, dies mit AOP zu lösen ist etwas, sollten Sie nicht machen. Verwenden Sie stattdessen ein Objekt, um Ihre Eigenschaften zu binden und dieses Objekt zu überprüfen.

public class QueryCriteria { 
    private String codeAccount; 
    private String searchFilter; 
    private int pageNumber; 
    private int pageSize; 
    private String order; 
    // Getters/Setters. 
} 

ändern Sie dann Ihre Controller-Methode

public QueryResult<TrsAccount> listExclude(@Valid QueryCriteria criteria, BIndingResult result) { ... } 

dann entweder einen Frühling Validator die bestätigt, was Sie brauchen.

public QueryCriteriaValidator implements Validator { 

    private final Pattern ACCOUNT_EXPR = Pattern.compile("^[0-9]{1,20}$"); 

    public boolean supports(Class<?> clazz) { 
     return QueryCriteria.isAssignable(clazz); 
    } 

    public void validate(Object target, Errors errors) { 
     final QueryCriteria criteria = (QueryCriteria) target; 
     if (!ACCOUNT_EXPR.matcher(criteria.getCodeAccount()).matches()) { 
      errors.rejectValue("codeAccount", "invalid.format"); 
     } 
    } 
} 

In einem @InitBinder in Ihrem Controller-Methode registrieren diese Prüfung

@InitBinder 
public void initBinder(WebDataBinder binder) { 
    binder.setValidator(new QueryCriteriaValidator()); 
} 

Wenn JSR-303 mit diesem die Sie nicht benötigen und Sie könnten einfach die codeAccount Feld mit dem @Pattern Annotation annotieren.

@Pattern(regexp="^[0-9]{1,20}$") 
private String codeAccount; 

Die Validierung funktioniert gut zusammen mit Spring MVC und Fehlerberichterstattung mit I18N. Anstatt also mit Ausnahmen zu hacken, arbeite ich mit dem Framework.

Ich empfehle ein Lesen der validation section und binding section des Spring Reference Guide.

Verwandte Themen