-J'implémente la validation dans le framework Spring, mais je veux filtrer le résultat de BindingResult! ・ Je souhaite utiliser un formulaire commun pour les nouveaux et les mises à jour!
View
En utilisant simplement la balise Spring, userForm est défini dans modelAttribute, et la balise d'entrée et la balise d'étiquette sont écrites. Le côté mise à jour a exactement la même structure.
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;
}
Des espaces, des expressions régulières, des mots de passe de confirmation, des adresses e-mail de confirmation et d'autres validations sont définis pour chaque élément. Les champs à filtrer sont séparés et il est préférable de spécifier GroupOrder. .. ..
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", "Un e-mail a été envoyé. Veuillez vérifier votre boîte aux lettres.");
return "redirect:/login";
}
Lorsque vous envisagez de les détourner du côté de la mise à jour, comme un problème (Supposons que vous apportiez les informations telles qu'elles proviennent de la base de données)
-Lors de la mise à jour du mot de passe, le mot de passe est haché de manière irréversible, de sorte que les informations apportées par la base de données ne peuvent pas être saisies telles quelles dans le formulaire côté mise à jour (celui haché au moment de la mise à jour est haché). Parce que ce sera fait). Le mot de passe doit être vide. -Lorsque vous ne souhaitez pas mettre à jour, les éléments du mot de passe de confirmation et de l'adresse e-mail de confirmation sont vides, la validation est donc appliquée. Il est difficile de placer les éléments un par un.
La validation fait donc obstacle.
Selon l'enseignant de Google, il semble que la méthode pour supprimer l'élément d'erreur n'est pas définie dans BindinResult
, donc cela ne peut pas être fait. Si vous `` redéfinissez l'objet '' au lieu de l'effacer, vous pourrez ainsi l'effacer!
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;
}
Arguments: Résultat BindingResult (stocke le résultat de l'erreur)
, ʻUserForm userForm (élément entré du côté de la vue)
`
Valeur de retour ・ ・ ・ BindingResult
1 ... Défini pour extraire les informations utilisateur de la base de données et vérifier si l'adresse e-mail a changé.
2 ... Puisque BindingResult est une interface, il n'a pas d'implémentation. BeanPropertyBindingResult est l'implémentation par défaut de BindingResult. Par conséquent, il est nécessaire d'attribuer un élément d'erreur filtré à cet objet, définissez-le donc.
Springframework
3 ... Dans cette implémentation, nous voulons utiliser la validation quand elle doit être mise à jour, alors vérifiez si le mot de passe est vide et que l'adresse e-mail n'a pas changé, et si true, filtrez sur la validation. Lorsque
est multiplié par '' et est faux, l'implémentation est telle que
multiplié par la validation normale ''.
4 ... Avec le contrôleur, les BindingResults reçus sont retirés un par un, ceux qui correspondent à l'élément à filtrer sont sautés avec continue et les autres sont affectés à tmpResult.
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;
}
}
Le résultat BindingResult est supprimé uniquement lorsqu'il est actualisé à l'aide de l'expression lambda et lorsque le mot de passe de confirmation et le mot de passe sont vides et lorsque l'adresse e-mail n'a pas changé et que l'adresse e-mail de confirmation est vide
. ..
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 ... La valeur de retour de la méthode définie précédemment est stockée dans filteringBindingResult
.
2 ... J'ai eu un moment très difficile ici, mais au début je me demandais si je pouvais l'implémenter en douceur en réécrivant la référence du résultat BindingResult, mais apparemment, lorsque ce contrôleur a été appelé, il est devenu un modèle. Le résultat de BindingResult avant d'appliquer le filtre a été stocké. Vous devez donc écraser cet objet. "org.springframework.validation.BindingResult.userForm
a imprimé et débogué le modèle lui-même ...
Honnêtement, je ne sais pas si c'est la meilleure pratique. Il peut être plus facile de voir lorsque vous l'examinez plus tard si vous séparez simplement le formulaire pour la mise à jour et le nouvel enregistrement, mais en rendant le formulaire commun, vous pouvez également rendre le message d'erreur commun, je vais donc utiliser cette méthode A été choisi. Je serais reconnaissant si quelqu'un pouvait être utile.
Si le @ GroupSequence
de la validation est identique, il y avait un problème que la validation n'a pas été interceptée lorsque d'autres champs étaient en erreur. Cela est dû au fait que le BindingResult filtré ne sera pas sorti après ValidGroup1 en raison de la spécification selon laquelle ValidGroup2,3,4 ci-dessous ne sera pas généré s'il est intercepté dans ValidGroup1 de GroupOrder.
Par conséquent, il est nécessaire de préparer et d'appliquer @ GroupSequence
séparément.
Recommended Posts