Skip to content

Commit

Permalink
SpringBoot初始化模板v2.1.9 更新国际化模块,添加初始化字典以及ReturnCode枚举国际化方法,设计加密模块。
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonyCheng committed Sep 2, 2024
1 parent 1d6e42f commit a02d37f
Show file tree
Hide file tree
Showing 25 changed files with 999 additions and 63 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -853,15 +853,15 @@ spring:

建议使用该模板国际化功能之前先把源代码看一遍或者是先了解一下国际化的通常流程,然后再进行自定义化的配置和编码。

1. 修改国际化相关配置,启动国际化功能:
1. 首先检查 `resources/i18n/messagesXXX.properties` 国际化字典文件中是否有内容,如果没有,建议先执行 `src/test/java/top/sharehome/springbootinittemplate/MainApplicationTests.java` 类中的 `initI18n()` 方法,将系统中 `ReturnCode` 响应进行国际化,将最后得到的打印结果手动粘贴复制到 `resources/i18n/messagesXXX.properties` 文件中,这样做的原因是当需要`ReturnCode` 枚举中内容国际化时可以直接调用其类方法 `toI18n()` 。

2. 修改国际化相关配置,主要根据项目要求修改默认语言:

```yaml
# 公共配置文件
spring:
# 国际化配置
messages:
# todo 是否启动国际化功能(预先关闭)
enable: true
# 默认语言
default-locale: zh_cn
# 解释:I18n是存放多语言文件目录,messages是文件前缀
Expand All @@ -873,18 +873,18 @@ spring:
# 找不到与用户区域设置匹配的消息时,将退回系统默认区域设置
fallback-to-system-locale: true
# 当找不到对应的消息键时,决定是否使用键值本身作为消息返回
use-code-as-default-message: false
use-code-as-default-message: true
```

2. 开发者需要确定好自己项目中需要涉及到的语言种类,模板中主动提供了英文、中文简体和中文繁体,以中文繁体为例准备好国际化词典文件 messages_zh_TW.properties (注意文件名前缀要保持和 `application.yaml` 配置文件一致):
3. 开发者需要确定好自己项目中需要涉及到的语言种类,模板中主动提供了英文、中文简体和中文繁体,以中文繁体为例准备好国际化词典文件 messages_zh_TW.properties (注意文件名前缀要保持和 `application.yaml` 配置文件一致):

```properties
opr_success=操作成功
opr_fail=操作失敗
msg_welcome=歡迎,{0}!
```

3. 将国际化词典文件放入 `resource/i18n` 文件夹中,并且记住后缀,将其按照规律写入 `top.sharehome.springbootinittemplate.config.i18n.properties.enums.LocaleType` 枚举类中:
4. 将国际化词典文件放入 `resource/i18n` 文件夹中,并且记住后缀,将其按照规律写入 `top.sharehome.springbootinittemplate.config.i18n.properties.enums.LocaleType` 枚举类中:

```java
@Getter
Expand All @@ -908,7 +908,7 @@ spring:
}
```

4. 然后参考国际化示例控制器 `top.sharehome.springbootinittemplate.config.i18n.controller.I18nDemoController` 进行国际化的使用:
5. 然后参考国际化示例控制器 `top.sharehome.springbootinittemplate.config.i18n.controller.I18nDemoController` 进行国际化的使用:

```java
/**
Expand Down
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,14 @@
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>

<!-- [测试所需依赖] 中文繁简体转换 -->
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>opencc4j</artifactId>
<version>1.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<!-- 项目构建概况 -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ public class R<T> implements Serializable {
*/
public static final String WARN_MSG = ReturnCode.WARN.getMsg();

/**
* 序列化UID
*/
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = -4320868468561398175L;

/**
* 消息状态码
Expand Down Expand Up @@ -95,18 +92,15 @@ public static <T> R<T> ok() {
}

public static R<Map<String, Object>> okWithToken() {
Map<String, Object> res = new HashMap<String, Object>();
res.put("token", StpUtil.getTokenValue());
res.put("res", null);
return restResult(res, SUCCESS, SUCCESS_MSG);
return okWithToken(SUCCESS_MSG);
}

public static <T> R<T> ok(T data) {
return restResult(data, SUCCESS, SUCCESS_MSG);
}

public static <T> R<Map<String, Object>> okWithToken(T data) {
Map<String, Object> res = new HashMap<String, Object>();
Map<String, Object> res = new HashMap<>();
res.put("token", StpUtil.getTokenValue());
res.put("res", data);
return restResult(res, SUCCESS, SUCCESS_MSG);
Expand All @@ -117,7 +111,7 @@ public static <T> R<T> ok(String msg) {
}

public static <T> R<Map<String, Object>> okWithToken(String msg) {
Map<String, Object> res = new HashMap<String, Object>();
Map<String, Object> res = new HashMap<>();
res.put("token", StpUtil.getTokenValue());
res.put("res", null);
return restResult(res, SUCCESS, msg);
Expand All @@ -128,7 +122,7 @@ public static <T> R<T> ok(String msg, T data) {
}

public static <T> R<Map<String, Object>> okWithToken(String msg, T data) {
Map<String, Object> res = new HashMap<String, Object>();
Map<String, Object> res = new HashMap<>();
res.put("token", StpUtil.getTokenValue());
res.put("res", data);
return restResult(res, SUCCESS, msg);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package top.sharehome.springbootinittemplate.common.base;

import lombok.Getter;
import top.sharehome.springbootinittemplate.config.i18n.I18nManager;

/**
* todo 这里主要记录开发者个人的返回码枚举值,模板中扮演的角色是HttpStatus的补充,主要搭配自定义异常和统一返回类一起使用
Expand Down Expand Up @@ -273,14 +274,18 @@ public enum ReturnCode {
*/
PDF_FILE_ERROR(40002, "处理PDF文件出错");


final private int code;

final private String msg;
private String msg;

ReturnCode(int code, String msg) {
this.code = code;
this.msg = msg;
}

public ReturnCode toI18n() {
this.msg = I18nManager.getMessage(this.name().toLowerCase().replace("_", "."));
return this;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package top.sharehome.springbootinittemplate.config.encrypt;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import top.sharehome.springbootinittemplate.config.encrypt.condition.EncryptCondition;
import top.sharehome.springbootinittemplate.utils.encrypt.AESUtils;
import top.sharehome.springbootinittemplate.utils.encrypt.RSAUtils;

import javax.annotation.PostConstruct;
import javax.crypto.SecretKey;
import java.security.KeyPair;
import java.util.concurrent.CompletableFuture;

/**
* 加密配置
*
* @author AntonyCheng
*/
@Configuration
@Conditional({EncryptCondition.class})
@Slf4j
public class EncryptConfiguration {

public static String RSAPublicKey = null;

public static String RSAPrivateKey = null;

public static String AESSecretKey = null;

static {
CompletableFuture.runAsync(() -> {
KeyPair keyPair = RSAUtils.generateKeyPair(4096);
RSAPublicKey = RSAUtils.getStringFromPublicKey(keyPair.getPublic());
RSAPrivateKey = RSAUtils.getStringFromPrivateKey(keyPair.getPrivate());
SecretKey secretKey = AESUtils.generateKey(32);
AESSecretKey = AESUtils.getStringFromKey(secretKey);
log.info("############ Encryption Key is Generated");
});
}

/**
* 依赖注入日志输出
*/
@PostConstruct
private void initDi() {
log.info("############ {} Configuration DI.", this.getClass().getSimpleName().split("\\$\\$")[0]);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package top.sharehome.springbootinittemplate.config.encrypt.annotation;

import java.lang.annotation.*;

/**
* 需要RSA算法解密的方法注解
*
* @author AntonyCheng
*/
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RSADecrypt {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package top.sharehome.springbootinittemplate.config.encrypt.annotation;

import java.lang.annotation.*;

/**
* 需要RSA算法加密的参数或字段注解
*
* @author AntonyCheng
*/
@Inherited
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RSAEncrypt {
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package top.sharehome.springbootinittemplate.config.i18n.condition;
package top.sharehome.springbootinittemplate.config.encrypt.condition;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
* 国际化自定义配置条件
* 请求参数加密自定义配置条件
*
* @author AntonyCheng
*/
public class I18nCondition implements Condition {
public class EncryptCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String property = context.getEnvironment().getProperty("spring.messages.enable");
return StringUtils.equals(Boolean.TRUE.toString(), property);
String encryptProperty = context.getEnvironment().getProperty("encrypt.enable");
return StringUtils.equals(Boolean.TRUE.toString(), encryptProperty);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package top.sharehome.springbootinittemplate.config.encrypt.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* 请求参数加密配置
*
* @author AntonyCheng
*/
@Data
@ConfigurationProperties(prefix = "encrypt")
public class EncryptProperties {

/**
* 请求参数加密开关
*/
private Boolean enable = false;

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import top.sharehome.springbootinittemplate.config.i18n.condition.I18nCondition;

import javax.annotation.PostConstruct;
import java.util.Locale;
Expand All @@ -17,7 +15,6 @@
* @author AntonyCheng
*/
@Component
@Conditional(I18nCondition.class)
@Slf4j
public class I18nManager {

Expand All @@ -29,10 +26,11 @@ public I18nManager(MessageSource messageSource) {
}

public static String getMessage(String key) {
return getMessage(key, null);
Locale locale = LocaleContextHolder.getLocale();
return messageSource.getMessage(key, null, locale);
}

public static String getMessage(String key, Object[] args) {
public static String getMessage(String key, Object... args) {
Locale locale = LocaleContextHolder.getLocale();
return messageSource.getMessage(key, args, locale);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package top.sharehome.springbootinittemplate.config.i18n.controller;

import org.springframework.context.annotation.Conditional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import top.sharehome.springbootinittemplate.common.base.R;
import top.sharehome.springbootinittemplate.common.base.ReturnCode;
import top.sharehome.springbootinittemplate.config.i18n.I18nManager;
import top.sharehome.springbootinittemplate.config.i18n.condition.I18nCondition;
import top.sharehome.springbootinittemplate.exception.customize.CustomizeReturnException;

import java.util.Random;

/**
* 国际化示例控制器
* 国际化示例控制器(测试时)
*
* @author AntonyCheng
*/
@RestController
@Conditional(I18nCondition.class)
public class I18nDemoController {

@GetMapping("/i18n")
public R<String> welcome(@RequestParam String name) {
return R.ok(I18nManager.getMessage("msg_welcome", new String[]{name}));
int seed = new Random().nextInt();
if (seed % 2 == 0) {
throw new CustomizeReturnException(ReturnCode.ACCOUNT_AND_EMAIL_DO_NOT_MATCH.toI18n());
}else {
return R.ok(I18nManager.getMessage("welcome", name));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import top.sharehome.springbootinittemplate.config.caffeine.properties.CaffeineProperties;
import top.sharehome.springbootinittemplate.config.i18n.condition.I18nCondition;
import top.sharehome.springbootinittemplate.config.i18n.interceptor.I18nInterceptor;
import top.sharehome.springbootinittemplate.config.i18n.properties.I18nProperties;

Expand All @@ -20,7 +17,6 @@
@Configuration
@EnableConfigurationProperties(I18nProperties.class)
@AllArgsConstructor
@Conditional(I18nCondition.class)
public class I18nInterceptorConfiguration implements WebMvcConfigurer {

private final I18nProperties i18nProperties;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@
public class I18nProperties {

/**
* 是否开启国际化
*/
private Boolean enable = false;

/**
* 默认语言
* 默认语言,默认简体中文
*/
private LocaleType defaultLocale = LocaleType.ZH_CN;

Expand Down
Loading

0 comments on commit a02d37f

Please sign in to comment.