欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring國際化和Validation詳解

 更新時間:2024年11月22日 14:37:42   作者:風(fēng)舞紅葉  
本文介紹了SpringBoot中國際化和Validation的融合實現(xiàn),包括配置MessageSource和LocalValidatorFactoryBean,以及自定義約束注解和校驗器,通過解析請求頭中的Accept-Language,SpringBoot可以返回不同語言的文本信息

SpringBoot國際化和Validation融合

場景

在應(yīng)用交互時,可能需要根據(jù)客戶端得語言來返回不同的語言數(shù)據(jù)。

前端通過參數(shù)、請求頭等往后端傳入locale相關(guān)得參數(shù),后端獲取參數(shù),根據(jù)不同得locale來獲取不同得語言得文本信息返回給前端。

實現(xiàn)原理

SpringBoot支持國際化和Validation,主要通過MessageSource接口和Validator實現(xiàn)。

國際化配置‌

  • 編寫國際化配置文件,如messages_en_US.propertiesmessages_zh_CN.properties,并置于resources/i18n目錄下。
  • 配置application.ymlapplication.properties以指定國際化文件的位置,例如spring.messages.basename=i18n/messages。
  • 配置LocaleResolver以解析當(dāng)前請求的locale,常用的實現(xiàn)是AcceptHeaderLocaleResolver,它通過請求頭accept-language獲取當(dāng)前的locale。

‌Validation配置‌

引入spring-boot-starter-validation依賴以支持Validation功能

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

配置LocalValidatorFactoryBean以使用國際化的校驗消息,需注入MessageSource

示例

引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

國際化配置文件

src/main/resources/i18n目錄下創(chuàng)建兩個文件:messages_en_US.propertiesmessages_zh_CN.properties

#messages_en_US.properties
welcome.message=Welcome to our website!

#messages_zh_CN.properties
welcome.message=歡迎來到我們的網(wǎng)站!

配置MessageSource‌

在Spring Boot的配置文件中(application.propertiesapplication.yml),配置MessageSource以指定國際化文件的位置。

如果你打算使用Validation的默認國際化文件,你實際上不需要為Validation單獨指定文件,因為LocalValidatorFactoryBean會自動查找ValidationMessages.properties。

但是,你可以配置自己的國際化文件,并讓MessageSource同時服務(wù)于你的應(yīng)用消息和Validation消息。

# 國際化文件被放置在src/main/resources/i18n目錄下,并以messages為前綴
spring.messages.basename=i18n/messages,org.hibernate.validator.ValidationMessages
spring.messages.encoding=utf-8

注意:上面的配置假設(shè)你的自定義消息文件位于i18n/messages.properties,而Validation的默認消息文件是org.hibernate.validator.ValidationMessages.properties

實際上,ValidationMessages.properties文件位于Hibernate Validator的jar包中,所以你不需要顯式地將它包含在你的資源目錄中。Spring Boot會自動從classpath中加載它。

配置LocalValidatorFactoryBean‌

在你的配置類中,創(chuàng)建一個LocalValidatorFactoryBean的bean,并將MessageSource注入到它中。

這樣,LocalValidatorFactoryBean就會使用Spring的MessageSource來解析校驗消息。

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import java.util.Properties;

@Configuration
public class ValidateConfig {

    @Bean
    public LocalValidatorFactoryBean validatorFactoryBean(MessageSource messageSource) {
        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
        factoryBean.setValidationMessageSource(messageSource);
        //        設(shè)置使用 HibernateValidator 校驗器
        factoryBean.setProviderClass(HibernateValidator.class);
//        設(shè)置 快速異常返回 只要有一個校驗錯誤就立即返回失敗,其他參數(shù)不在校驗
        Properties properties = new Properties();
        properties.setProperty("hibernate.validator.fail_fast", "true");
        factoryBean.setValidationProperties(properties);
//        加載配置
        factoryBean.afterPropertiesSet();
        return factoryBean;
    }
}

使用校驗

import javax.validation.constraints.NotNull;

public class MyModel {

    @NotNull(message = "{not.null.message}")
    private String field;

    // getters and setters
}

messages.properties文件中,你可以添加

not.null.message=This field cannot be null.

而在Hibernate Validator的ValidationMessages.properties文件中,已經(jīng)包含了默認的校驗消息,如{javax.validation.constraints.NotNull.message}的值。

自定義校驗

  • 定義約束注解:創(chuàng)建一個注解,用@Constraint標(biāo)記,并定義messagegroupspayload屬性
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;


@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyValidateContent.class)
public @interface MyValidate {
    String message() default "";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
  • 實現(xiàn)約束驗證器**:創(chuàng)建一個實現(xiàn)了ConstraintValidator接口的類,并重寫isValid方法
  • isValid方法中使用ConstraintValidatorContext**‌:如果驗證失敗,使用ConstraintValidatorContextbuildConstraintViolationWithTemplate方法來構(gòu)建ConstraintViolation
import com.example.dto.ParamVo;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;


public class MyValidateContent implements ConstraintValidator<MyValidate, ParamVo> {
    @Override
    public void initialize(MyConstraint constraintAnnotation) {
        // 初始化代碼(如果需要的話)
    }
    @Override
    public boolean isValid(ParamVo paramVo, ConstraintValidatorContext constraintValidatorContext) {
        if ("N".equals(paramVo.getSex())) {
            if (paramVo.getAge() < 18) {
                buildMessage(constraintValidatorContext, "template1");
                return false;
            }
        } else {
            if (paramVo.getAge() <  20) {
                buildMessage(constraintValidatorContext, "template2");
                return false;
            }
        }
        return true;
    }

    private void buildMessage(ConstraintValidatorContext context, String key) {
        String template = ('{'+key+'}').intern();
        context.buildConstraintViolationWithTemplate(template)
                .addConstraintViolation();
    }
}

在這個例子中,如果sexN并且age小于18,驗證器將使用ConstraintValidatorContext來構(gòu)建一個帶有錯誤消息的ConstraintViolation。

消息模板"{template1}"將會在驗證失敗時被解析,并替換為你在MyValidate注解中定義的默認消息或你在messages.properties文件中定義的國際化消息。

確保你的MyValidate注解定義了一個message屬性,并且你在messages.properties文件中有一個對應(yīng)的條目例如:

template1=男性要大于18
template2=女性要大于20
import com.example.validate.MyValidate;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Getter
@Setter
@MyValidate
public class ParamVo {
    @NotBlank(message = "{javax.validation.constraints.NotNull.message}")
    private String sex;
    @NotNull(message = "age 不能為空")
    private Integer age;
    @NotBlank(message = "{name.not.null}")
    @Length(max = 3,message = "{name.length.max}")
    private String name;
}

Controller層異常處理

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;


@RestControllerAdvice
public class GlobalException {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        BindingResult result = ex.getBindingResult();
        for (FieldError error : result.getFieldErrors()) {
            errors.put(error.getField(), error.getDefaultMessage());
        }
        // 這里可以根據(jù)實際需求定制返回的錯誤信息結(jié)構(gòu)
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.BAD_REQUEST.value());
        response.put("errors", errors);
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
}

內(nèi)部方法校驗

import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
//@Validated 
@Validated
public interface ServiceIntface {
    //校驗返回值,校驗入?yún)?
    @NotNull Object hello(@NotNull @Min(10) Integer id, @NotNull String name);
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ServiceImpl implements ServiceIntface {
    @Override
    public Object hello(Integer id, String name) {
        return null;
    }
}
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


@RestControllerAdvice
public class GlobalException {

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Object> handleValidationExceptions(ConstraintViolationException ex) {
        Map<String, String> errors = new HashMap<>();
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            String key = constraintViolation.getPropertyPath().toString();
            String message = constraintViolation.getMessage();
            errors.put(key, message);
        }

        // 這里可以根據(jù)實際需求定制返回的錯誤信息結(jié)構(gòu)
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.BAD_REQUEST.value());
        response.put("errors", errors);
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
}
  • 校驗寫在接口上的,拋出異常javax.validation.ConstraintViolationException
  • 校驗寫在具體實現(xiàn),拋出異常javax.validation.ConstraintDeclarationException

注意點

代碼中國際化使用

代碼里響應(yīng),手動獲取使用MessageSource的getMessage方法即可,也就是spring容器中的getMessage()

# messages_en_US.properties
welcome.message=Welcome to our website!

# messages_zh_CN.properties
welcome.message=歡迎來到我們的網(wǎng)站!

#定義消息,并使用占位符{0}、{1}等表示參數(shù)位置
#welcome.message=歡迎{0}來到{1}
//創(chuàng)建一個配置類來配置LocaleResolver,以便根據(jù)請求解析當(dāng)前的語言環(huán)境:
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.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import java.util.Locale;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
        sessionLocaleResolver.setDefaultLocale(Locale.US); // 設(shè)置默認語言
        return sessionLocaleResolver;
    }
}
//創(chuàng)建一個控制器來使用國際化的消息
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Locale;

@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private MessageSource messageSource;

    @GetMapping
    public String hello(HttpServletRequest request) {
        Locale locale = (Locale) request.getAttribute(org.springframework.web.servlet.LocaleResolver.LOCALE_RESOLVER_ATTRIBUTE);
         //messageSource.getMessage("welcome.message", new Object[]{"張三", "中國"}, Locale.CHINA)。
        return messageSource.getMessage("welcome.message", null, locale);
    }
}

Locale獲取

默認情況下spring注冊的messageSource對象為ResourceBundleMessageSource,會讀取spring.message配置。

請求中Locale的獲取是通過LocaleResolver進行處理,默認是AcceptHeaderLocaleResolver,通過WebMvcAutoConfiguration注入,從Accept-Language請求頭中獲取locale信息。

此時前端可以在不同語言環(huán)境時傳入不同的請求頭Accept-Language即可達到切換語言的效果

Accept-Language: en-Us
Accept-Language: zh-CN

默認情況下前端請求中的不用處理,如果約定其他信息傳遞Local,使用自定義的I18nLocaleResolver替換默認的AcceptHeaderLocaleResolver,重寫resolveLocale方法就可以自定義Locale的解析邏輯。

import cn.hutool.core.util.StrUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 *
 */
@Configuration
public class I18nConfig {
    @Bean
    public LocaleResolver localeResolver() {
        return new I18nLocaleResolver();
    }

    /**
     * 獲取請求頭國際化信息
     * 使用自定義的I18nLocaleResolver替換默認的AcceptHeaderLocaleResolver,重寫resolveLocale方法就可以自定義Locale的解析邏輯。
     *
     * 自定義后使用content-language傳Locale信息,使用_劃分語言個地區(qū)。
     * content-language: en_US
     * content-language: zh_CN
     */
    static class I18nLocaleResolver implements LocaleResolver {

        @Override
        public Locale resolveLocale(HttpServletRequest httpServletRequest) {
            String language = httpServletRequest.getHeader("content-language");
            Locale locale = Locale.getDefault();
            if (StrUtil.isNotBlank(language)) {
                String[] split = language.split("_");
                locale = new Locale(split[0], split[1]);
            }
            return locale;
        }

        @Override
        public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

        }
    }
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java消息摘要算法MAC實現(xiàn)與應(yīng)用完整示例

    Java消息摘要算法MAC實現(xiàn)與應(yīng)用完整示例

    這篇文章主要介紹了Java消息摘要算法MAC實現(xiàn)與應(yīng)用,結(jié)合完整實例形式分析了java消息摘要算法MAC的概念、原理、實現(xiàn)方法及相關(guān)操作注意事項,需要的朋友可以參考下
    2019-09-09
  • Java語言Lang包下常用的工具類介紹

    Java語言Lang包下常用的工具類介紹

    這篇文章主要介紹了Java語言Lang包下常用的工具類介紹,次奧變覺得挺不錯的,這里分享給大家,需要的朋友可以參考下。
    2017-10-10
  • MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用詳解

    MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用詳解

    這篇文章主要介紹了MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用詳解,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Java設(shè)計模式之觀察者模式

    Java設(shè)計模式之觀察者模式

    本文詳細講解了Java設(shè)計模式之觀察者模式,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 使用Apache?POI和SpringBoot實現(xiàn)Excel文件上傳和解析功能

    使用Apache?POI和SpringBoot實現(xiàn)Excel文件上傳和解析功能

    在現(xiàn)代企業(yè)應(yīng)用開發(fā)中,數(shù)據(jù)的導(dǎo)入和導(dǎo)出是一項常見且重要的功能需求,Excel?作為一種廣泛使用的電子表格工具,常常被用來存儲和展示數(shù)據(jù),下面我們來看看如何使用Apache?POI和SpringBoot實現(xiàn)Excel文件上傳和解析功能吧
    2025-01-01
  • Spring中@RequestParam、@RequestBody和@PathVariable的用法詳解

    Spring中@RequestParam、@RequestBody和@PathVariable的用法詳解

    這篇文章主要介紹了Spring中@RequestParam、@RequestBody和@PathVariable的用法詳解,后端使用集合來接受參數(shù),靈活性較好,如果url中沒有對參數(shù)賦key值,后端在接收時,會根據(jù)參數(shù)值的類型附,賦一個初始key,需要的朋友可以參考下
    2024-01-01
  • 使用Spring自定義實現(xiàn)IOC和依賴注入(注解方式)

    使用Spring自定義實現(xiàn)IOC和依賴注入(注解方式)

    這篇文章主要介紹了使用Spring自定義實現(xiàn)IOC和依賴注入(注解方式),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • spring?kafka?@KafkaListener詳解與使用過程

    spring?kafka?@KafkaListener詳解與使用過程

    這篇文章主要介紹了spring-kafka?@KafkaListener詳解與使用,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-02-02
  • SpringCloud災(zāi)難性雪崩效應(yīng)處理方法之降級實現(xiàn)流程詳解

    SpringCloud災(zāi)難性雪崩效應(yīng)處理方法之降級實現(xiàn)流程詳解

    這篇文章主要介紹了SpringCloud災(zāi)難性雪崩效應(yīng)處理方法之降級,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧<BR>
    2022-11-11
  • @KafkaListener 如何使用

    @KafkaListener 如何使用

    這篇文章主要介紹了@KafkaListener 如何使用,本文通過圖文實例代碼相結(jié)合給大家詳細講解,文末給大家介紹了kafka的消費者分區(qū)分配策略,需要的朋友可以參考下
    2023-02-02

最新評論