✍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
属性。然后,我们使用Expression
的getValue
方法在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. 高阶使用方法及示例:
-
使用SpEL表达式引用Bean:
在SpEL表达式中可以引用Spring管理的Bean。示例:
@Value("#{myBean.myProperty}") private String myProperty;
在这个示例中,我们使用
@Value
注解和SpEL表达式注入myBean
的myProperty
属性的值。 -
使用SpEL表达式引用静态变量和方法:
可以使用T()
操作符引用静态变量和方法。示例:
@Value("#{T(java.lang.Math).PI}") private double pi;
在这个示例中,我们使用
@Value
注解和SpEL表达式注入Math.PI
的值。 -
使用SpEL表达式进行条件判断:
可以使用?:
运算符进行条件判断。示例:
@Value("#{systemProperties['java.home'] ?: 'C:\\Java\\JDK1.8'}") private String javaHome;
在这个示例中,我们使用
@Value
注解和SpEL表达式注入java.home
系统属性的值,如果java.home
系统属性的值为空,则使用C:\\Java\\JDK1.8
作为默认值。 -
使用SpEL表达式访问List和Map:
可以使用[]
操作符访问List和Map。示例:
@Value("#{myBean.myList[0]}") private String firstElement;
在这个示例中,我们使用
@Value
注解和SpEL表达式注入myBean
的myList
属性的第一个元素的值。
✍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
方法,该方法会调用ExampleService
的doSomething
方法。
这是一个简单的Spring Boot应用程序示例,它包括国际化的创建和使用。
注意:Spring Boot自动配置了一个MessageSource
,它是ResourceBundleMessageSource
的一个实例。因此,我们可以直接注入MessageSource
,而不需要自定义一个MessageSource
。
另外,我们可以在application.properties
或application.yml
文件中配置MessageSource
的属性。
示例:
spring.messages.basename=messages
spring.messages.cache-duration=3600
在这个示例中,我们配置了MessageSource
的basename
属性和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. 高阶使用方法及示例:
高阶使用方法:
-
消息参数化:
可以在消息中插入动态的值。示例:
String message = messageSource.getMessage("example.message", new Object[]{"John"}, locale); System.out.println(message);
在这个示例中,我们插入了动态的值"John"到
example.message
消息中。 -
默认值:
可以设置消息的默认值。示例:
String message = messageSource.getMessage("example.message", null, "Default Message", locale); System.out.println(message);
在这个示例中,如果
example.message
消息不存在,那么会使用默认的消息"Default Message"。
这些高阶使用方法可以使得MessageSource
更加灵活和强大。