跳至主要內容

SpringBoot接口 - 如何参数校验国际化

张启忻大约 3 分钟

SpringBoot接口 - 如何参数校验国际化

提示

上文我们学习了如何对SpringBoot接口进行参数校验,但是如果需要有国际化的信息(比如返回校验结果有中英文),应该如何优雅处理呢?

什么是国际化

软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。国际化又称为 i18n:internationalization

实现案例

这里实现一个案例: 语言切换和国际化(中英文)验证信息。

定义资源文件

在Resources下添加如下:

填写名称和资源语言类型

添加中英文对应的message

使用message


    @Data
    @Builder
    @ApiModel(value = "User", subTypes = {AddressParam.class})
    public class UserParam implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @NotEmpty(message = "{user.msg.userId.notEmpty}") // 这里
        private String userId;
    

中英文切换拦截

由于默认是拦截request参数获取locale参数来实现的切换语言,这里我们可以改下,优先从header中获取,如果没有获取到再从request参数中获取。


    package tech.pdai.springboot.validation.i18n.config;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.lang.NonNull;
    import org.springframework.util.ObjectUtils;
    import org.springframework.web.servlet.LocaleResolver;
    import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
    import org.springframework.web.servlet.support.RequestContextUtils;
    
    /**
     * custom locale change interceptor.
     *
     * @author pdai
     */
    @Slf4j
    public class CustomLocaleChangeInterceptor extends LocaleChangeInterceptor {
    
        /**
         * try to get locale from header, if not exist then get it from request parameter.
         *
         * @param request  request
         * @param response response
         * @param handler  handler
         * @return bool
         * @throws ServletException ServletException
         */
        @Override
        public boolean preHandle(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws ServletException {
            String newLocale = request.getHeader(getParamName());
            if (newLocale!=null) {
                if (checkHttpMethods(request.getMethod())) {
                    LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
                    if (localeResolver==null) {
                        throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
                    }
                    try {
                        localeResolver.setLocale(request, response, parseLocaleValue(newLocale));
                    } catch (IllegalArgumentException ex) {
                        if (isIgnoreInvalidLocale()) {
                            log.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage());
                        } else {
                            throw ex;
                        }
                    }
                }
                return true;
            } else {
                return super.preHandle(request, response, handler);
            }
        }
    
        private boolean checkHttpMethods(String currentMethod) {
            String[] configuredMethods = getHttpMethods();
            if (ObjectUtils.isEmpty(configuredMethods)) {
                return true;
            }
            for (String configuredMethod : configuredMethods) {
                if (configuredMethod.equalsIgnoreCase(currentMethod)) {
                    return true;
                }
            }
            return false;
        }
    }
    

初始化相关配置


    package tech.pdai.springboot.validation.i18n.config;
    
    import java.util.Locale;
    
    import lombok.RequiredArgsConstructor;
    import org.springframework.boot.validation.MessageInterpolatorFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.support.ResourceBundleMessageSource;
    import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
    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;
    
    /**
     * This class is for web config.
     *
     * @author pdai
     */
    @Configuration
    @RequiredArgsConstructor
    public class WebConfig implements WebMvcConfigurer {
    
        /**
         * lang param name in header, default to 'locale'.
         */
        private static final String LANGUAGE_PARAM_NAME = LocaleChangeInterceptor.DEFAULT_PARAM_NAME;
    
        /**
         * message source.
         */
        private final ResourceBundleMessageSource resourceBundleMessageSource;
    
        /**
         * default locale.
         *
         * @return locale resolver
         */
        @Bean
        public LocaleResolver localeResolver() {
            SessionLocaleResolver localeResolver = new SessionLocaleResolver();
            localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
            return localeResolver;
        }
    
        /**
         * local validator factory bean.
         *
         * @return LocalValidatorFactoryBean
         */
        @Bean
        public LocalValidatorFactoryBean localValidatorFactoryBean() {
            LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
            MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
            factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
            factoryBean.setValidationMessageSource(resourceBundleMessageSource);
            return factoryBean;
        }
    
        /**
         * locale change interceptor.
         *
         * @return LocaleChangeInterceptor
         */
        @Bean
        public LocaleChangeInterceptor localeChangeInterceptor() {
            LocaleChangeInterceptor interceptor = new CustomLocaleChangeInterceptor();
            interceptor.setParamName(LANGUAGE_PARAM_NAME);
            return interceptor;
        }
    
        /**
         * register locale change interceptor.
         *
         * @param registry registry
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(localeChangeInterceptor());
        }
    }
    

校验

  • 设置语言是中文

查看校验结果

  • 设置语言是英文

查看校验结果

示例源码

https://github.com/realpdai/tech-pdai-spring-demos