SpringBoot @InitBinder注解实现Bean国际化校验
创始人
2024-03-14 18:51:25
0

参考资料

  1. 参考: 妥当性チェックのエラーメッセージ出力方法 (需翻墙)
  2. springMVC之@InitBinder的用法1
  3. springMVC之@InitBinder的用法2
  4. springMVC之@InitBinder 和 Validator
  5. Spring MVCにおけるフォームバリデーションの適用事例【後編】

目录

  • 一. 前期准备
    • 1.1 自定义校验注解
    • 1.2 国际化资源文件
    • 1.3 application配置文件
    • 1.4 国际化配置文件
    • 1.5 待校验Bean
  • 二. 实现Validator接口
  • 三. @InitBinder校验Get请求
    • 3.1 前端
    • 3.2 controller层
    • 3.3 全局捕获BindException异常
    • 3.4 效果
  • 四. @InitBinder校验Post请求
    • 4.1 前端
    • 4.2 controller层
    • 4.3 全局捕获MethodArgumentNotValidException异常
    • 4.4 效果


一. 前期准备

1.1 自定义校验注解

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[] 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[] payload() default {};
}

1.2 国际化资源文件

⏹messages_zh.properties

1001E=请输入{msgArgs}。
1007E={0}和{1}的大小关系不正确。

⏹messages_ja.properties

1001E={msgArgs}を入力してください。
1007E={0}と{1}の大小関係が逆らいました。

⏹置于i18n文件夹下

在这里插入图片描述

1.3 application配置文件

spring:messages:# 指定国际化文件所在目录和文件前缀basename: i18n/messagesencoding: UTF-8

1.4 国际化配置文件

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());}
}

1.5 待校验Bean

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;
}

二. 实现Validator接口

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, "");}}
}

三. @InitBinder校验Get请求

3.1 前端

⏹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> BindExceptionHandle(BindException errors) {// 存放所有error信息的ListList> errorList = new ArrayList<>();for(FieldError err : errors.getFieldErrors()){// 根据当前的FieldError对象从国际化资源文件中获取信息String msg = this.messageSource.getMessage(err, LocaleContextHolder.getLocale());// 封装错误信息Map errorMap = new HashMap() {{put("field", err.getField());put("msg", msg);}};errorList.add(errorMap);}return errorList;}
}

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 效果

在这里插入图片描述

相关内容

热门资讯

进口危化品“白名单”管理制度在... 中新网大连12月26日电 (记者 杨毅)大连海关26日发布消息称,进口危化品“白名单”管理制度近期在...
北京两年办理虚假诉讼监督案21... 12月26日,北京市人民检察院召开虚假诉讼专项监督新闻发布会,介绍检方开展虚假诉讼专项监督行动的工作...
仅存7人!缅怀2025年离世的... 2025年末,上海师范大学中国“慰安妇”问题研究中心发布消息,沉痛送别两位日军“慰安妇”制度受害幸存...
原创 圣... 一觉醒来,长期攻击比亚迪的黑媒体天塌了。 就在圣诞节当天,比亚迪给他们送去了每人200万元的罚单。...
韩国前总统夫人金建希,被起诉 张昀/央视新闻 韩国前总统尹锡悦夫人金建希(资料图) 当地时间12月26日,韩国“金建希特检组”以...
守护公平正义 传递法治温度——... 2025年,长春市法律援助中心在局党组的坚强领导下,紧紧围绕“努力让人民群众在每一个司法案件中感受到...
4年纠纷一朝化解 河南法治报记者 朱广亚 通讯员 郭向东 “太感谢了,困扰我们4年的问题解决了,我们全家有房子住了!”...
日常金融纠纷何解?多地建立第三... 图片来源:界面新闻 界面新闻记者 | 安震 信用卡、理财产品、各类信贷等金融产品与服务的普及,...
京尹资讯:暖冬相聚,情满京尹—... 岁末暖冬,温情相聚。在平安夜与圣诞节的温馨氛围中,北京京尹律师事务所将节日庆典与十二月生日会巧妙融合...
空客因坠机事故被遇难者家属起诉 中国航空新闻网讯:据外媒12月25日报道,两名在2023年12月一起直升机坠毁事故中遇难机组人员的家...