1、cf-gateway locale透传修复;2、LocaleResolver修改为全局web服务配置;

This commit is contained in:
gaoqr
2026-05-13 11:45:03 +08:00
parent db2e31680c
commit 8438563147
5 changed files with 45 additions and 34 deletions
@@ -4,6 +4,8 @@ import com.cf.imes.framework.common.exception.enums.ServiceErrorCodeRange;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.util.Locale;
/** /**
* 业务逻辑异常 Exception * 业务逻辑异常 Exception
*/ */
@@ -22,6 +24,8 @@ public final class ServiceException extends RuntimeException {
*/ */
private String message; private String message;
private Locale locale;
/** /**
* 占位参数 * 占位参数
*/ */
@@ -44,6 +48,19 @@ public final class ServiceException extends RuntimeException {
this.message = message; this.message = message;
} }
public ServiceException(ErrorCode errorCode, Locale locale, Object... args) {
this.code = errorCode.getCode();
this.locale = locale;
this.message = errorCode.getMsg();
this.args = args;
}
public ServiceException(Integer code, Locale locale, String message) {
this.code = code;
this.locale = locale;
this.message = message;
}
public Integer getCode() { public Integer getCode() {
return code; return code;
} }
@@ -24,11 +24,15 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.Filter; import jakarta.servlet.Filter;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import java.util.Locale;
@AutoConfiguration @AutoConfiguration
@EnableConfigurationProperties(WebProperties.class) @EnableConfigurationProperties(WebProperties.class)
@@ -60,6 +64,13 @@ public class ChenfengWebAutoConfiguration implements WebMvcConfigurer {
&& antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包 && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包
} }
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
@Bean @Bean
public I18nUtils i18nUtils(MessageSource messageSource) { public I18nUtils i18nUtils(MessageSource messageSource) {
return new I18nUtils(messageSource); return new I18nUtils(messageSource);
@@ -17,7 +17,6 @@ import jakarta.annotation.Resource;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction; import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction;
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -83,14 +82,6 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
// 移除 login-user 的请求头,避免伪造模拟 // 移除 login-user 的请求头,避免伪造模拟
SecurityFrameworkUtils.removeLoginUser(exchange); SecurityFrameworkUtils.removeLoginUser(exchange);
String Language = exchange.getRequest()
.getHeaders()
.getFirst("Accept-Language");
if (StrUtil.isEmpty(Language)) {
Language = Locale.CHINA.getLanguage();
}
LocaleContextHolder.setLocale(Locale.forLanguageTag(Language));
// 情况一,如果没有 Token 令牌,则直接继续 filter // 情况一,如果没有 Token 令牌,则直接继续 filter
String token = SecurityFrameworkUtils.obtainAuthorization(exchange); String token = SecurityFrameworkUtils.obtainAuthorization(exchange);
if (CharSequenceUtil.isEmpty(token)) { if (CharSequenceUtil.isEmpty(token)) {
@@ -114,8 +105,6 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
return chain.filter(exchange); return chain.filter(exchange);
} }
System.out.println("Accept-Language BEFORE = "
+ exchange.getRequest().getHeaders().getFirst("Accept-Language"));
// 情况二,如果有 Token 令牌,则解析对应 userId、userType、organId 等字段,并通过 通过 Header 转发给服务 // 情况二,如果有 Token 令牌,则解析对应 userId、userType、organId 等字段,并通过 通过 Header 转发给服务
// 重要说明:defaultIfEmpty 作用,保证 Mono.empty() 情况,可以继续执行 `flatMap 的 chain.filter(exchange)` 逻辑,避免返回给前端空的 Response!! // 重要说明:defaultIfEmpty 作用,保证 Mono.empty() 情况,可以继续执行 `flatMap 的 chain.filter(exchange)` 逻辑,避免返回给前端空的 Response!!
@@ -140,9 +129,14 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
// 用token从checktoken api中获取当前用户 // 用token从checktoken api中获取当前用户
Long organId = WebFrameworkUtils.getOrganId(exchange); Long organId = WebFrameworkUtils.getOrganId(exchange);
return checkAccessToken(organId, token).flatMap((Function<String, Mono<LoginUser>>) body -> { return checkAccessToken(organId, token).flatMap((Function<String, Mono<LoginUser>>) body -> {
System.out.println("Accept-Language CHECKTOKEN = " String language = exchange.getRequest().getHeaders().getFirst("Accept-Language");
+ exchange.getRequest().getHeaders().getFirst("Accept-Language")); Locale locale;
LoginUser remoteUser = buildUser(body); if(StrUtil.isEmpty(language)) {
locale = Locale.CHINA;
} else {
locale = Locale.forLanguageTag(language);
}
LoginUser remoteUser = buildUser(body, locale);
if (remoteUser != null) { if (remoteUser != null) {
return Mono.just(remoteUser); return Mono.just(remoteUser);
} }
@@ -162,7 +156,7 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
.retrieve().bodyToMono(String.class); .retrieve().bodyToMono(String.class);
} }
private LoginUser buildUser(String body) { private LoginUser buildUser(String body, Locale locale) {
CommonResult commonResult = JsonUtils.parseObject(body, TOKEN_RESULT); CommonResult commonResult = JsonUtils.parseObject(body, TOKEN_RESULT);
if(commonResult != null) { if(commonResult != null) {
@@ -171,15 +165,15 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
Object[] args = commonResult.getArgs(); Object[] args = commonResult.getArgs();
if(code != 0) { if(code != 0) {
if (TOKEN_TIME_IS_EXPIRES.getCode().equals(code)) { if (TOKEN_TIME_IS_EXPIRES.getCode().equals(code)) {
throw new ServiceException(TOKEN_TIME_IS_EXPIRES); throw new ServiceException(TOKEN_TIME_IS_EXPIRES, locale);
} else if (TOKEN_CONFIG_NOT_EXISTS.getCode().equals(code)) { } else if (TOKEN_CONFIG_NOT_EXISTS.getCode().equals(code)) {
throw new ServiceException(TOKEN_CONFIG_NOT_EXISTS); throw new ServiceException(TOKEN_CONFIG_NOT_EXISTS, locale);
} else if (ORGAN_NOT_EXISTS.getCode().equals(code)) { } else if (ORGAN_NOT_EXISTS.getCode().equals(code)) {
throw new ServiceException(ORGAN_NOT_EXISTS); throw new ServiceException(ORGAN_NOT_EXISTS, locale);
} else if (ORGAN_DISABLE.getCode().equals(code)) { } else if (ORGAN_DISABLE.getCode().equals(code)) {
throw new ServiceException(new ErrorCode(code, msg), args); throw new ServiceException(new ErrorCode(code, msg), locale, args);
} else if (ORGAN_EXPIRE.getCode().equals(code)) { } else if (ORGAN_EXPIRE.getCode().equals(code)) {
throw new ServiceException(new ErrorCode(code, msg), args); throw new ServiceException(new ErrorCode(code, msg), locale, args);
} }
} }
} }
@@ -7,7 +7,6 @@ import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import com.cf.imes.gateway.util.WebFrameworkUtils; import com.cf.imes.gateway.util.WebFrameworkUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponse;
@@ -70,17 +69,17 @@ public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
*/ */
@ExceptionHandler(value = Exception.class) @ExceptionHandler(value = Exception.class)
public CommonResult defaultExceptionHandler(ServerWebExchange exchange, public CommonResult defaultExceptionHandler(ServerWebExchange exchange,
Throwable ex) { Throwable ex) {
ServerHttpRequest request = exchange.getRequest(); ServerHttpRequest request = exchange.getRequest();
log.error("[defaultExceptionHandler][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex); log.error("[defaultExceptionHandler][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex);
// TODO 晨丰:是否要插入异常日志呢? // TODO 晨丰:是否要插入异常日志呢?
// 返回 ERROR CommonResult // 返回 ERROR CommonResult
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ERROR_PATH, INTERNAL_SERVER_ERROR.getMsg(), null, LocaleContextHolder.getLocale(), null)); return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ERROR_PATH, INTERNAL_SERVER_ERROR.getMsg(), null, exchange.getLocaleContext().getLocale(), null));
} }
@ExceptionHandler(value = ServiceException.class) @ExceptionHandler(value = ServiceException.class)
public CommonResult serviceExceptionHandler(ServiceException ex) { public CommonResult serviceExceptionHandler(ServiceException ex) {
String errMsg = ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ERROR_PATH, ex.getMessage(), null, LocaleContextHolder.getLocale(), null); String errMsg = ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ERROR_PATH, ex.getMessage(), null, ex.getLocale(), null);
// 系统异常输出堆栈 // 系统异常输出堆栈
if (INTERNAL_SERVER_ERROR.getCode().equals(ex.getCode())) { if (INTERNAL_SERVER_ERROR.getCode().equals(ex.getCode())) {
log.info("[serviceExceptionHandler]", ex); log.info("[serviceExceptionHandler]", ex);
@@ -3,20 +3,10 @@ package com.cf.imes.module.system.framework.trans.config;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import java.util.Locale;
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(TransProperties.class) @EnableConfigurationProperties(TransProperties.class)
public class TransConfiguration { public class TransConfiguration {
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
@Bean @Bean
public TransApi transApi(TransProperties transProperties) { public TransApi transApi(TransProperties transProperties) {