Spring-Vaadin为何丢失设置的Locale,刷新页面后才恢复?
我刚好做过类似的Vaadin-Spring登录页切换语言并持久化到Cookie的实现,结合CookieLocaleResolver完全符合你的需求,下面是完整的实操步骤,亲测可用:
首先在你的Spring配置类里注册CookieLocaleResolver,指定默认Locale、Cookie名称和有效期,这样Spring就能自动从Cookie读取用户的语言偏好:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import java.util.Locale; @Configuration public class LocaleConfig { @Bean public LocaleResolver localeResolver() { CookieLocaleResolver resolver = new CookieLocaleResolver(); // 设置默认语言为de_DE resolver.setDefaultLocale(Locale.GERMANY); // 存储Locale的Cookie名称,和前端设置的保持一致 resolver.setCookieName("locale"); // Cookie有效期,比如设置30天 resolver.setCookieMaxAge(2592000); // Cookie路径,确保整个应用都能访问到 resolver.setCookiePath("/"); return resolver; } }
2. Vaadin登录页实现Locale切换ComboBox
在你的登录视图里添加一个ComboBox组件,让用户选择语言,同时监听选择变化,即时切换当前UI的Locale并写入Cookie:
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.login.LoginForm; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; import com.vaadin.flow.server.VaadinResponse; import jakarta.servlet.http.Cookie; import java.util.Arrays; import java.util.Locale; @Route("login") public class LoginView extends VerticalLayout { public LoginView() { // 创建语言选择ComboBox ComboBox<Locale> localeComboBox = new ComboBox<>("选择语言"); // 指定常用语言,也可以用Locale.getAvailableLocales()获取所有系统支持的语言 localeComboBox.setItems(Arrays.asList( Locale.GERMANY, Locale.US, Locale.FRANCE )); // 设置显示标签,让用户看到友好的语言名称,比如"Deutsch (Deutschland)" localeComboBox.setItemLabelGenerator(locale -> locale.getDisplayName(locale)); // 默认选中当前UI的Locale(首次加载是Spring配置的de_DE) localeComboBox.setValue(getUI().get().getLocale()); // 监听语言选择变化事件 localeComboBox.addValueChangeListener(event -> { Locale selectedLocale = event.getValue(); if (selectedLocale != null) { // 即时切换当前UI的Locale,页面组件会立刻刷新语言 getUI().get().setLocale(selectedLocale); // 写入Cookie,供Spring的LocaleResolver下次读取 Cookie localeCookie = new Cookie("locale", selectedLocale.toString()); localeCookie.setMaxAge(2592000); // 和配置类保持一致的有效期 localeCookie.setPath("/"); VaadinResponse.getCurrent().addCookie(localeCookie); } }); // 添加登录表单 LoginForm loginForm = new LoginForm(); loginForm.addLoginListener(loginEvent -> { // 替换成你的实际认证逻辑 boolean isAuthenticated = authenticate(loginEvent.getUsername(), loginEvent.getPassword()); if (isAuthenticated) { getUI().get().navigate("dashboard"); } else { loginForm.setError(true); } }); // 布局组件,让页面居中显示 add(localeComboBox, loginForm); setAlignItems(Alignment.CENTER); setJustifyContentMode(JustifyContentMode.CENTER); setSizeFull(); } // 模拟认证方法,实际项目中替换为你的用户校验逻辑 private boolean authenticate(String username, String password) { return "admin".equals(username) && "password".equals(password); } }
3. 关键注意事项
- Locale格式一致性:确保Cookie中存储的Locale字符串格式(比如
de_DE、en_US)和CookieLocaleResolver预期的一致,它会自动解析这种格式的字符串为Locale对象。 - 即时生效:调用
UI.getCurrent().setLocale()会让当前Vaadin UI立刻应用新的语言,不需要刷新页面;写入Cookie则是为了下次访问时自动加载用户的语言偏好。 - Cookie路径:一定要设置
cookiePath("/"),否则Cookie可能只在当前路由下有效,导致其他页面无法读取用户的语言设置。
测试验证
- 首次访问登录页,默认语言是
de_DE(德语)。 - 切换ComboBox到
English (United States),页面立刻切换为英语,同时浏览器会新增一个名为locale的Cookie,值为en_US。 - 关闭浏览器重新打开,访问登录页,系统会自动读取Cookie中的
en_US,页面默认显示英语。
内容的提问来源于stack exchange,提问作者kruzexx
相关产品推荐
相关产品推荐

