SpringCloud网关(Zuul)如何给多个微服务之间传递共享参数

 更新时间:2022年03月22日 10:06:08   作者:蜀山雪松  
这篇文章主要介绍了SpringCloud网关(Zuul)如何给多个微服务之间传递共享参数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

1、使用场景

因为最近项目需要国际化,但是以前国际化的语言切换是放置在未进行微服务化之前的一个独立的SpringBoot服务之中。

目前由于业务的需要和不同模块能够复用的要求目前已经拆分为如下服务:zuul网关服务、**dx服务(包含主要服务)、**ai(一些推荐的AI服务)、message(消息咨询服务)、forum(论坛版块服务)等等。

如果还是按照以前的的方式只切换 **dx服务 之中的语言;其他微服务是不知道当前的Request请求是什么语言体系的。

就意味   **dx服务 是en语言,但是其他服务还是 zh(中文语言)。

因为此问题,我本人在项目开始进行国际化改版的时候,我就知道有此问题。 我就知道有此问题。 最开始就是有人不信;最后遇见问题了还是相信了!遇见问题了,总得使用相关的方案来解决此问题。

于是本人就是想到了有如下两种解决方案:

解决方案1

在网关服务(Zuul)之中,写一个统一的切换语言接口;在切换语言的使用同时调用其他服务的切换语言接口。这样实现起来最为简单。

具体如下图所示:

此方法比较原始直接,但是书写代码比较多;想当与每个微服务都得提供一个修改语言体系的接口供 网关(Zuul)

解决方案2

在网关(Zuul)服务层进行语言切换时候获得切换语言的参数;使用 LocaleContextHolder 暂存当前已经切换语言的信息;

然后在Zuul的过滤器之中通过获得当前请求(Request)的参数后,把以前语言切换暂存参数值从LocaleContextHolder获得切换语言的参数值。然后把这个参数传递到其他微服务之中;其他微服务通过Request 即可获得最新切换的语言参数;然后做到顺利获取切换后的最新的语言信息。   

具体如下图所示:   

          

针对方案一与方案二比较后;我选择使用的方案二。

2、代码实现

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String reqUrl=request.getRequestURL().toString();
        HttpSession session = request.getSession();         
    	Map<String, Object> user=(Map<String, Object>) session.getAttribute("user");  
        if(!(reqUrl.contains("permissionUser/userLogin") || (reqUrl.contains("noAuth")) 
        		|| reqUrl.contains("appapi"))) {
        	String[] actProfile = env.getActiveProfiles();
    		String curProfile = actProfile[0];
    		
        	if (StringUtils.startsWith(curProfile, "dev")) { //dev环境不做过滤    			
    			return null;    			
    		} 
        	
    		//判断用户ID是否存在,不存在就跳转到登录界面
        	if (!checkUserIsLogin(ctx, user)) {
        	//	System.out.println("session丢失: " + request.getSession().getId());
        		return null;
        	}
        	
            //放行ignoreUrls中配置的url
        	if(checkIsIgnoreUrl(request)) {
        		addUserToZuulRequestHeader(user);
        		return null;
        	}
        	
        	//检查该url是否有权访问
        	if (!checkIsUrlHasRight(ctx)) {
        		return null;
        	}
        	//从会话之中获得当前登录用户的userId,判断用户是否被踢
        	if (checkUserIsKickout(ctx, user)) {
        		return null;
        	}            
        }
        //可以往后走了,把session放入request的header中
        addUserToZuulRequestHeader(user);  
        //语言包
        setLanguageLocal(request);
        return null;
    }
 
     /**
	 * 设置本地语言包
	 * */
	private void setLanguageLocal(HttpServletRequest request) {
		String lang = "zh";
		if (StringUtils.isNotEmpty(request.getParameter("lang"))) {
			lang = request.getParameter("lang");
		}else {
			lang=localeMessageSourceService.getCurrentLanguage();
		}
		switch(lang) {
			case "zh":
				LocaleContextHolder.setLocale(Locale.CHINESE);
				break;
			case "en":
				LocaleContextHolder.setLocale(Locale.ENGLISH);
				break;
			case "fr":
				LocaleContextHolder.setLocale(Locale.FRENCH); 
				break;
		}
		//此处为获得请求的参数 然后在请求的参数里面加入暂存的语言携带参数 lang
		RequestContext ctx = RequestContext.getCurrentContext();
		request.getParameterMap();
		Map<String,List<String>> requestQueryParams=ctx.getRequestQueryParams();
		if(requestQueryParams==null) {
			requestQueryParams=new HashMap<>();
		}
		//String langCode=request.getParameter("lang").toString();
		//讲需要新增的参数添加进去,被调用的微服务可以直接获取,就像普通的一样;框架会直接注入进去
		    ArrayList<String> arrayList = new ArrayList<>();
            arrayList.add(lang);       
            requestQueryParams.put("lang", arrayList);
            ctx.setRequestQueryParams(requestQueryParams);
		FrameWorkConstant.MSG_INFO_EMPTY = localeMessageSourceService.getMessage("msg.info.empty");
		FrameWorkConstant.MSG_INFO_SUCCESS = localeMessageSourceService.getMessage("msg.success.operate");
		FrameWorkConstant.MSG_INFO_FAILED= localeMessageSourceService.getMessage("msg.error.unknown");
	}

ChangeLanauageConfigurer

import java.util.Locale; 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
 
/***
 *@purpose:国际化启动配置类
 *@since:2018年4月9日
 ***/
@Configuration
public class ChangeLanauageConfigurer extends WebMvcConfigurerAdapter {
 
 
	/**
	 * 描述 : 国际化配置类(会话区域解析器)
	 *
	 */
	@Bean
    public SessionLocaleResolver localeResolver() {
        SessionLocaleResolver slr = new SessionLocaleResolver();
//        System.out.println("aaaaaaaaaaaaaaaaaaaaaa");
//        // 设置默认语言
        slr.setDefaultLocale(Locale.CHINESE);       
        return slr;
    }
 
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        // 设置参数名
        lci.setParamName("lang");
        return lci;
    }
 
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}

LocaleMessageSourceService

/***
 *@purpose:本地化语言信息工具类
 *@since:2018年3月30日
 ***/
@Service
public class LocaleMessageSourceService {
	
	@Autowired
	private MessageSource messageSource;
 
    /**
    *
    *@param code:对应messages配置的key.
    *@return
    */
 
   public String getMessage(String code){
 
      //这里使用比较方便的方法,不依赖request.
      Locale locale = LocaleContextHolder.getLocale();
      String lang = locale.getLanguage();
      if(LanguageConstant.LANGUAGE_FR.equals(lang)) {
    	  locale = new Locale(lang,"FR");
      }
      if(LanguageConstant.LANGUAGE_ZH.equals(lang)) {
    	  locale = new Locale(lang,"CN");
      }
      if(LanguageConstant.LANGUAGE_EN.equals(lang)) {
    	  locale = new Locale(lang,"US");
      }
      
      String message = messageSource.getMessage(code,null,locale);
      return message;
   }
   
   /**
             * 获得当前语言
    * @param code
    * @return
    */
   public String getCurrentLanguage(){
 
       Locale locale = LocaleContextHolder.getLocale();
       String lang = locale.getLanguage();
       if(StringUtils.isEmpty(lang)) {
       	lang = LanguageConstant.LANGUAGE_EN;
       }
       return lang;
    }  
}

3、成果展现

在网关服务之中切换语言(en)后获得信息

ai服务的语言体系

**dx服务的语言体系

网关切换为中文(zh)后其他服务语言返回

ai服务语言切换结果

**dx服务语言切换结果

4、总结

如果使用简单粗暴的方法,直接通过网关调用其他微服务;虽然能够实现功能;但是此方法比较笨重;同时书写的代码比较多。为后期维护带来很大的不便利。

如果使用方案二在网关层进行统一处理,借助语言切换的能够在网关(Zuul)服务进行暂存和传递;同时动态添加切换语言后的参数到Request之中;能够便捷的把语言参数带到其他微服务之中。此方法值得推崇。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 基于java中两个对象属性的比较

    基于java中两个对象属性的比较

    下面小编就为大家带来一篇基于java中两个对象属性的比较。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Java实现图书管理系统的示例代码

    Java实现图书管理系统的示例代码

    这篇文章将通过Java实现一个简答的图书管理系统,本图书管理系统用对象数组的方式来提供操作方法,比较特别,建议新手学习,这对理解Java面向对象有很大帮助
    2022-11-11
  • Java模拟服务器解析web数据

    Java模拟服务器解析web数据

    本篇文章主要给大家详细分享了搭建JavaWeb服务器的详细步骤以及用到的代码,对此有需要的朋友可以跟着学习下,希望能给你带来帮助
    2021-07-07
  • 解决IDEA鼠标点击光标变大问题

    解决IDEA鼠标点击光标变大问题

    这篇文章主要介绍了解决IDEA鼠标点击光标变大问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 学习Spring-Session+Redis实现session共享的方法

    学习Spring-Session+Redis实现session共享的方法

    本篇文章主要介绍了学习Spring-Session+Redis实现session共享的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Spring Security实现退出登录和退出处理器

    Spring Security实现退出登录和退出处理器

    本文主要介绍了Spring Security实现退出登录和退出处理器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • javaGUI实现多人聊天功能

    javaGUI实现多人聊天功能

    这篇文章主要为大家详细介绍了javaGUI实现多人聊天功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • SpringBoot整合Mybatis-plus实现多级评论功能

    SpringBoot整合Mybatis-plus实现多级评论功能

    本文介绍了如何使用SpringBoot整合Mybatis-plus实现多级评论功能,同时提供了数据库的设计和详细的后端代码,前端界面使用的Vue2,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-05-05
  • SpringBoot使用hutool操作FTP的详细过程

    SpringBoot使用hutool操作FTP的详细过程

    在使用SpringBoot结合hutool操作FTP时,遇到防火墙导致上传文件大小为0kb的问题,通过设置FTP为被动模式解决,本文详细解析了FTP的主动模式和被动模式的工作原理、安全性及适用场景,帮助理解FTP的连接方式和解决网络限制问题
    2024-09-09
  • mybatis接口绑定失效的解决

    mybatis接口绑定失效的解决

    这篇文章主要介绍了mybatis接口绑定失效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11

最新评论