-Ich implementiere Validation in Spring Framework, aber ich möchte das Ergebnis von BindingResult filtern! ・ Ich möchte ein gemeinsames Formular für neue und aktualisierte verwenden!
View
Durch einfaches Verwenden des Spring-Tags wird userForm in modelAttribute definiert und das Eingabe-Tag und das Label-Tag werden geschrieben. Die Update-Seite hat genau die gleiche Struktur.
Form
UserForm.java
@Data
@ConfirmMail(field = "mail", groups = MailGroup3.class)
@ConfirmPassword(field = "password", groups = PasswordGroup4.class)
@CheckBirthday(field = "birthday", groups = ValidGroup2.class)
public class UserForm {
private String id;
@NotBlank(groups = ValidGroup1.class)
@Size(min = 6, max = 20, groups = ValidGroup2.class)
@Pattern(regexp = "^[a-zA-Z0-9]+$", groups = ValidGroup3.class)
private String account;
@NotBlank(groups = PasswordGroup1.class)
@Size(min = 6, max = 12, groups = PasswordGroup2.class)
@Pattern(regexp = "^[a-zA-Z0-9!-/:-@¥[-`{-~]]+$", groups = PasswordGroup3.class)
private String password;
@NotBlank(groups = PasswordGroup1.class)
@Size(min = 6, max = 12, groups = PasswordGroup2.class)
@Pattern(regexp = "^[a-zA-Z0-9!-/:-@¥[-`{-~]]+$", groups = PasswordGroup3.class)
private String confirmPassword;
@NotBlank(groups = ValidGroup1.class)
@Size(min = 1, max = 10, groups = ValidGroup2.class)
private String name;
@NotBlank(groups = ValidGroup1.class)
private String birthday;
@NotBlank(groups = MailGroup1.class)
@Email(groups = MailGroup2.class)
private String mail;
@NotBlank(groups = MailGroup1.class)
@Email(groups = MailGroup2.class)
private String confirmMail;
private String roleName;
}
Für jeden Artikel werden Leerzeichen, reguläre Ausdrücke, Bestätigungskennwörter, Bestätigungs-E-Mail-Adressen und andere Überprüfungen definiert. Die zu filternden Felder sind getrennt, und es ist besser, GroupOrder anzugeben. .. ..
Controller
SignupController
@PostMapping("/signup")
String createUser(@ModelAttribute("userForm") @Validated({ GroupOrder.class, PasswordGroupOrder.class, MailGroupOrder.class }) UserForm userForm,
BindingResult result, RedirectAttributes redirectAttributes) {
if(result.hasErrors()) {
return "users/signup/new";
}
mailAuthUserService.authUserbyMail(userForm);
redirectAttributes.addFlashAttribute("resultMessage", "Eine E-Mail wurde gesendet. Bitte überprüfen Sie Ihre Mailbox.");
return "redirect:/login";
}
Wenn man die Umleitung dieser zur Update-Seite als Problem betrachtet (Angenommen, Sie bringen die Informationen so, wie sie aus der Datenbank stammen.)
-Wenn das Kennwort aktualisiert wird, wird das Kennwort irreversibel gehasht, sodass die von der Datenbank übermittelten Informationen nicht so eingegeben werden können, wie sie in dem Formular auf der Aktualisierungsseite vorliegen (das zum Zeitpunkt der Aktualisierung gehashte Kennwort wird gehasht). Weil es gemacht wird). Das Passwort muss leer sein. -Wenn Sie nicht aktualisieren möchten, sind die Elemente des Bestätigungskennworts und der Bestätigungs-E-Mail-Adresse leer, sodass die Validierung angewendet wird. Es ist mühsam, Gegenstände einzeln zu platzieren.
Die Validierung steht also im Weg.
Laut Google-Lehrer scheint die Methode zum Löschen des Fehlerelements nicht in "BindinResult" definiert zu sein, daher kann dies nicht durchgeführt werden. Wenn Sie das Objekt neu definieren, anstatt es zu löschen, können Sie es als Ergebnis löschen!
UserController.java
private BindingResult filteringBindingResult(BindingResult result, UserForm userForm) {
UserDto userDto = findById(userForm.getId()); //・ ・ ・ 1
BindingResult tmpResult = new BeanPropertyBindingResult(userForm, "userForm");//・ ・ ・ 2
if(StringUtils.isEmpty(userForm.getPassword()) && userDto.getMail().equals(userForm.getMail())) { //· · · 3
for(FieldError fieldError : result.getFieldErrors()) { //・ ・ ・ 4
if(fieldError.getField().equals("confirmMail") ||
fieldError.getField().equals("confirmPassword") ||
fieldError.getField().equals("password")) {
continue;
}
tmpResult.addError(fieldError);
}
return tmpResult;
}
if(StringUtils.isEmpty(userForm.getPassword())) {
for(FieldError fieldError : result.getFieldErrors()) {
if(fieldError.getField().equals("confirmPassword") ||
fieldError.getField().equals("password")) {
continue;
}
tmpResult.addError(fieldError);
}
return tmpResult;
}
if(userDto.getMail().equals(userForm.getMail())) {
for(FieldError fieldError : result.getFieldErrors()) {
if(fieldError.getField().equals("confirmMail")) {
continue;
}
tmpResult.addError(fieldError);
}
return tmpResult;
}
return result;
}
Argumente: BindingResult-Ergebnis (speichert das Fehlerergebnis)
, UserForm userForm (Element auf der Ansichtsseite eingegeben)
Rückgabewert ・ ・ ・ BindingResult
1 ... Definiert, um Benutzerinformationen aus der Datenbank abzurufen und zu überprüfen, ob sich die E-Mail-Adresse geändert hat.
2 ... Da BindingResult eine Schnittstelle ist, hat es keine Implementierung. BeanPropertyBindingResult ist die Standardimplementierung von BindingResult. Daher ist es erforderlich, diesem Objekt ein gefiltertes Fehlerelement zuzuweisen. Definieren Sie es daher.
Springframework
3 ... In dieser Implementierung möchten wir die Validierung verwenden, wenn sie aktualisiert werden muss. Überprüfen Sie daher, ob das Kennwort leer ist und sich die E-Mail-Adresse nicht geändert hat, und filtern Sie nach "Valaidation", wenn "true". Wenn mit
multipliziert wird und falsch ist, ist die Implementierung so, dass
mit normaler Valaidation multipliziert wird ``.
4 ... Mit dem Controller werden die empfangenen BindingResults einzeln entfernt, diejenigen, die den zu filternden Elementen entsprechen, werden mit continue übersprungen und die anderen werden tmpResult zugewiesen.
UserController.java
private BindingResult filteringBindingResult(BindingResult result, UserForm userForm) throws Exception {
final BindingResult newResult = new BeanPropertyBindingResult(userForm, "userForm");
Set<FieldError> allErrors = new HashSet<>();
result.getFieldErrors().forEach(x -> allErrors.add(x));
if (StringUtils.isEmpty(userForm.getPassword()) && StringUtils.isEmpty(userForm.getConfirmPassword())) {
allErrors.removeIf(x -> x.getField().equals("password") || x.getField().equals("confirmPassword"));
}
UserDto userDto = userService.findById(userForm.getId());
if (userDto.getMail().equals(userForm.getMail()) && StringUtils.isEmpty(userForm.getConfirmMail())) {
allErrors.removeIf(x -> x.getField().equals("mail") || x.getField().equals("confirmMail"));
}
allErrors.forEach(x -> newResult.addError(x));
if (result.getFieldErrorCount() == newResult.getFieldErrorCount()) {
return result;
} else {
return newResult;
}
}
Das BindingResult-Ergebnis wird nur entfernt, wenn das Bestätigungskennwort und das Kennwort leer sind "und wenn sich die E-Mail-Adresse nicht geändert hat und die Bestätigungs-E-Mail-Adresse leer ist". ..
Controller
UserController.java
@PostMapping("/{id}/edit")
String edit(Model model,
@Validated({ GroupOrder.class, PasswordGroupOrder.class, MailGroupOrder.class }) UserForm userForm,
BindingResult result) {
BindingResult filteringBindingResult = filteringBindingResult(result, userForm); //・ ・ ・ 1
if(filteringBindingResult.hasErrors()) {
model.addAttribute("org.springframework.validation.BindingResult.userForm", filteringBindingResult); //・ ・ ・ 2
return "users/edit";
}
userService.update(userForm);
return "redirect:/user/mypage";
}
1 ... Der Rückgabewert der zuvor definierten Methode wird in filteringBindingResult
gespeichert.
2 ... Ich hatte hier eine sehr schwierige Zeit, aber zuerst fragte ich mich, ob ich es reibungslos implementieren könnte, indem ich die Referenz des BindingResult-Ergebnisses umschreibe, aber anscheinend wurde es, als dieser Controller aufgerufen wurde, ein Modell. Das Ergebnis von BindingResult vor dem Anwenden des Filters wurde gespeichert. Sie müssen dieses Objekt also überschreiben. "org.springframework.validation.BindingResult.userForm
hat das Modell selbst gedruckt und debuggt ...
Ich weiß ehrlich gesagt nicht, ob es die beste Praxis ist. Es ist möglicherweise einfacher zu erkennen, wenn Sie es später betrachten, wenn Sie einfach das Formular für die Aktualisierung und die neue Registrierung trennen. Wenn Sie das Formular jedoch allgemein machen, können Sie auch die Fehlermeldung allgemein machen, sodass ich diese Methode ausführen werde Wurde ausgewählt. Ich wäre dankbar, wenn jemand hilfreich sein könnte.
Wenn die "@ GroupSequence" der Validierung alle gleich ist, gab es ein Problem, dass die Validierung nicht abgefangen wurde, als andere Felder fehlerhaft waren. Dies liegt daran, dass das gefilterte BindingResult nach ValidGroup1 nicht ausgegeben wird, da angegeben wird, dass ValidGroup2,3,4 darunter nicht ausgegeben wird, wenn es in ValidGroup1 von GroupOrder abgefangen wird. Daher ist es notwendig, "@ GroupSequence" separat vorzubereiten und anzuwenden.
Recommended Posts