Springboot - 10.类型转换和表达式语言、国际化

✍1. 类型转换:

在Spring框架中,类型转换是通过ConversionService接口实现的。

1. ConversionService接口:

  • 作用:

    • ConversionService接口用于在不同类型之间进行转换,以便在应用程序中更轻松地处理不同数据类型之间的转换操作。
  • 使用场景:

    • 在应用程序中需要将一个数据类型转换为另一个数据类型,例如将String转换为Integer
  • 示例:

    @Service
    public class ExampleService {
    
        private final ConversionService conversionService;
    
        @Autowired
        public ExampleService(ConversionService conversionService) {
            this.conversionService = conversionService;
        }
    
        public void doSomething(String input) {
            if (conversionService.canConvert(String.class, Integer.class)) {
                Integer output = conversionService.convert(input, Integer.class);
                System.out.println(output);
            } else {
                System.out.println("Cannot convert from String to Integer");
            }
        }
    
    }
    

    在这个示例中,ExampleService类使用ConversionService进行类型转换,将输入的String转换为Integer

2. 高级用法:

  • 自定义类型转换器:

    • 在某些情况下,Spring的默认类型转换可能无法满足特定的需求。您可以自定义类型转换器,以实现自定义的类型转换逻辑。

    示例:

    public class CustomConverter implements Converter<SourceType, TargetType> {
        @Override
        public TargetType convert(SourceType source) {
            // Custom conversion logic here
        }
    }
    
  • 处理复杂类型转换:

    • 如果需要处理复杂的对象转换,您可以编写自定义类型转换器或使用Spring提供的转换服务来处理多个步骤的转换。

    示例:

    public class ComplexConverter implements Converter<String, ComplexType> {
        @Override
        public ComplexType convert(String source) {
            // Convert String to intermediate type
            IntermediateType intermediate = convertToIntermediate(source);
    
            // Convert intermediate type to ComplexType
            ComplexType complexType = convertToComplexType(intermediate);
    
            return complexType;
        }
    }
    
  • 在Web层处理数据绑定:

    • 在Spring MVC中,可以使用数据绑定和类型转换来将请求参数绑定到控制器方法的参数上。

    示例:

    @Controller
    public class UserController {
    
        @GetMapping("/user")
        public String getUser(@RequestParam("userId") Long userId) {
            // Use userId in your logic
        }
    
    }
    

    在这个示例中,userId请求参数将会自动从String转换为Long类型。

这些高级用法可以根据项目的实际需求来进一步扩展和定制类型转换的功能,以满足更复杂的业务场景。

✍2. 表达式语言:

Spring Expression Language (SpEL) 是Spring框架的一个强大的表达式语言,它可以用于查询和操作对象图。

1. SpEL表达式:

  • SpEL表达式是一个字符串,它可以包含字面量、属性、方法、数组、集合、索引器、运算符、变量、类型等。

    作用
    SpEL表达式可以用于在运行时动态访问和操作对象的属性和方法。

    使用场景
    SpEL可以用于Spring配置文件,注解,XML配置等。

    优缺点
    优点是它可以动态访问和操作对象,缺点是它可能会使代码变得复杂,不易读。

    示例:

    String expression = "name == 'John Doe'";
    

    在这个示例中,expression是一个SpEL表达式,它比较name属性的值是否等于John Doe

2. Expression接口:

  • Expression是一个接口,它定义了一些方法,用于解析和求值SpEL表达式。

    作用
    用于解析和求值SpEL表达式。

    使用场景
    当需要解析和求值SpEL表达式时。

    优缺点
    优点是它提供了一个简单的方式来解析和求值SpEL表达式,缺点是它可能会使代码变得复杂,不易读。

    示例:

    ExpressionParser parser = new SpelExpressionParser();
    Expression expression = parser.parseExpression("name == 'John Doe'");
    

    在这个示例中,我们创建了一个SpelExpressionParser对象,并使用它的parseExpression方法解析SpEL表达式。

3. 求值SpEL表达式:

  • SpEL表达式可以在一个上下文中求值。上下文可以是一个对象、一个数组、一个集合、一个字典等。

    作用
    在特定的上下文中求值SpEL表达式。

    使用场景
    当需要在特定的上下文中求值SpEL表达式时。

    优缺点
    优点是它可以在特定的上下文中求值SpEL表达式,缺点是它可能会使代码变得复杂,不易读。

    示例:

    Person person = new Person();
    person.setName("John Doe");
    Boolean result = expression.getValue(person, Boolean.class);
    System.out.println(result);
    

    在这个示例中,我们创建了一个Person对象,并设置它的name属性。然后,我们使用ExpressiongetValue方法在Person对象的上下文中求值SpEL表达式。

这是一个简单的Spring Boot应用程序示例,它包括SpEL表达式的创建、解析和求值。

注意:SpEL也可以用于配置文件、注解、XML配置等。

示例:

@Value("#{systemProperties['java.home']}")
private String javaHome;

在这个示例中,我们使用@Value注解和SpEL表达式注入java.home系统属性的值。

另外,SpEL也可以用于@Query注解。

示例:

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {

    @Query("select p from Person p where p.name = :#{#person.name}")
    List<Person> findByName(@Param("person") Person person);

}

在这个示例中,我们使用@Query注解和SpEL表达式定义了一个查询方法。

4. 高阶使用方法及示例:

  1. 使用SpEL表达式引用Bean:
    在SpEL表达式中可以引用Spring管理的Bean。

    示例:

    @Value("#{myBean.myProperty}")
    private String myProperty;
    

    在这个示例中,我们使用@Value注解和SpEL表达式注入myBeanmyProperty属性的值。

  2. 使用SpEL表达式引用静态变量和方法:
    可以使用T()操作符引用静态变量和方法。

    示例:

    @Value("#{T(java.lang.Math).PI}")
    private double pi;
    

    在这个示例中,我们使用@Value注解和SpEL表达式注入Math.PI的值。

  3. 使用SpEL表达式进行条件判断:
    可以使用?:运算符进行条件判断。

    示例:

    @Value("#{systemProperties['java.home'] ?: 'C:\\Java\\JDK1.8'}")
    private String javaHome;
    

    在这个示例中,我们使用@Value注解和SpEL表达式注入java.home系统属性的值,如果java.home系统属性的值为空,则使用C:\\Java\\JDK1.8作为默认值。

  4. 使用SpEL表达式访问List和Map:
    可以使用[]操作符访问List和Map。

    示例:

    @Value("#{myBean.myList[0]}")
    private String firstElement;
    

    在这个示例中,我们使用@Value注解和SpEL表达式注入myBeanmyList属性的第一个元素的值。

✍3. 国际化:

Spring框架通过MessageSource接口支持国际化,这样应用程序可以根据不同的地区显示不同的消息。

1. MessageSource接口:

  • MessageSource接口定义了几个方法来解析消息。最常用的是getMessage方法,它可以根据消息的键、参数和地区解析消息。

    作用
    MessageSource接口是用来解析消息的。它可以根据不同的地区、参数和消息的键来解析消息。

    使用场景
    MessageSource可以用在任何需要根据不同地区显示不同消息的场景。

    优缺点
    优点是它支持国际化,可以在一个地方管理所有的消息,而不需要在代码中硬编码消息。缺点是需要维护不同语言的消息资源。

    示例:

    @Service
    public class ExampleService {
    
        private final MessageSource messageSource;
    
        @Autowired
        public ExampleService(MessageSource messageSource) {
            this.messageSource = messageSource;
        }
    
        public void doSomething(Locale locale) {
            String message = messageSource.getMessage("example.message", null, locale);
            System.out.println(message);
        }
    
    }
    

    在这个示例中,ExampleService类有一个doSomething方法,该方法会解析example.message消息。

2. 使用MessageSource:

  • MessageSource可以在服务层或控制层使用。

    作用
    在服务层或控制层解析消息。

    使用场景
    当需要在服务层或控制层解析消息时。

    优缺点
    优点是它可以在服务层或控制层解析消息,缺点是需要维护不同语言的消息资源。

    示例:

    @RestController
    public class ExampleController {
    
        private final ExampleService exampleService;
    
        @Autowired
        public ExampleController(ExampleService exampleService) {
            this.exampleService = exampleService;
        }
    
        @GetMapping("/example")
        public ResponseEntity<?> getExample(Locale locale) {
            exampleService.doSomething(locale);
            return ResponseEntity.ok().build();
        }
    
    }
    

    在这个示例中,ExampleController类有一个getExample方法,该方法会调用ExampleServicedoSomething方法。

这是一个简单的Spring Boot应用程序示例,它包括国际化的创建和使用。

注意:Spring Boot自动配置了一个MessageSource,它是ResourceBundleMessageSource的一个实例。因此,我们可以直接注入MessageSource,而不需要自定义一个MessageSource

另外,我们可以在application.propertiesapplication.yml文件中配置MessageSource的属性。

示例:

spring.messages.basename=messages
spring.messages.cache-duration=3600

在这个示例中,我们配置了MessageSourcebasename属性和cacheDuration属性。

basename属性是一个逗号分隔的列表,它包含了消息资源的基本名称。cacheDuration属性是消息资源的缓存持续时间,单位是秒。

另外,我们也可以在@Value注解中使用MessageSource

示例:

@Value("#{messageSource.getMessage('example.message', null, locale)}")
private String message;

在这个示例中,我们使用@Value注解和MessageSource注入example.message消息的值。

3. 为什么要这样做?

国际化是软件开发的一个重要组成部分,它使得软件可以根据不同的地区显示不同的消息。这对于开发全球化的应用程序是非常重要的。

Spring框架通过MessageSource接口支持国际化,这样我们可以在应用程序中使用不同的消息资源,而不需要修改代码。

MessageSource接口提供了一个灵活的方式来解

析消息。我们可以根据消息的键、参数和地区解析消息。这样,我们可以在一个地方管理所有的消息,而不需要在代码中硬编码消息。

此外,MessageSource接口也支持消息的参数化,这样我们可以在消息中插入动态的值。

总的来说,MessageSource接口提供了一个强大的方式来支持应用程序的国际化。

4. 高阶使用方法及示例:

高阶使用方法:

  1. 消息参数化:
    可以在消息中插入动态的值。

    示例:

    String message = messageSource.getMessage("example.message", new Object[]{"John"}, locale);
    System.out.println(message);
    

    在这个示例中,我们插入了动态的值"John"到example.message消息中。

  2. 默认值:
    可以设置消息的默认值。

    示例:

    String message = messageSource.getMessage("example.message", null, "Default Message", locale);
    System.out.println(message);
    

    在这个示例中,如果example.message消息不存在,那么会使用默认的消息"Default Message"。

这些高阶使用方法可以使得MessageSource更加灵活和强大。

你可能感兴趣的:(Springboot-详解,spring,boot,java,后端)