Skip to content

Commit dfec108

Browse files
committed
可用的多插件地区解析实现
1 parent f1b5130 commit dfec108

File tree

21 files changed

+208
-159
lines changed

21 files changed

+208
-159
lines changed

examples/fit-example/02-static-plugin/app-assistant/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@
3939
<artifactId>default-weather-for-static</artifactId>
4040
<version>1.0-SNAPSHOT</version>
4141
</dependency>
42+
<dependency>
43+
<groupId>org.fitframework.example</groupId>
44+
<artifactId>other-weather-for-static</artifactId>
45+
<version>1.0-SNAPSHOT</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>org.fitframework.plugin</groupId>
49+
<artifactId>fit-i18n-registry</artifactId>
50+
<version>${fit.version}</version>
51+
</dependency>
4252
</dependencies>
4353

4454
<build>

examples/fit-example/02-static-plugin/app-assistant/src/main/java/modelengine/fit/example/controller/AssistantController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import modelengine.fit.http.annotation.GetMapping;
1111
import modelengine.fitframework.annotation.Component;
1212
import modelengine.fitframework.annotation.Fit;
13+
import modelengine.fitframework.util.LocaleContextHolder;
1314

1415
/**
1516
* 表示控制器。
@@ -30,8 +31,8 @@ public AssistantController(@Fit Weather weather) {
3031
*
3132
* @return 表示天气信息的 {@link String}。
3233
*/
33-
@GetMapping(path = "/weather")
34+
@GetMapping(path = "/locale")
3435
public String getWeather() {
35-
return this.weather.get();
36+
return LocaleContextHolder.getLocale().getLanguage();
3637
}
3738
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package modelengine.fit.example.controller;
2+
3+
import modelengine.fit.http.annotation.GetMapping;
4+
import modelengine.fit.http.annotation.RequestMapping;
5+
import modelengine.fitframework.annotation.Component;
6+
import modelengine.fitframework.util.LocaleContextHolder;
7+
8+
@Component
9+
@RequestMapping(path = "/1")
10+
public class controller2 {
11+
@GetMapping(path = "/weather")
12+
public String getWeather() {
13+
return LocaleContextHolder.getLocale().getLanguage();
14+
}
15+
}

examples/fit-example/02-static-plugin/plugin-default-weather/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
<artifactId>weather-for-static</artifactId>
3535
<version>1.0-SNAPSHOT</version>
3636
</dependency>
37+
<dependency>
38+
<groupId>org.fitframework.service</groupId>
39+
<artifactId>fit-http-classic</artifactId>
40+
<version>${fit.version}</version>
41+
</dependency>
3742
</dependencies>
3843

3944
<build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package modelengine.fit.example;
2+
3+
import modelengine.fit.http.server.HttpClassicServerRequest;
4+
import modelengine.fit.http.server.HttpClassicServerResponse;
5+
import modelengine.fit.http.util.i18n.DefualtLocaleResolver;
6+
import modelengine.fit.http.util.i18n.LocaleResolver;
7+
import modelengine.fitframework.annotation.Bean;
8+
import modelengine.fitframework.annotation.Component;
9+
10+
import java.util.Locale;
11+
12+
@Component
13+
public class DefalutLocaleResolveConfig {
14+
@Bean
15+
public LocaleResolver localeResolver2() {
16+
LocaleResolver localeResolver = new LocaleResolver() {
17+
@Override
18+
public Locale resolveLocale(HttpClassicServerRequest request) {
19+
return Locale.forLanguageTag("en-US");
20+
}
21+
22+
@Override
23+
public void setLocale(HttpClassicServerResponse response, Locale locale) {
24+
25+
}
26+
27+
@Override
28+
public String getUrlPattern() {
29+
return "/locale";
30+
}
31+
32+
@Override
33+
public void setUrlPattern(String urlPattern) {
34+
35+
}
36+
};
37+
return localeResolver;
38+
}
39+
}

examples/fit-example/02-static-plugin/plugin-other-weather/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
<artifactId>weather-for-static</artifactId>
3535
<version>1.0-SNAPSHOT</version>
3636
</dependency>
37+
<dependency>
38+
<groupId>org.fitframework.service</groupId>
39+
<artifactId>fit-http-classic</artifactId>
40+
<version>${fit.version}</version>
41+
</dependency>
3742
</dependencies>
3843

3944
<build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package modelengine.fit.example;
2+
3+
import modelengine.fit.http.server.HttpClassicServerRequest;
4+
import modelengine.fit.http.server.HttpClassicServerResponse;
5+
import modelengine.fit.http.util.i18n.DefualtLocaleResolver;
6+
import modelengine.fit.http.util.i18n.LocaleResolver;
7+
import modelengine.fitframework.annotation.Bean;
8+
import modelengine.fitframework.annotation.Component;
9+
10+
import java.util.Locale;
11+
12+
@Component
13+
public class OtherLocaleResolveConfig {
14+
@Bean
15+
public LocaleResolver localeResolver1() {
16+
LocaleResolver localeResolver = new LocaleResolver() {
17+
@Override
18+
public Locale resolveLocale(HttpClassicServerRequest request) {
19+
return Locale.forLanguageTag("cn");
20+
}
21+
22+
@Override
23+
public void setLocale(HttpClassicServerResponse response, Locale locale) {
24+
25+
}
26+
27+
@Override
28+
public String getUrlPattern() {
29+
return "/locale";
30+
}
31+
32+
@Override
33+
public void setUrlPattern(String urlPattern) {
34+
35+
}
36+
};
37+
return localeResolver;
38+
}
39+
}

framework/fit/java/fit-builtin/plugins/fit-i18n-registry/src/main/java/modelengine/fitframework/i18n/LocaleResolveFilter.java

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import modelengine.fit.http.server.HttpClassicServerResponse;
66
import modelengine.fit.http.server.HttpServerFilter;
77
import modelengine.fit.http.server.HttpServerFilterChain;
8-
import modelengine.fit.http.util.i18n.DefualtLocaleResolver;
98
import modelengine.fit.http.util.i18n.LocaleResolver;
109
import modelengine.fitframework.annotation.Component;
1110
import modelengine.fitframework.annotation.Scope;
@@ -23,9 +22,6 @@
2322
*/
2423
@Component
2524
public class LocaleResolveFilter implements HttpServerFilter {
26-
27-
private LocaleResolver localeResolver = null;
28-
2925
private List<String> matchPatterns = List.of("/**");
3026

3127
private List<String> mismatchPatterns = List.of();
@@ -37,17 +33,10 @@ public class LocaleResolveFilter implements HttpServerFilter {
3733
/**
3834
* 构造函数。
3935
*
40-
* @param localeResolver 表示地区解析器的 {@link LocaleResolver}。
41-
*/
42-
public LocaleResolveFilter(LocaleResolver localeResolver, LocaleResolverRegistry localeResolverRegistry) {
43-
localeResolver = localeResolver;
44-
}
45-
46-
/**
47-
* 构造函数。
36+
* @param localeResolverRegistry 表示地区解析器注册中心的 {@link LocaleResolverRegistry}。
4837
*/
4938
public LocaleResolveFilter(LocaleResolverRegistry localeResolverRegistry) {
50-
this.localeResolver = new DefualtLocaleResolver();
39+
this.localeResolverRegistry = localeResolverRegistry;
5140
}
5241

5342
@Override
@@ -77,17 +66,15 @@ public void doFilter(HttpClassicServerRequest request, HttpClassicServerResponse
7766
// 如果参数中带有地区,说明用户想使用新地区执行后续的操作,直接设置地区。
7867
String paramLocale = request.queries().first("locale").orElse(null);
7968
Locale responseLocale = null;
69+
// 使用责任链解析 locale
70+
LocaleResolver localeResolver = localeResolverRegistry.dispatch(request);
8071
if (paramLocale != null && !paramLocale.trim().isEmpty()) {
8172
responseLocale = Locale.forLanguageTag(paramLocale);
8273
LocaleContextHolder.setLocaleContext(new LocaleContext(responseLocale));
8374
}
8475
// 如果参数中不包含地区,则解析请求所带的地区参数。
8576
else {
86-
// 使用责任链解析locale
87-
Locale locale = this.localeResolverRegistry.resolveLocale(request);
88-
if (locale == null) {
89-
locale = this.localeResolver.resolveLocale(request); // fallback
90-
}
77+
Locale locale = localeResolver.resolveLocale(request);
9178
LocaleContextHolder.setLocaleContext(new LocaleContext(locale));
9279
}
9380

framework/fit/java/fit-builtin/plugins/fit-i18n-registry/src/main/java/modelengine/fitframework/i18n/LocaleResolverEntry.java

Lines changed: 0 additions & 40 deletions
This file was deleted.

framework/fit/java/fit-builtin/plugins/fit-i18n-registry/src/main/java/modelengine/fitframework/i18n/LocaleResolverRegistry.java

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package modelengine.fitframework.i18n;
22

3+
import static modelengine.fitframework.inspection.Validation.notBlank;
4+
import static modelengine.fitframework.inspection.Validation.notNull;
5+
36
import modelengine.fit.http.server.HttpClassicServerRequest;
4-
import modelengine.fit.http.server.HttpClassicServerResponse;
57
import modelengine.fit.http.server.dispatch.MappingTree;
68
import modelengine.fit.http.server.dispatch.support.DefaultMappingTree;
9+
import modelengine.fit.http.util.i18n.DefualtLocaleResolver;
710
import modelengine.fit.http.util.i18n.LocaleResolver;
11+
import modelengine.fit.http.util.i18n.RegisterLocaleResolverException;
812
import modelengine.fitframework.annotation.Component;
913
import modelengine.fitframework.ioc.BeanContainer;
1014
import modelengine.fitframework.ioc.BeanFactory;
@@ -18,6 +22,7 @@
1822
import java.util.stream.Collectors;
1923
import modelengine.fitframework.resource.UrlUtils;
2024
import modelengine.fitframework.util.OptionalUtils;
25+
import modelengine.fitframework.util.StringUtils;
2126
import modelengine.fitframework.util.wildcard.PathPattern;
2227
import modelengine.fitframework.util.wildcard.Pattern;
2328

@@ -27,40 +32,56 @@ public class LocaleResolverRegistry implements PluginStartedObserver, PluginStop
2732

2833
// 参考DefaultHttpDispatcher的三层结构
2934
private final Map<String, LocaleResolver> noPathVariableResolvers = new ConcurrentHashMap<>();
30-
private final MappingTree<LocaleResolver> pathVariableResolvers = new DefaultMappingTree<>();
35+
private final Map<String, MappingTree<LocaleResolver>> pathVariableResolvers = new ConcurrentHashMap<>();
3136
private final Map<String, LocaleResolver> wildcardResolvers = new ConcurrentHashMap<>();
3237

38+
private final LocaleResolver defaultLocaleResolver = new DefualtLocaleResolver();
39+
40+
public LocaleResolverRegistry() {
41+
// 与 DefaultHttpDispatcher 保持一致,使用 ConcurrentHashMap 提供线程安全。
42+
this.pathVariableResolvers.put(DefaultMappingTree.PATH_SEPARATOR, new DefaultMappingTree<>());
43+
}
3344

34-
public void register(String pluginName, LocaleResolver resolver, String urlPattern) {
35-
String pathPattern = MappingTree.convertToMatchedPathPattern(urlPattern);
45+
public void register(LocaleResolver resolver) {
46+
notNull(resolver, "The locale resolver cannot be null.");
47+
String pathPattern = MappingTree.convertToMatchedPathPattern(resolver.getUrlPattern());
48+
notBlank(pathPattern, "The path pattern cannot be blank.");
49+
LocaleResolver preResolver;
3650
if (pathPattern.contains("**")) {
37-
wildcardResolvers.put(pathPattern, resolver);
51+
preResolver = wildcardResolvers.put(pathPattern, resolver);
3852
} else if (pathPattern.contains("*")) {
39-
pathVariableResolvers.register(pathPattern, resolver);
53+
preResolver = pathVariableResolvers.get(DefaultMappingTree.PATH_SEPARATOR)
54+
.register(pathPattern, resolver)
55+
.orElse(null);
56+
;
4057
} else {
41-
noPathVariableResolvers.put(pathPattern, resolver);
58+
preResolver = noPathVariableResolvers.put(pathPattern, resolver);
59+
}
60+
if (preResolver != null) {
61+
String message = StringUtils.format("Locale resolver has been registered. [pattern={0}]", pathPattern);
62+
throw new RegisterLocaleResolverException(message);
4263
}
4364
}
4465

45-
public void unregister(String pluginName, List<String> urlPatterns) {
46-
for (String pattern : urlPatterns) {
47-
String pathPattern = MappingTree.convertToMatchedPathPattern(pattern);
48-
if (pathPattern.contains("**")) {
49-
wildcardResolvers.remove(pathPattern);
50-
} else if (pathPattern.contains("*")) {
51-
pathVariableResolvers.unregister(pathPattern);
52-
} else {
53-
noPathVariableResolvers.remove(pathPattern);
54-
}
66+
public void unregister(LocaleResolver resolver) {
67+
notNull(resolver, "The locale resolver cannot be null.");
68+
String pathPattern = MappingTree.convertToMatchedPathPattern(resolver.getUrlPattern());
69+
notBlank(pathPattern, "The path pattern cannot be blank.");
70+
if (pathPattern.contains("**")) {
71+
wildcardResolvers.remove(pathPattern);
72+
} else if (pathPattern.contains("*")) {
73+
pathVariableResolvers.get(DefaultMappingTree.PATH_SEPARATOR).unregister(pathPattern);
74+
;
75+
} else {
76+
noPathVariableResolvers.remove(pathPattern);
5577
}
5678
}
5779

5880
public LocaleResolver dispatch(HttpClassicServerRequest request) {
5981
String path = UrlUtils.decodePath(request.path());
6082
return (LocaleResolver) OptionalUtils.get(() -> selectFromNoPathVariableResolvers(path))
6183
.orElse(() -> selectFromPathVariableResolvers(path))
62-
.orElse(() -> selectFromWildcardResolvers(path))
63-
.orElse(null);
84+
.orElse(() -> selectFromWildcardResolvers(path)).orDefault(this.defaultLocaleResolver);
6485
}
6586

6687
private Optional<LocaleResolver> selectFromNoPathVariableResolvers(String path) {
@@ -69,7 +90,7 @@ private Optional<LocaleResolver> selectFromNoPathVariableResolvers(String path)
6990
}
7091

7192
private Optional<LocaleResolver> selectFromPathVariableResolvers(String path) {
72-
return pathVariableResolvers.search(path);
93+
return pathVariableResolvers.get(DefaultMappingTree.PATH_SEPARATOR).search(path);
7394
}
7495

7596
private Optional<LocaleResolver> selectFromWildcardResolvers(String path) {
@@ -90,7 +111,7 @@ public void onPluginStarted(Plugin plugin) {
90111
.map(BeanFactory::<LocaleResolver>get)
91112
.collect(Collectors.toList());
92113
for(LocaleResolver localeResolver : localeResolvers) {
93-
this.register(localeResolver.getName(),localeResolver,localeResolver.getUrlPattern(),localeResolver.getPriority());
114+
this.register(localeResolver);
94115
}
95116
}
96117

@@ -102,7 +123,7 @@ public void onPluginStopping(Plugin plugin) {
102123
.map(BeanFactory::<LocaleResolver>get)
103124
.collect(Collectors.toList());
104125
for(LocaleResolver localeResolver : localeResolvers) {
105-
this.unregister(localeResolver.getName());
126+
this.unregister(localeResolver);
106127
}
107128
}
108129
}

0 commit comments

Comments
 (0)