参考资料
import javax.validation.Constraint;
import javax.validation.OverridesAttribute;
import javax.validation.Payload;
import javax.validation.constraints.Size;
import javax.validation.ReportAsSingleViolation;
import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@Documented
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Size
public @interface ValidateSize {String msgArgs() default "";String message() default "{1006E}";Class>[] groups() default {};Class extends Payload>[] payload() default {};// 覆盖重写@Size注解中的属性@OverridesAttribute(constraint = Size.class, name = "min")int min() default 0;@OverridesAttribute(constraint = Size.class, name = "max")int max() default Integer.MAX_VALUE;
}
import javax.validation.Constraint;
import javax.validation.constraints.NotEmpty;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import java.lang.annotation.*;@Documented
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@NotEmpty
@ReportAsSingleViolation
public @interface ValidateNotEmpty {String msgArgs() default "";String message() default "{1001E}";Class>[] groups() default {};Class extends Payload>[] payload() default {};
}
⏹messages_zh.properties
1001E=请输入{msgArgs}。
1007E={0}和{1}的大小关系不正确。
⏹messages_ja.properties
1001E={msgArgs}を入力してください。
1007E={0}と{1}の大小関係が逆らいました。
⏹置于i18n文件夹下

spring:messages:# 指定国际化文件所在目录和文件前缀basename: i18n/messagesencoding: UTF-8
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;import javax.annotation.Resource;
import java.util.Locale;@Configuration
public class InternationalConfig implements WebMvcConfigurer {// 默认解析器,用来设置当前会话默认的国际化语言@Beanpublic LocaleResolver localeResolver() {SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();// 指定当前项目的默认语言是中文sessionLocaleResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);return sessionLocaleResolver;}// 默认拦截器,用来指定切换国际化语言的参数名@Beanpublic LocaleChangeInterceptor localeChangeInterceptor() {LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();/*设置国际化请求参数为language设置完成之后,URL中的 ?language=zh 表示读取国际化文件messages_zh.properties*/localeChangeInterceptor.setParamName("language");return localeChangeInterceptor;}// 将我们自定义的国际化语言参数拦截器放入Spring MVC的默认配置中@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(localeChangeInterceptor());}
}
import lombok.Data;import javax.validation.groups.Default;@Data
public class Test4Entity {@ValidateNotEmpty(msgArgs = "ID项目", groups = {Default.class})private String id;@ValidateSize(msgArgs = "地址项目", max = 6, groups = {Default.class})private String address;@ValidateSize(msgArgs = "兴趣项目", max = 5, groups = {Default.class})private String hobby;
}
import lombok.Data;import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;@Data
public class Test16Form {@ValidateNotEmpty(msgArgs = "姓名")private String name;private Date birthday;private BigDecimal money;private Integer fromNumber;private Integer toNumber;// 校验List集合@Validprivate List tableList;
}
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;import java.util.HashMap;
import java.util.Locale;
import java.util.Map;@Component
public class FromToValidator implements Validator {@Overridepublic boolean supports(Class> clazz) {// 只支持指定Bean类型的校验return Test16Form.class.equals(clazz);}@Overridepublic void validate(Object target, Errors errors) {Test16Form form = (Test16Form) target;// 获取from和to的数字Integer fromNumber = form.getFromNumber();Integer toNumber = form.getToNumber();// 有任何一方为空,就不行校验if (ObjectUtils.isEmpty(fromNumber) || ObjectUtils.isEmpty(toNumber)) {return;}// 模拟从缓存或者session或者数据库中获取国际化消息Map languageErrorParamMap = new HashMap() {{put("zh", new Object[] { "开始数字", "结束数字" });put("ja", new Object[] { "スタートの数字", "エンドの数字" });}};// 获取当前设置地区的语言Locale locale = LocaleContextHolder.getLocale();String language = locale.getLanguage();Object[] errorParam = languageErrorParamMap.get(language);// 当from数字 大于 to数字的时候,进行业务校验if (fromNumber > toNumber) {/*参数1: bean中被校验住的属性名参数2: 国际化资源文件中的key参数3: error消息的参数参数4: 默认消息*/errors.rejectValue("fromNumber", "1007E", errorParam, "");}}
}
⏹test16.html
Title
3.2 controller层
@Controller
@RequestMapping("/test16")
public class Test16Controller {// 注入我们自定义的校验器@Resourceprivate FromToValidator fromToValidator;@InitBinderpublic void initBinder(WebDataBinder binder) {// 去除字符串前后的空格binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));// 使用我们自定义的校验器binder.addValidators(fromToValidator);}@GetMapping("/init")public ModelAndView init() {ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("test16");return modelAndView;}// 校验@GetMapping("/receiveGet")@ResponseBodypublic void receiveGet(@Validated Test16Form form) {System.out.println(form);}
}
3.3 全局捕获BindException异常
- Get请求被被校验住之后,会抛出BindException异常
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@ControllerAdvice
public class GlobalExceptionHandler {@Resourceprivate MessageSource messageSource;@ExceptionHandler(BindException.class)// 通过注解指定了响应的状态码,前台$.ajax会在error函数的xhr响应中接收错误json@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodypublic List
3.4 效果

四. @InitBinder校验Post请求
4.1 前端
⏹test16.html
Title
4.2 controller层
@Controller
@RequestMapping("/test16")
public class Test16Controller {// 注入我们自定义的校验器@Resourceprivate FromToValidator fromToValidator;@InitBinderpublic void initBinder(WebDataBinder binder) {// 去除字符串前后的空格binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));// 使用我们自定义的校验器binder.addValidators(fromToValidator);}@GetMapping("/init")public ModelAndView init() {ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("test16");return modelAndView;}// 校验@PostMapping("/receivePost")@ResponseBodypublic void receivePost(@RequestBody @Validated Test16Form form) {System.out.println(form);}
}
4.3 全局捕获MethodArgumentNotValidException异常
- Post请求被被校验住之后,会抛出MethodArgumentNotValidException异常
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@ControllerAdvice
public class GlobalExceptionHandler {@Resourceprivate HttpServletResponse response;@Resourceprivate MessageSource messageSource;@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic List> HandleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {// 存放所有error信息的ListList> errorList = new ArrayList<>();List errors = ex.getFieldErrors();for(FieldError err : errors){// 根据当前的FieldError对象从国际化资源文件中获取信息String msg = this.messageSource.getMessage(err, LocaleContextHolder.getLocale());Map errorMap = new HashMap() {{put("field", err.getField());put("msg", msg);}};errorList.add(errorMap);}// 通过response对象指定了响应的状态码,前台$.ajax会在error函数的xhr响应中接收错误jsonresponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);return errorList;
}
4.4 效果

相关内容