Skip to content

Commit 26a293e

Browse files
committed
[fit] 实现请求地区解析
1 parent aaad077 commit 26a293e

File tree

5 files changed

+267
-0
lines changed

5 files changed

+267
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
package modelengine.fit.http.util.i18n;
7+
8+
import modelengine.fit.http.Cookie;
9+
import modelengine.fit.http.server.HttpClassicServerRequest;
10+
import modelengine.fit.http.server.HttpClassicServerResponse;
11+
12+
import java.util.Locale;
13+
14+
15+
public class DefualtLocaleResolver implements LocaleResolver{
16+
17+
public static final String DEFAULT_COOKIE_NAME = "locale";
18+
public static final int DEFAULT_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
19+
public static final String DEFAULT_COOKIE_DOMAIN = "/";
20+
public static final String DEFAULT_COOKIE_PATH = "/";
21+
private String cookieName = DEFAULT_COOKIE_NAME;
22+
private int cookieMaxAge = DEFAULT_COOKIE_MAX_AGE;
23+
private String cookieDomain = DEFAULT_COOKIE_DOMAIN;
24+
private String cookiePath = DEFAULT_COOKIE_PATH;
25+
private Locale defaultLocale;
26+
27+
@Override
28+
public Locale resolveLocale(HttpClassicServerRequest request) {
29+
// 先解析 Cookie,如果没有则使用 Accept-Language 头
30+
String newLocale = request.cookies().get(this.cookieName).map(Cookie::value).orElse(null);
31+
if(newLocale != null){
32+
return Locale.forLanguageTag(newLocale);
33+
}
34+
35+
String acceptLanguage = request.headers().require("Accept-Language");
36+
if (acceptLanguage != null && !acceptLanguage.trim().isEmpty()) {
37+
return Locale.forLanguageTag(acceptLanguage);
38+
}
39+
40+
return defaultLocale;
41+
}
42+
43+
@Override
44+
public void setLocale(HttpClassicServerResponse response, Locale locale) {
45+
46+
if(locale != null){
47+
response.cookies().add(Cookie.builder()
48+
.name(cookieName)
49+
.value(locale.toLanguageTag())
50+
.maxAge(cookieMaxAge)
51+
.domain(cookieDomain)
52+
.path(cookiePath)
53+
.build());
54+
}else{
55+
response.cookies().add(Cookie.builder()
56+
.name(cookieName)
57+
.maxAge(0)
58+
.build());
59+
}
60+
}
61+
62+
public void setCookieName(String cookieName) {
63+
this.cookieName = cookieName;
64+
}
65+
66+
public void setCookieMaxAge(int cookieMaxAge) {
67+
this.cookieMaxAge = cookieMaxAge;
68+
}
69+
70+
public void setCookieDomain(String cookieDomain) {
71+
this.cookieDomain = cookieDomain;
72+
}
73+
74+
public void setCookiePath(String cookiePath) {
75+
this.cookiePath = cookiePath;
76+
}
77+
78+
public void setDefaultLocale(Locale defaultLocale) {
79+
this.defaultLocale = defaultLocale;
80+
}
81+
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.http.util.i18n;
8+
9+
import java.util.Locale;
10+
11+
/**
12+
* 地区上下文,包含地区信息
13+
*
14+
* @author fit-framework
15+
* @since 2025-01-01
16+
*/
17+
public class LocaleContext {
18+
private final Locale locale;
19+
20+
public LocaleContext(Locale locale) {
21+
this.locale = locale;
22+
}
23+
24+
public Locale getLocale() {
25+
return locale;
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.http.util.i18n;
8+
9+
import java.util.Locale;
10+
11+
12+
public class LocaleContextHolder {
13+
14+
private static final ThreadLocal<LocaleContext> LOCALE_CONTEXT_HOLDER = new ThreadLocal<>();
15+
16+
/**
17+
* 设置当前线程的地区上下文
18+
*/
19+
public static void setLocaleContext(LocaleContext localeContext) {
20+
LOCALE_CONTEXT_HOLDER.set(localeContext);
21+
}
22+
23+
/**
24+
* 获取当前线程的地区上下文
25+
*/
26+
public static LocaleContext getLocaleContext() {
27+
return LOCALE_CONTEXT_HOLDER.get();
28+
}
29+
30+
/**
31+
* 获取当前线程的地区
32+
*/
33+
public static Locale getLocale() {
34+
LocaleContext context = getLocaleContext();
35+
return context != null ? context.getLocale() : Locale.getDefault();
36+
}
37+
38+
39+
/**
40+
* 清除当前线程的地区上下文
41+
*/
42+
public static void clear() {
43+
LOCALE_CONTEXT_HOLDER.remove();
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package modelengine.fit.http.util.i18n;
2+
3+
import modelengine.fit.http.server.*;
4+
import modelengine.fitframework.annotation.Scope;
5+
6+
import java.util.List;
7+
import java.util.Locale;
8+
9+
public class LocaleResolveFilter implements HttpServerFilter {
10+
11+
private LocaleResolver localeResolver = null;
12+
13+
private List<String> matchPatterns = List.of("/**");
14+
15+
private List<String> mismatchPatterns = null;
16+
17+
private Scope scope = Scope.GLOBAL;
18+
19+
public LocaleResolveFilter(LocaleResolver localeResolver) {
20+
localeResolver = localeResolver;
21+
}
22+
23+
public LocaleResolveFilter(){
24+
this.localeResolver = new DefualtLocaleResolver();
25+
}
26+
27+
@Override
28+
public String name() {
29+
return "LocaleResolveFilter";
30+
}
31+
32+
@Override
33+
public int priority() {
34+
return 0;
35+
}
36+
37+
@Override
38+
public List<String> matchPatterns() {
39+
return matchPatterns;
40+
}
41+
42+
@Override
43+
public List<String> mismatchPatterns() {
44+
return mismatchPatterns;
45+
}
46+
47+
@Override
48+
public void doFilter(HttpClassicServerRequest request, HttpClassicServerResponse response, HttpServerFilterChain chain) throws DoHttpServerFilterException {
49+
try {
50+
// 如果参数中带有地区,则直接设置地区
51+
String paramLocale = request.queries().first("locale").orElse( null);
52+
Locale responseLocale = null;
53+
if(paramLocale != null && !paramLocale.trim().isEmpty()){
54+
responseLocale = Locale.forLanguageTag(paramLocale);
55+
LocaleContextHolder.setLocaleContext(new LocaleContext(responseLocale));
56+
}
57+
// 如果参数中不包含地区,则解析
58+
else{
59+
Locale locale =localeResolver.resolveLocale(request);
60+
LocaleContextHolder.setLocaleContext(new LocaleContext(locale));
61+
}
62+
63+
chain.doFilter(request, response);
64+
65+
// responseLocale是用户期望设置的地区,不受 server 端处理的影响
66+
localeResolver.setLocale(response, responseLocale);
67+
}finally {
68+
LocaleContextHolder.clear();
69+
}
70+
71+
}
72+
73+
@Override
74+
public Scope scope() {
75+
return scope;
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
package modelengine.fit.http.util.i18n;
7+
8+
import modelengine.fit.http.server.HttpClassicServerRequest;
9+
import modelengine.fit.http.server.HttpClassicServerResponse;
10+
11+
import java.util.Locale;
12+
13+
/**
14+
* 地区解析器接口,用于从HTTP请求中解析用户的地区设置
15+
*
16+
* @author fit-framework
17+
* @since 2025-01-01
18+
*/
19+
public interface LocaleResolver {
20+
21+
/**
22+
* 解析用户的地区设置
23+
*
24+
* @param request HTTP请求 {@link HttpClassicServerRequest}。
25+
* @return 解析出来的地区 {@link Locale}。
26+
*/
27+
Locale resolveLocale(HttpClassicServerRequest request);
28+
29+
/**
30+
* 设置地区到响应中
31+
*
32+
* @param response HTTP响应 {@link HttpClassicServerResponse}。
33+
* @param locale 要设置的地区 {@link Locale}。
34+
*/
35+
void setLocale(HttpClassicServerResponse response, Locale locale);
36+
}

0 commit comments

Comments
 (0)