我们编写的Web应用程序需要双语网址。我们以前使用过“普通Spring / Spring MVC”,但我们已经开始转换到Spring boot。
在我们较早的Spring 3.x / 4.x应用程序中,我们通过展开大多数“autoconfig”来解决此问题,以覆盖 getMappingPathPatterns 以包含URL的翻译版本。例如:
@Override
protected Set<String> getMappingPathPatterns(RequestMappingInfo info) {
Set<String> unilingualPatterns = super.getMappingPathPatterns(info);
Set<String> bilingualPatterns = new HashSet<String>();
for (String pattern : unilingualPatterns) {
bilingualPatterns.add(pattern);
// Create the French and English URLs.
// "resolver" translates the english URL to French.
final String fraURL = resolver.convertUrl(pattern, Locale.CANADA_FRENCH);
if (!pattern.equals(fraURL)) {
bilingualPatterns.add(fraURL);
}
}
return bilingualPatterns;
}
这样,控制器的方法如下:
@RequestMapping(value = "/home")
public String homeView() {
return "home";
}
会自动拥有“/ accueil”的第二个映射。从本质上讲,就好像这个方法实际上是这样注释的:
@RequestMapping(value = {"/home", "/accueil"})
public String homeView() {
return "home";
}
正如我上面提到的,这需要解开很多“自动配置”,这使得设置更加复杂。
我们开始将Spring Boot用于新项目,我们的目标之一是降低配置的复杂性。我希望找到一种更简洁的方法来包含这个功能。
我尝试在Configuration类中创建自己的 RequestMappingHandlerMapping bean,但它没有被使用。事实上,无论如何,Spring似乎并不真的希望你覆盖这个类。
之后,我尝试抓住Spring Boot创建的 RequestMappingHandlerMapping ,遍历 handlerMethods 列表,并为已翻译的 PatternsRequestCondition添加新的 handlerMethods ,但是我从 RequestMappingHandlerMapping.getHandlerMethods()返回的地图是不可修改的,所以这也是一个死胡同。
我觉得无论如何我都会走错路。我发现在使用Spring时,如果我的解决方案变得复杂(就像这个那样),那么我做错了,我只需要找到“简单的方法”。
如果有人知道如何手动添加新的HandlerMethods(基本上复制现有的HandlerMethods,但使用已翻译的URL模式),那就太棒了。
提前致谢。
答案 0 :(得分:2)
在尝试了许多不同的解决方案之后,这个解决方案似乎是最标准的&#34;是为URL使用单个属性文件。这就是我使用Spring Boot完成此任务的方法。
首先,我在 scr / main / resources 下创建了一个名为 urls.properties 的新属性文件,其中包含我的应用程序的网址,例如:
url.home=/home
url.start=/start
我在我的WebConfig配置文件中添加了 @PropertySource 注释:
/**
* Web configuration.
*
* Since 1.0.0
*/
@Configuration
@PropertySource("classpath:i18n/urls.properties")
public class WebConfig extends WebMvcConfigurerAdapter {
/**
* Locale resolver.
*
* @return <code>LocaleResolver</code>
*/
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.CANADA);
return localeResolver;
}
/**
* Locale change interceptor.
*
* @return <code>LocaleChangeInterceptor</code>
*/
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
/** {@inheritDoc} */
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(localeChangeInterceptor());
}
}
这使我可以在我的控制器中访问这些属性。
/**
* Demo API controller.
*
* @since 1.0.0
*/
@Controller
@RequestMapping("${url.home}")
public class DemoController {
/**
* Demo GET method binding.
*
* @return <code>String</code>
*/
@RequestMapping(method = RequestMethod.GET)
public String getHome() {
return "home";
}
}
确保 urls.properties 属性文件在我的 application.properties 文件中列为属性源。
spring.messages.basename=messages,urls
这使我可以在Thymeleaf模板中访问这些网址。例如:
<a th:href="@{#{url.home}}">Home</a>
拥有 @PropertySource 注释还可以轻松访问测试用例中的网址,例如:
/**
* DemoController test class.
*
* @since 1.0.0
*/
public class DemoControllerTest extends AbstractMockMvcTest {
@Value("${url.home}")
private String urlHome;
/**
* Test get username.
*
* @throws Exception Exception
*/
@Test
public void getUsername() throws Exception {
// Request.
resultActions = mockMvc.perform(get(urlHome));
// Verify response.
resultActions.andExpect(status().isOk());
}
}
现在,当它需要翻译网址时,只需要发送urls.properties文件进行翻译。重要的是要注意,这仍然只是一个文件(没有_en和_fr变种),所以文件最终看起来像:
url.home=/home-accueil
url.start=/start-debut
我希望这有助于其他人。找出实现这项工作的最佳方法是痛苦的。
如果有其他人提出更好的方法来做到这一点(这并不需要太多的黑客攻击),请告诉我!
感谢。