spring6-Internationalization: i18n | Data verification: Validation

1. Internationalization: i18n

Insert image description here

1.1, i18n overview

Internationalization is also called i18n, which comes from the first and last characters i and n of the English word internationalization, and 18 is the number of characters in the middle. Since software may be released to multiple countries, the process of displaying software in different languages ​​for users in different countries is internationalization. Generally speaking, internationalization in software is achieved through configuration files. If you want to support two languages, you need two versions of configuration files.

1.2. Java internationalization

(1) Java itself supports internationalization. java.util.Locale is used to specify the locale and other information of the current user, and java.util.ResourceBundle is used to find the resource file corresponding to the binding. Locale contains language information and country information. The static method used by Locale when creating the default locale object:

    /**
     * This method must be called only for creating the Locale.*
     * constants due to making shortcuts.
     */
    private static Locale createConstant(String lang, String country) {
    
    
        BaseLocale base = BaseLocale.createInstance(lang, country);
        return getInstance(base, null);
    }

(2) Configuration file naming rules:
basename_language_country.properties
The above naming rules must be followed before java can recognize it. Among them, basename is required, language and country are optional. There is a priority concept here. If both messages.properties and messages_zh_CN.propertes are provided at the same time, and if the locale provided conforms to en_CN, then the messages_en_CN.propertes configuration file will be searched first. If not found, the messages.properties configuration will be searched. document. Finally, as prompted, all configuration files must be placed in the classpath, usually in the resources directory

(3) Experiment: Demonstrate Java internationalization

The first step is to create the sub-module spring6-i18n and introduce spring dependencies.

Insert image description here

Step 2 Create two configuration files in the resource directory: messages_zh_CN.propertes and messages_en_GB.propertes

Insert image description here

Step 3 Test

package com.atguigu.spring6.javai18n;

import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.ResourceBundle;

public class Demo1 {
    
    

    public static void main(String[] args) {
    
    
        System.out.println(ResourceBundle.getBundle("messages",
                new Locale("en","GB")).getString("test"));

        System.out.println(ResourceBundle.getBundle("messages",
                new Locale("zh","CN")).getString("test"));
    }
}

1.3. Spring6 internationalization

1.3.1. MessageSource interface

Internationalization in spring is supported through the MessageSource interface.

Common implementation classes

ResourceBundleMessageSource

This is based on Java's ResourceBundle basic class implementation, allowing internationalized resources to be loaded only through resource names.

ReloadableResourceBundleMessageSource

This function is similar to the function of the first class, with the addition of a scheduled refresh function, which allows updating resource information without restarting the system.

StaticMessageSource

It allows to provide internationalized information programmatically. Later we can use this to implement the function of storing internationalized information in the db.

1.3.2. Use Spring6 internationalization

Step 1: Create resource files

Internationalized file naming format: basename_language_country.properties

Contents like {0},{1} are dynamic parameters.

Insert image description here

(1) Create atguigu_en_US.properties

www.atguigu.com=welcome {0},时间:{1}

(2) Create atguigu_zh_CN.properties

www.atguigu.com=欢迎 {0},时间:{1}

Step 2: Create spring configuration file and configure MessageSource

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="messageSource"
          class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>atguigu</value>
            </list>
        </property>
        <property name="defaultEncoding">
            <value>utf-8</value>
        </property>
    </bean>
</beans>

Step 3 Create test class

package com.atguigu.spring6.javai18n;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Date;
import java.util.Locale;

public class Demo2 {
    
    

    public static void main(String[] args) {
    
    
        
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        //传递动态参数,使用数组形式对应{0} {1}顺序
        Object[] objs = new Object[]{
    
    "atguigu",new Date().toString()};

        //www.atguigu.com为资源文件的key值,
        //objs为资源文件value值所需要的参数,Local.CHINA为国际化为语言
        String str=context.getMessage("www.atguigu.com", objs, Locale.CHINA);
        System.out.println(str);
    }
}

2. Data verification: Validation

Insert image description here

2.1. Overview of Spring Validation

Insert image description here

During development, we often encounter the need for parameter verification. For example, when a user registers, it is necessary to verify that the user name cannot be empty, the length of the user name does not exceed 20 characters, the mobile phone number is in a legal mobile phone number format, etc. If we use the ordinary method, we will couple the verification code with the real business processing logic, and if we want to add a new verification logic in the future, we will need to modify multiple places. Spring validation allows object verification rules to be defined through annotations, which separates verification from business logic, making code writing more convenient. Spring Validation is actually a further encapsulation of Hibernate Validator to facilitate use in Spring.

There are many verification methods in Spring

The first is to implement the org.springframework.validation.Validator interface and then call this class in the code

The second is to perform verification according to the Bean Validation method, that is, through annotations.

The third method is to implement verification based on methods

In addition, custom verification can also be implemented

2.2. Experiment 1: Implementation through Validator interface

The first step is to create the submodule spring6-validator

Insert image description here

Step 2: Introduce relevant dependencies

<dependencies>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>7.0.5.Final</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>jakarta.el</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencies>

Step 3: Create entity classes and define properties and methods

package com.atguigu.spring6.validation.method1;

public class Person {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public int getAge() {
    
    
        return age;
    }
    public void setAge(int age) {
    
    
        this.age = age;
    }
}

Step 4: Create a class to implement the Validator interface and implement the interface method to specify the verification rules.

package com.atguigu.spring6.validation.method1;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class PersonValidator implements Validator {
    
    

    @Override
    public boolean supports(Class<?> clazz) {
    
    
        return Person.class.equals(clazz);
    }

    @Override
    public void validate(Object object, Errors errors) {
    
    
        ValidationUtils.rejectIfEmpty(errors, "name", "name.empty");
        Person p = (Person) object;
        if (p.getAge() < 0) {
    
    
            errors.rejectValue("age", "error value < 0");
        } else if (p.getAge() > 110) {
    
    
            errors.rejectValue("age", "error value too old");
        }
    }
}

The class defined above actually implements the corresponding method in the interface.

The supports method is used to indicate which type this check is used on.

Validate is the place where validation logic is set. ValidationUtils is a validation tool class encapsulated by Spring to help quickly implement validation.

Step 5: Use the above Validator to test

package com.atguigu.spring6.validation.method1;

import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;

public class TestMethod1 {
    
    

    public static void main(String[] args) {
    
    
        //创建person对象
        Person person = new Person();
        person.setName("lucy");
        person.setAge(-1);
        
        // 创建Person对应的DataBinder
        DataBinder binder = new DataBinder(person);

        // 设置校验
        binder.setValidator(new PersonValidator());

        // 由于Person对象中的属性为空,所以校验不通过
        binder.validate();

        //输出结果
        BindingResult results = binder.getBindingResult();
        System.out.println(results.getAllErrors());
    }
}

2.3. Experiment 2: Bean Validation annotation implementation

Using the Bean Validation verification method is how to inject the javax.validation.ValidatorFactory and javax.validation.Validator required for Bean Validation into the container. Spring has an implementation class by default, LocalValidatorFactoryBean, which implements the interface in Bean Validation above, and also implements the org.springframework.validation.Validator interface.

The first step is to create a configuration class and configure LocalValidatorFactoryBean

@Configuration
@ComponentScan("com.atguigu.spring6.validation.method2")
public class ValidationConfig {
    
    

    @Bean
    public LocalValidatorFactoryBean validator() {
    
    
        return new LocalValidatorFactoryBean();
    }
}

Step 2: Create an entity class and use annotations to define verification rules

package com.atguigu.spring6.validation.method2;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;

public class User {
    
    

    @NotNull
    private String name;

    @Min(0)
    @Max(120)
    private int age;

    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public int getAge() {
    
    
        return age;
    }
    public void setAge(int age) {
    
    
        this.age = age;
    }
}

Common annotations
@NotNull restriction must not be null
@NotEmpty only applies to string type, the string is not empty, and the length Not 0
@NotBlank only applies to string types, the string is not empty, and the string after trim() is not an empty string
@DecimalMax(value) The limit must be a number not greater than the specified value
@DecimalMin(value) The limit must be a number not less than the specified value
@Max(value) The limit must be Is a number that is not greater than the specified value
@Min(value) The limit must be a number that is not less than the specified value
@Pattern(value) The limit must comply with the specified Regular expression
@Size(max,min) The limit character length must be between min and max
@Email Verify that the element value of the annotation is Email, also Custom email formats can be specified through regular expressions and flags

The third step is to use two different validators to implement

(1) Use jakarta.validation.Validator to verify

package com.atguigu.spring6.validation.method2;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;

@Service
public class MyService1 {
    
    

    @Autowired
    private Validator validator;

    public  boolean validator(User user){
    
    
        Set<ConstraintViolation<User>> sets =  validator.validate(user);
        return sets.isEmpty();
    }

}

(2) Use org.springframework.validation.Validator to verify

package com.atguigu.spring6.validation.method2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindException;
import org.springframework.validation.Validator;

@Service
public class MyService2 {
    
    

    @Autowired
    private Validator validator;

    public boolean validaPersonByValidator(User user) {
    
    
        BindException bindException = new BindException(user, user.getName());
        validator.validate(user, bindException);
        return bindException.hasErrors();
    }
}

Step 4 Test

package com.atguigu.spring6.validation.method2;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMethod2 {
    
    

    @Test
    public void testMyService1() {
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
        MyService1 myService = context.getBean(MyService1.class);
        User user = new User();
        user.setAge(-1);
        boolean validator = myService.validator(user);
        System.out.println(validator);
    }

    @Test
    public void testMyService2() {
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
        MyService2 myService = context.getBean(MyService2.class);
        User user = new User();
        user.setName("lucy");
        user.setAge(130);
        user.setAge(-1);
        boolean validator = myService.validaPersonByValidator(user);
        System.out.println(validator);
    }
}

2.4. Experiment 3: Method-based verification

The first step is to create a configuration class and configure MethodValidationPostProcessor

package com.atguigu.spring6.validation.method3;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

@Configuration
@ComponentScan("com.atguigu.spring6.validation.method3")
public class ValidationConfig {
    
    

    @Bean
    public MethodValidationPostProcessor validationPostProcessor() {
    
    
        return new MethodValidationPostProcessor();
    }
}

Step 2: Create an entity class and use annotations to set verification rules

package com.atguigu.spring6.validation.method3;

import jakarta.validation.constraints.*;

public class User {
    
    

    @NotNull
    private String name;

    @Min(0)
    @Max(120)
    private int age;

    @Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
    @NotBlank(message = "手机号码不能为空")
    private String phone;

    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public int getAge() {
    
    
        return age;
    }
    public void setAge(int age) {
    
    
        this.age = age;
    }
    public String getPhone() {
    
    
        return phone;
    }
    public void setPhone(String phone) {
    
    
        this.phone = phone;
    }
}

Step 3 Define the Service class and operate the object through annotations

package com.atguigu.spring6.validation.method3;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

@Service
@Validated
public class MyService {
    
    
    
    public String testParams(@NotNull @Valid User user) {
    
    
        return user.toString();
    }

}

Step 4 Test

package com.atguigu.spring6.validation.method3;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMethod3 {
    
    

    @Test
    public void testMyService1() {
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
        MyService myService = context.getBean(MyService.class);
        User user = new User();
        user.setAge(-1);
        myService.testParams(user);
    }
}

2.5. Experiment 4: Implement custom verification

Step 1: Customize verification annotations

package com.atguigu.spring6.validation.method4;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({
    
    ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {
    
    CannotBlankValidator.class})
public @interface CannotBlank {
    
    
    //默认错误消息
    String message() default "不能包含空格";

    //分组
    Class<?>[] groups() default {
    
    };

    //负载
    Class<? extends Payload>[] payload() default {
    
    };

    //指定多个时使用
    @Target({
    
    ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
    
    
        CannotBlank[] value();
    }
}

Step 2: Write the real verification class

package com.atguigu.spring6.validation.method4;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

public class CannotBlankValidator implements ConstraintValidator<CannotBlank, String> {
    
    

        @Override
        public void initialize(CannotBlank constraintAnnotation) {
    
    
        }

        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
    
    
                //null时不进行校验
                if (value != null && value.contains(" ")) {
    
    
                        //获取默认提示信息
                        String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();
                        System.out.println("default message :" + defaultConstraintMessageTemplate);
                        //禁用默认提示信息
                        context.disableDefaultConstraintViolation();
                        //设置提示语
                        context.buildConstraintViolationWithTemplate("can not contains blank").addConstraintViolation();
                        return false;
                }
                return true;
        }
}

Guess you like

Origin blog.csdn.net/m0_62946761/article/details/133978553