实现图表展示数据项的国际化实现方案几种方案参考

Posted by Futari on 2024-03-08
Estimated Reading Time 6 Minutes
Words 1.1k In Total
Viewed Times

切面方案

  1. 定义注解 **InternationalizedField**
1
2
3
4
5
6
7
8
9
10
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InternationalizedField {
String key(); // 用于指定国际化资源文件中的键
}
  1. 创建国际化服务接口 LocalizationService和实现 LocalizationServiceImpl,与之前保持一致。
  2. 定义DTO类 **MyDTO****Result****B**
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.List;

public class MyDTO {
@InternationalizedField(key = "xxxxDTO.field1")
private String field1;

@InternationalizedField(key = "xxxxDTO.field2")
private String field2;

// Getters and setters
}

public class Result {
private List<MyDTO> a;
private List<B> bList;

// Getters and setters
}

public class B {
private String name;
private String realName;

// Getters and setters
}
  1. 创建国际化切面 **InternationalizationAspect**
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;

@Aspect
@Component
public class InternationalizationAspect {

private final LocalizationService localizationService;

@Autowired
public InternationalizationAspect(LocalizationService localizationService) {
this.localizationService = localizationService;
}

@AfterReturning(pointcut = "execution(* com.example.MyService.getResult(..)) && args(locale)", returning = "result")
public void internationalizeResult(Result result, String locale) throws IllegalAccessException {
if (result == null) {
return;
}

// 遍历Result对象中的A集合,构建注解的键与字段映射关系
for (MyDTO item : result.getA()) {
processLocalization(item, result.getBList(), locale);
}
}

private void processLocalization(MyDTO dto, List<B> bList, String locale) throws IllegalAccessException {
Field[] fields = dto.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(InternationalizedField.class)) {
InternationalizedField annotation = field.getAnnotation(InternationalizedField.class);
String key = annotation.key();
String localizedValue = localizationService.getLocalizedValue(key, locale);

// 遍历bList,查找name与注解key匹配的B对象,并设置其realName
for (B b : bList) {
if (b.getName().equals(key)) {
b.setRealName(localizedValue);
}
}
}
}
}
}
  1. 配置文件 **application-enus.properties****application-zhcn.properties**

application-enus.properties

1
2
xxxxDTO.field1=Field 1 EN
xxxxDTO.field2=Field 2 EN

application-zhcn.properties

1
2
xxxxDTO.field1=字段 1 中文
xxxxDTO.field2=字段 2 中文
  1. 服务类 **MyService**
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service
public class MyService {

public Result getResult(String locale) {
MyDTO dto1 = new MyDTO();
MyDTO dto2 = new MyDTO();
List<MyDTO> dtoList = Arrays.asList(dto1, dto2);

B b1 = new B();
b1.setName("xxxxDTO.field1");

B b2 = new B();
b2.setName("xxxxDTO.field2");

List<B> bList = Arrays.asList(b1, b2);

Result result = new Result();
result.setA(dtoList);
result.setBList(bList);

return result;
}
}
  1. 主应用程序 **MainApplication**
1
2
3
4
5
6
7
8
9
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
  1. 控制器示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

private final MyService myService;

public MyController(MyService myService) {
this.myService = myService;
}

@GetMapping("/result")
public Result getResult(@RequestHeader("Accept-Language") String locale) {
return myService.getResult(locale);
}
}

序列化器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;

@Component
public class InternationalizedSerializer extends JsonSerializer<Result> {

@Autowired
private LocalizationService localizationService;

private static final String FIELD_A = "a";
private static final String FIELD_B_LIST = "bList";
private static final String FIELD_NAME = "name";
private static final String FIELD_REAL_NAME = "realName";

@Override
public void serialize(Result result, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();

// 序列化 A 列表
serializeA(result.getA(), gen);

// 序列化 B 列表
serializeB(result.getBList(), result.getA(), gen);

gen.writeEndObject();
}

private void serializeA(List<MyDTO> aList, JsonGenerator gen) throws IOException {
gen.writeArrayFieldStart(FIELD_A); // 开始写入名为 "a" 的数组字段
for (MyDTO dto : aList) {
gen.writeStartObject(); // 开始写入一个对象
// 序列化 MyDTO 中的每个字段
for (Field field : dto.getClass().getDeclaredFields()) {
field.setAccessible(true); // 设置字段可访问
String fieldName = field.getName(); // 获取字段名
Object value;
try {
value = field.get(dto); // 获取字段的值
} catch (IllegalAccessException e) {
value = null;
}
gen.writeObjectField(fieldName, value); // 写入字段名和对应的值
}
gen.writeEndObject(); // 结束当前对象的写入
}
gen.writeEndArray(); // 结束数组字段的写入
}

private void serializeB(List<B> bList, List<MyDTO> aList, JsonGenerator gen) throws IOException {
gen.writeArrayFieldStart(FIELD_B_LIST); // 开始写入名为 "bList" 的数组字段
for (B b : bList) {
gen.writeStartObject(); // 开始写入一个对象
gen.writeStringField(FIELD_NAME, b.getName()); // 写入 "name" 字段的值
String locale = LocaleContextHolder.getLocale().toString(); // 获取当前语言环境
String realName = getRealNameFromDTOs(aList, b.getName(), locale); // 获取实际名称的国际化值
gen.writeStringField(FIELD_REAL_NAME, realName); // 写入 "realName" 字段的值
gen.writeEndObject(); // 结束当前对象的写入
}
gen.writeEndArray(); // 结束数组字段的写入
}

private String getRealNameFromDTOs(List<MyDTO> dtos, String name, String locale) {
for (MyDTO dto : dtos) {
for (Field field : dto.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(InternationalizedField.class)) {
InternationalizedField annotation = field.getAnnotation(InternationalizedField.class);
if (annotation.key().equals(name)) {
return localizationService.getLocalizedValue(annotation.key(), locale);
}
}
}
}
return null;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {

@Bean
public ObjectMapper objectMapper(InternationalizedSerializer internationalizedSerializer) {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Result.class, internationalizedSerializer);
objectMapper.registerModule(module);
return objectMapper;
}
}

其他的和上方一致


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !