Skip to content

Instantly share code, notes, and snippets.

@HamidOsouli-zz
Forked from sndyuk/CustomConstraint.java
Created September 24, 2021 13:03
Show Gist options
  • Save HamidOsouli-zz/2a45f2d1c66d4352c00382befd12b694 to your computer and use it in GitHub Desktop.
Save HamidOsouli-zz/2a45f2d1c66d4352c00382befd12b694 to your computer and use it in GitHub Desktop.
Bean Validation
package sample;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = sample.CustomValidator.class)
public @interface CustomConstraint {
String message() default "message.custom.invalid";
Class[] groups() default {};
Class[] payload() default {};
}
package sample;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class CustomValidator implements ConstraintValidator<CustomConstraint, Object> {
private Validator[] validators;
@Override
public void initialize(CustomConstraint constraintAnnotation) {
this.validators = getInstancesOf(constraintAnnotation.payload());
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
boolean valid = true;
for (Validator validator : this.validators) {
Message[] errors = validator.validate(value); // ①
if (errors != null && errors.length > 0) {
for (Message error : errors) {
context.buildConstraintViolationWithTemplate(error.getMsg()).addConstraintViolation();
valid = false;
}
}
}
return valid;
}
public static <T> Validator[] getInstancesOf(Class[] classes) {
… // classからValdatorのインスタンスを生成する
}
}
package sample;
import javax.validation.constraints.NotNull;
import javax.validation.Valid;
import sample.CustomConstraint;
import sample.Validators.Id;
public class Document {
@CustomConstraint(payload = Id.class) // ③
private Long id;
@NotNull // ④
private String text;
@Valid // ⑤
private Edtior editor;
...
}
package sample;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import sample.CustomConstraint;
import sample.Validators.DocumentSaveMode;
@Controller
public class DocumentController {
@RequestMapping(value = "document",
method = RequestMethod.PUT,
consumes = "application/json",
produces = "application/json")
@ResponseBody public Document saveDocument(
final HttpServletRequest request,
final HttpServletResponse response,
final @RequestBody @Valid Document doc, // ①
final BindingResult result // ②
) {
...
}
package sample;
public class Message {
private final String msg;
private final Object[] params;
...
}
package sample;
public interface Validator<T> {
Message[] validate(T value);
}
package sample;
import javax.validation.Payload;
import sample.Message;
import sample.Validator;
import sample.DocumentSaveMode;
public final class Validators {
public static class Id implements Payload, Validator<Long> {
@Override
public Message[] validate(Long value) {
return ...; // 値をバリデーションしてエラーがあればMessageを返す。
}
...
}
public static class DocumentSaveMode implements Payload, Validator<DocumentSaveMode> {
@Override
public Message[] validate(DocumentSaveMode value) {
return ...; // 値をバリデーションしてエラーがあればMessageを返す。
}
...
}
...
}
package sample;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@EnableWebMvc
public abstract class WebConfig extends WebMvcConfigurerAdapter {
private final MessageSource messageSource;
{
ResourceBundleMessageSource bean = new ResourceBundleMessageSource();
bean.setBasenames("message");
bean.setDefaultEncoding("utf-8");
this.messageSource = bean;
}
@Bean
public MessageSource messageSource() {
return this.messageSource;
}
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(this.messageSource);
return bean;
}
@Override
public Validator getValidator() {
return validator();
}
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment