实现了国际化

This commit is contained in:
dengqichen 2024-11-26 17:21:07 +08:00
parent 5130c7593a
commit ee1e20daff
13 changed files with 211 additions and 55 deletions

View File

@ -1,7 +1,9 @@
package com.qqchen.deploy.backend.api;
import com.qqchen.deploy.backend.common.controller.BaseController;
import com.qqchen.deploy.backend.common.dto.Response;
import com.qqchen.deploy.backend.common.api.Response;
import com.qqchen.deploy.backend.common.enums.ResponseCode;
import com.qqchen.deploy.backend.common.utils.MessageUtils;
import com.qqchen.deploy.backend.converter.UserConverter;
import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.dto.query.UserQuery;
@ -32,7 +34,7 @@ public class UserApiController extends BaseController<User, Long, UserQuery, Use
public Response<UserResponse> register(@Validated @RequestBody UserRegisterRequest request) {
// 基础的注册逻辑
if (!request.getPassword().equals(request.getConfirmPassword())) {
return Response.error(Response.INVALID_PARAM_CODE, "两次密码不一致");
return Response.error(ResponseCode.USER_NOT_FOUND);
}
User user = converter.toEntity(request);

View File

@ -0,0 +1,53 @@
package com.qqchen.deploy.backend.common.api;
import com.qqchen.deploy.backend.common.enums.ResponseCode;
import com.qqchen.deploy.backend.common.utils.MessageUtils;
import lombok.Data;
import java.io.Serializable;
@Data
public class Response<T> implements Serializable {
private boolean success;
private String message;
private T data;
private Integer code;
public static <T> Response<T> success() {
Response<T> response = new Response<>();
response.setSuccess(true);
response.setCode(ResponseCode.SUCCESS.getCode());
response.setMessage(MessageUtils.getMessage(ResponseCode.SUCCESS.getMessageKey()));
return response;
}
public static <T> Response<T> success(T data) {
Response<T> response = new Response<>();
response.setSuccess(true);
response.setCode(ResponseCode.SUCCESS.getCode());
response.setMessage(MessageUtils.getMessage(ResponseCode.SUCCESS.getMessageKey()));
response.setData(data);
return response;
}
public static <T> Response<T> error(ResponseCode responseCode) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setCode(responseCode.getCode());
response.setMessage(MessageUtils.getMessage(responseCode.getMessageKey()));
return response;
}
public static <T> Response<T> error(ResponseCode responseCode, Object... args) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setCode(responseCode.getCode());
response.setMessage(MessageUtils.getMessage(responseCode.getMessageKey(), args));
return response;
}
}

View File

@ -0,0 +1,32 @@
package com.qqchen.deploy.backend.common.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@Configuration
public class MessageConfig {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages");
messageSource.setDefaultEncoding("UTF-8");
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return localeResolver;
}
}

View File

@ -2,7 +2,9 @@ package com.qqchen.deploy.backend.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@ -15,4 +17,11 @@ public class WebConfig implements WebMvcConfigurer {
.allowedHeaders("*") // 允许所有header
.maxAge(3600); // 预检请求的有效期单位为秒
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
}

View File

@ -4,7 +4,7 @@ import com.qqchen.deploy.backend.common.domain.Entity;
import com.qqchen.deploy.backend.common.converter.BaseConverter;
import com.qqchen.deploy.backend.common.query.BaseQuery;
import com.qqchen.deploy.backend.common.dto.BaseRequest;
import com.qqchen.deploy.backend.common.dto.Response;
import com.qqchen.deploy.backend.common.api.Response;
import com.qqchen.deploy.backend.common.service.BaseService;
import jakarta.annotation.Resource;
import org.springframework.data.domain.Page;

View File

@ -1,45 +0,0 @@
package com.qqchen.deploy.backend.common.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 通用响应对象
*/
@Data
public class Response<T> implements Serializable {
private boolean success;
private String message;
private T data;
private Integer code;
public static final int SUCCESS_CODE = 200;
public static final int ERROR_CODE = 500;
public static final int INVALID_PARAM_CODE = 400;
public static final int UNAUTHORIZED_CODE = 401;
public static <T> Response<T> success() {
return success(null);
}
public static <T> Response<T> success(T data) {
Response<T> response = new Response<>();
response.setSuccess(true);
response.setCode(SUCCESS_CODE);
response.setData(data);
return response;
}
public static <T> Response<T> error(String message) {
return error(ERROR_CODE, message);
}
public static <T> Response<T> error(Integer code, String message) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setCode(code);
response.setMessage(message);
return response;
}
}

View File

@ -0,0 +1,28 @@
package com.qqchen.deploy.backend.common.enums;
import lombok.Getter;
@Getter
public enum ResponseCode {
SUCCESS(200, "response.success"),
ERROR(500, "response.error"),
INVALID_PARAM(400, "response.invalid.param"),
UNAUTHORIZED(401, "response.unauthorized"),
FORBIDDEN(403, "response.forbidden"),
NOT_FOUND(404, "response.not.found"),
CONFLICT(409, "response.conflict"),
// 业务错误码
USER_NOT_FOUND(1001, "user.not.found"),
USERNAME_EXISTS(1002, "user.username.exists"),
EMAIL_EXISTS(1003, "user.email.exists");
private final int code;
private final String messageKey; // 国际化消息key
ResponseCode(int code, String messageKey) {
this.code = code;
this.messageKey = messageKey;
}
}

View File

@ -12,27 +12,37 @@ public class EntityPathResolver {
public static Path<?> getPath(EntityPath<?> entityPath, String fieldName) {
try {
// 首先尝试直接获取字段
// 1. 首先尝试直接获取字段
try {
Field field = entityPath.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (Path<?>) field.get(entityPath);
} catch (NoSuchFieldException e) {
// 如果找不到尝试从_super中获取
// 2. 尝试从_super中获取
Field superField = entityPath.getClass().getDeclaredField("_super");
superField.setAccessible(true);
Object superInstance = superField.get(entityPath);
if (superInstance != null) {
try {
// 直接从_super中获取字段
Field field = superInstance.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (Path<?>) field.get(superInstance);
} catch (NoSuchFieldException ex) {
// 打印调试信息
log.debug("Field {} not found in _super, available fields:", fieldName);
for (Field field : superInstance.getClass().getDeclaredFields()) {
log.debug("Field name in _super: {}", field.getName());
// 3. 尝试从_super.entity中获取
try {
Field entityField = superInstance.getClass().getDeclaredField("entity");
entityField.setAccessible(true);
Object entityInstance = entityField.get(superInstance);
if (entityInstance != null) {
Field field = entityInstance.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (Path<?>) field.get(entityInstance);
}
} catch (NoSuchFieldException | IllegalAccessException innerEx) {
log.debug("Field {} not found in _super.entity", fieldName);
}
}
}

View File

@ -0,0 +1,30 @@
package com.qqchen.deploy.backend.common.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
@Component
public class MessageUtils {
private static MessageSource messageSource;
public MessageUtils(MessageSource messageSource) {
MessageUtils.messageSource = messageSource;
}
public static String getMessage(String key) {
try {
return messageSource.getMessage(key, null, LocaleContextHolder.getLocale());
} catch (Exception e) {
return key;
}
}
public static String getMessage(String key, Object... args) {
try {
return messageSource.getMessage(key, args, LocaleContextHolder.getLocale());
} catch (Exception e) {
return key;
}
}
}

View File

@ -1,7 +1,7 @@
package com.qqchen.deploy.backend.controller;
import com.qqchen.deploy.backend.api.UserApiController;
import com.qqchen.deploy.backend.common.dto.Response;
import com.qqchen.deploy.backend.common.api.Response;
import com.qqchen.deploy.backend.converter.UserConverter;
import com.qqchen.deploy.backend.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;

View File

@ -20,8 +20,21 @@ spring:
time_zone: Asia/Shanghai
mvc:
log-request-details: true # \u6253\u5370\u8BF7\u6C42\u8BE6\u60C5
messages:
basename: messages
encoding: UTF-8
fallback-to-system-locale: false
messages:
basename: messages
encoding: UTF-8
fallback-to-system-locale: false
always-use-message-format: false
use-code-as-default-message: true
cache-duration: 3600
logging:
level:
org.springframework.web: DEBUG
org.springframework.context.i18n: DEBUG
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: TRACE # \u6253\u5370\u6240\u6709\u6CE8\u518C\u7684\u63A5\u53E3\u8DEF\u5F84
org.hibernate.type.descriptor.sql.BasicBinder: TRACE # \u663E\u793ASQL\u53C2\u6570
org.hibernate.type.descriptor.sql: TRACE

View File

@ -0,0 +1,12 @@
# 中文
response.success=操作成功
response.error=系统错误
response.invalid.param=无效的参数
response.unauthorized=未授权
response.forbidden=禁止访问
response.not.found=资源未找到
response.conflict=资源冲突
user.not.found=用户不存在
user.username.exists=用户名已存在
user.email.exists=邮箱已存在

View File

@ -0,0 +1,12 @@
# \u9ED8\u8BA4\u8BED\u8A00\uFF08\u82F1\u6587\uFF09
response.success=Success
response.error=System Error
response.invalid.param=Invalid Parameter
response.unauthorized=Unauthorized
response.forbidden=Forbidden
response.not.found=Resource Not Found
response.conflict=Resource Conflict
user.not.found=User not found
user.username.exists=Username already exists
user.email.exists=Email already exists