框架为ruoyi-vue 需求是内容国际化 静态资源已经使用接口通过json格式传给前端并赋值了 遇到的问题就是一些异常的提示信息还需要进行调整 需求就是根据前端的cookie中包含的language的值进行提示信息语言类型的判断 下面是ruoyi本身的提示信息工具类代码
public class MessageUtils {
/**
* 根据消息键和参数 获取消息 委托给spring messageSource
*
* @param code 消息键
* @param args 参数
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args) {
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}
可以看出来 本来的是将i18n的静态资源实例化获取的信息
现在我们需要写一个service来从数据库中获取资源
@Service
public class LanguageService {
@Autowired
private LanguageMessageLoader messageLoader;
// 这里的userthread我是从请求头中获取的language的值
public String getMessage(String keyName) {
return messageLoader.getMessage(keyName, UserThread.get());
}
}
public class UserThread {
private UserThread(){}
//线程变量隔离
private static final ThreadLocal<String> language = new ThreadLocal<>();
public static void put(String str){
language.set(str);
}
public static String get(){
return language.get();
}
public static void remove(){
language.remove();
}
}
拦截器注册配置类
这里的LanguageConfig本来是ruoyi框架里的i18nConfig 因为需求用不了i18n 所以我们改造一下
@Configuration
@Slf4j
public class LanguageConfig implements WebMvcConfigurer {
@Autowired
private LanguageInterceptor languageInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(languageInterceptor)
.addPathPatterns("/**");
}
}
拦截器
@Component
public class LanguageInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
UserThread.put(request.getHeader("language"));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
UserThread.remove();
}
}
//LanguageMessage是我的语言信息实体类 属性名称需要和数据库中该表的字段一一对应
public interface LanguageMessageRepository extends CrudRepository<LanguageMessage,Long> {
List<LanguageMessage> findAll();
// 可以根据需要添加其他自定义的查询方法
}
// 在应用启动时加载多语言信息到内存,创建一个 MessageLoader 组件,在应用启动时从数据库加载多语言信息并存储在内存中
@Component
public class LanguageMessageLoader implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private LanguageMessageRepository languageMessageRepository;
private Map<String, Map<String, String>> messages = new ConcurrentHashMap<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
List<LanguageMessage> allMessages = languageMessageRepository.findAll();
for (LanguageMessage message : allMessages) {
messages.computeIfAbsent(message.getKeyName(), k -> new HashMap<>())
.put(message.getLanguageCode(), message.getMessageText());
}
}
public String getMessage(String keyName, String languageCode) {
Map<String, String> languageMessages = messages.get(keyName);
if (languageMessages != null) {
return languageMessages.get(languageCode);
}
return null;
}
}
最后我们将messageUtils进行修改就可以了 需要注意这里的message为静态方法 我们需要通过@PostConstruct注解将非静态依赖注入到静态方法中 感兴趣可以了解下这个注解 主要是生命周期的管理
@Component
public class MessageUtils {
private static LanguageService languageService;
@Autowired
private LanguageService autowiredLanguageService;
@PostConstruct
public void init() {
languageService = autowiredLanguageService;
}
public static String message(String code, Object... args) {
if (languageService != null) {
return languageService.getMessage(code);
} else {
// 处理 languageService 为 null 的情况
return "LanguageService is not available";
}
}
}