Validierung generischer Parameter in Federreglern

Bild
Wir alle schreiben oft einfache Methoden in Steuerungen, die mit numerischen Bezeichnern arbeiten.

@RequestMapping(value = {"/entityName/{entityId}/get"}, method = RequestMethod.GET) @ResponseBody public Entity get(@PathVariable(value = "entityId") Integer entityId) { //    ID } 

Die eingehende ID muss validiert werden. Beispielsweise haben nicht alle Benutzer Zugriff auf alle IDs.

Es versteht sich, dass die Verwendung von UUIDs sicherer und zuverlässiger ist. Es muss jedoch erstellt, gespeichert, indiziert usw. werden. Für alle Unternehmen ist dies langwierig und schwierig. In vielen Fällen ist es einfacher, mit regulären numerischen IDs zu arbeiten.

Die Validierung kann auf einfache Weise erfolgen:

  @RequestMapping(value = {"/entityName/{entityId}/get"}, method = RequestMethod.GET) @ResponseBody public Entity get(@PathVariable(value = "entityId") Integer entityId) { if(!@dao.validate(entityId)) return some_error; //    ID } 

Diese Lösung enthält nur ein Plus. Einfach und schnell.
Alles andere ist schlecht. Codeduplizierung, Validierung ist nicht mit Objektvalidierung kompatibel, eine separate Verarbeitung in jeder Methode ist erforderlich.

Ich möchte das tun:

  @RequestMapping(value = {"/entityName/{entityId}/get"}, method = RequestMethod.GET) @ResponseBody public Entity get(@Validated @PathVariable(value = "entityId") Integer entityId) { //    ID } 

Diese einfache und logische Option funktioniert nicht. Der Validator wird einfach nicht aufgerufen. Die Validierung von PathVariable durch Spring wird nicht unterstützt.

Damit diese Option funktioniert, müssen Sie PathVariable in ModelAttribute umwandeln:

 @ModelAttribute private Integer integerAsModelAttribute(@PathVariable("entityId") Integer id) { return id; } 

Und beim Zugriff auf den Controller wird eine Fehlermeldung angezeigt. Die Wrapper generischer Typen haben keinen Standardkonstruktor ohne Parameter und es gibt keinen Setter. Dies wird mit Optional umgangen. Er hat sowohl einen Standardkonstruktor als auch einen Setter, der gewöhnliche Ints akzeptiert.

Ganzzahl in Optional umwandeln:

 @ModelAttribute private Integer integerAsModelAttribute(@PathVariable("entityId") Optional<Integer> id) { return id.orElse(null); } 

Und dementsprechend die Controller-Methode selbst und die Validator-Deklaration:

 @InitBinder({"entityId"}) protected void initCommissionIdBinder(WebDataBinder binder) { binder.setValidator(validateEntityIdValidator); binder.setBindEmptyMultipartFiles(false); } @RequestMapping(value = {"/entityName/{entityId}/get"}, method = RequestMethod.GET) @ResponseBody public Entity get(@Validated @ModelAttribute(value = "entityId") Integer entityId) { //    ID.   . } 

Die Validator-Klasse ist absolut normal:

 public class ValidateIntegerValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Integer.class.equals(aClass); } @Override public void validate(Object o, Errors errors) { if(o instanceof Integer) { Integer integer = (Integer) o; if(!dao.checkId(integer)) { errors.reject("-1", "ERROR"); } } else { errors.reject("-2","WRONG TYPE"); } } } 

Ein vollständiges Arbeitsbeispiel finden Sie hier .

Source: https://habr.com/ru/post/de425001/


All Articles