Quelle est la meilleure façon de mettre en œuvre une validation personnalisée au printemps de l'application?
Je suis (de nouveau dans le développement de la source) la création d'API REST pour mon application, les opérations CRUD sont mis en œuvre avec succès, mais maintenant, je veux mettre en œuvre côté serveur de validation. J'ai aussi lu qu'il y a plusieurs façons de validation pourrait être mis en œuvre.
- À l'aide de donnée annotations -> @notempty, @mail, etc...
- À l'aide de validation personnalisée -> étendre les validateurs
Je veux mettre en œuvre les deux dans mon application, Avec référence,
est-ce la bonne démarche à suivre?
OU
Est-il d'autres moyens de validation peuvent être mises en œuvre?
Contrôleur
@RestController
public class EmployeeController {
@Autowired
DataServices dataServices;
@Autowired
EmployeeValidator employeeValidator;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(employeeValidator);
}
@RequestMapping(value = "/employee/", method = RequestMethod.POST)
public ResponseEntity<Object> createUser(
@Valid @RequestBody Employee employee,
UriComponentsBuilder ucBuilder) throws Exception,
DataIntegrityViolationException {
if (dataServices.addEmployee(employee) == 0) {
Error error = new Error(1, "Data integrity violation",
"Email id is already exists.");
return new ResponseEntity<Object>(error, HttpStatus.CONFLICT);
}
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/employee/{id}")
.buildAndExpand(employee.getId()).toUri());
Status status = new Status(1, "Employee has been added successfully.");
return new ResponseEntity<Object>(status, headers, HttpStatus.CREATED);
}
}
Gestionnaire D'Erreur
@ControllerAdvice
public class RestErrorHandler {
private static final Logger logger = Logger
.getLogger(RestErrorHandler.class);
private MessageSource messageSource;
@Autowired
public RestErrorHandler(MessageSource messageSource) {
this.messageSource = messageSource;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ValidationErrorDTO processValidationError(
MethodArgumentNotValidException ex) {
logger.debug("Handling form validation error");
BindingResult result = ex.getBindingResult();
List<FieldError> fieldErrors = result.getFieldErrors();
return processFieldErrors(fieldErrors);
}
private ValidationErrorDTO processFieldErrors(List<FieldError> fieldErrors) {
ValidationErrorDTO dto = new ValidationErrorDTO();
for (FieldError fieldError : fieldErrors) {
String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
dto.addFieldError(fieldError.getField(), localizedErrorMessage,
fieldError.getDefaultMessage());
}
return dto;
}
private String resolveLocalizedErrorMessage(FieldError fieldError) {
Locale currentLocale = LocaleContextHolder.getLocale();
String localizedErrorMessage = messageSource.getMessage(fieldError,
currentLocale);
//If a message was not found, return the most accurate field error code
//instead.
//You can remove this check if you prefer to get the default error
//message.
if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
String[] fieldErrorCodes = fieldError.getCodes();
localizedErrorMessage = fieldErrorCodes[0];
}
return localizedErrorMessage;
}
}
Validateur
@Component
public class EmployeeValidator implements Validator {
public boolean supports(Class clazz) {
return Employee.class.isAssignableFrom(clazz);
}
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", errors
.getFieldError().getCode(), "First name is required.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", errors
.getFieldError().getCode(),
"Last name is required.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", errors
.getFieldError().getCode(),
"Email is required.");
}
}
Modèle
@Entity
@Table(name = "employee")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "id")
private long id;
//@NotEmpty(message = "Please enter first name")
@Column(name = "first_name")
private String firstName;
//@NotEmpty(message = "Please enter last name")
@Column(name = "last_name")
private String lastName;
//@NotEmpty(message = "Please enter email address")
@Email(message = "Please enter valid email address")
@Column(name = "email", unique = true)
private String email;
@NotEmpty(message = "Please enter mobile number")
@Size(min = 10, message = "Please enter valid mobile number")
@Column(name = "phone")
private String phone;
//Getter and Setter
}
Juste une remarque: Si vous commencez à exposer vos entités (l'Employé) à l'INTERFACE utilisateur à l'aide de JSON,vous devez utiliser le Printemps des Données au Repos, c'est exactement conçu pour répondre à ce besoin. À propos de la validation, je suis en utilisant cette stratégie.
Il existe de nombreux exemples de validation disponible avec la Liaison Résultat. Exactement ce que vous voulez atteindre?
Il existe de nombreux exemples de validation disponible avec la Liaison Résultat. Exactement ce que vous voulez atteindre?
OriginalL'auteur imbond | 2015-09-02
Vous devez vous connecter pour publier un commentaire.
Dans votre approche vous utilisez le Serveur de côté les validations, mais seulement dans la couche contrôleur. Avez-vous tryied à l'utilisation Professionnelle de la couche de validations, comme Hibernate API de Validation http://hibernate.org/validator/
Je l'ai utilisé dans un projet récent et formulaire de moi, c'est une excellente façon de garder des données cohérentes. Quelques ajustements et utils ont été nécessaires pour faire le travail que nous voulions, mais il n'a pas été trop difficile. Par exemple, cette validation, par défaut, ne sont vérifiées juste après la persistance d'un Objet dans la base de données, mais dans notre contrôleur, nous avons nécessaires pour faire de ce validations antérieures, de sorte que nous avons eu à mettre en œuvre un moyen d'appeler le mécanisme de validation qui s'appuie sur hibernate mécanisme de validation. Ou, autre exemple, nous avons dû développer un système similaire sur un service web pour retourner des erreurs lors de l'arrivée de données n'est pas valide.
Une manière d'utiliser des validations en cas de besoin est à mettre en œuvre sur l'ensemble de vos bussines objets. Ils peuvent hériter d'une classe comme ceci:
Noter que j'utilise la norme javax.la validation.Validation API (vérifier les références ici JPA 2.0 : qu'est-ce que javax.la validation.* package?). Mais la mise en œuvre que j'utilise est celui de la mise en veille prolongée.
Pour:
Contre:
Si vous utilisez la mise en veille prolongée (peut-être à l'aide de l'api JPA) vous pouvez essayer Hibernate API de Validation hibernate.org/validator/documentation/getting-started sachez que pour les projets simples, il peut être un peu exagérée, mais c'est une bonne pratique cependant.
Comment nous retourner un message de validation dans le cas de l'Api REST?
J'ai mis à jour ma réponse avec un exemple. Vous pouvez utiliser getErrors sur votre business object et de faire un utilitaire pour transformer Set<ConstraintViolation<BusinessObject>> les erreurs à vos besoins. Messages Json pour le Reste des réponses, XML sur le webservices réponses, correspondent à des erreurs de champs de formulaire dans une page JSP, etc.
OriginalL'auteur Ricardo Vila