springcloud-zuul路由的使用

學習使用zuul的原因是現在原有架構的一些功能被拆分爲微服務,每個服務可能都需要調用其他服務,這樣就會有服務之間的不斷的調用,但是還有一個對外提供的接口需要做一些驗證,還有登錄等需要做一些驗證,這些功能抽出來作爲一個統一的管理端,原來的方式將這些功能單獨作爲一個服務,後來發現zuul有類似的功能,所以學習了一下並在項目中進行了使用,這篇文章主要參考了程序猿DD的文章,並對一些已知的事實進行了驗證。最簡單的方式,首先引入以下jar包
<dependencies>
	<dependency>
		<groupid>org.springframework.cloud</groupid>
		<artifactld>spring - cloud - starter - zuul</artifactid>
	</dependency>
</dependencies>
spring-cloud-starter-zuul包中包含了提供線程保護以及熔斷處理的spring-cloud-starter-hystrix依賴,提供監控的spring-boot-star七er-actutor依賴以及提供客戶端負載的spring-cloud-starter-ribbon依賴,在主類中配置以下內容:
@EnableZuulProxy
@SpringBootApplication
public class ApiGatewayApplication {
	public static void main(String[] args) {
		SpringApplication.run(ApiGatewayApplication.class, args);
	}
}
配置文件中提供以下內容
zuul.routes.api-a-url.path=/api-gateway/**
zuul.routes.api-a-url.url=http://localhost:8083/
這樣在請求localhost/api-gateway/api的時候就會轉發到http://localhost:8083/api中去,實現對請求的轉發,更進一步的是實現zuul和Eureka的結合,在zuul服務中繼續添加以下jar包
<dependency>
	<groupid>org.springframework.cloud</groupid>
	<artifactid>spring-cloud-starter-eureka</artifactid>
</dependency>
配置文件添加以下內容,同時將原配置文件中的內容註釋掉
spring.application.name = api-gateway
#eureka服務的註冊地址
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/

#服務一的轉發配置
zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.serviceId=COMPUTE-SERVICE

#服務二的轉發配置
zuul.routes.api-b.path=/api-b/**
zuul.routes.api-b.serviceId=EUREKA-CONSUMER-RIBBON-HYSTRIX
這樣就可以實現多個服務的請求轉發,這只是請求轉發的過程,請求轉發,但是還需要對一些登錄的接口以及對外提供服務的接口做一些過濾的功能,那怎麼去實現呢?就是利用ZuulFilter,底層是基於javax.servlet.Filter,以下的Java代碼就是實現了對請求參數的過濾
public class AccessFilter extends ZuulFilter {

    /**
     * 過濾器的類型, 它決定過濾器在請求的哪個生命週期中執行。
     * 這裏定義爲pre, 代表會在請求被路由之前執行
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 過濾器的執行順序。
     * 當請求在一個階段中存在多個過濾器時, 需要根據該方法返回的值來依次執行。
	 * 越小的越先執行
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 判斷該過濾器是否需要被執行。
     * 這裏我們直接返回了true, 因此該過濾器對所有請求都會生效。
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        Object accessToken = request.getParameter("accessToken");
        if (accessToken == null) {
            //zuul不對空的路由進行路由
            ctx.setSendZuulResponse(false);
            //返回的錯誤碼
            ctx.setResponseStatusCode(401);
            return "請添加token";
        }
        return null;
    }
}

http://localhost:9001/api-b/consumer請求改爲http://localhost:9001/api-b/consumer?accessToken=abc這種URL的方式就可以通過,否則就會出現401,如果要實現過濾的生效還需要在主類中增加以下的代碼,讓其形成能夠運行的bean
	@Bean
	public AccessFilter accessFilter() {
		return new AccessFilter();
	}
如果按照請求的類型進行過濾的時候需要添加以下代碼
    @Override
    public boolean shouldFilter() {
        String method = RequestContext.getCurrentContext().getRequest().getMethod();
        if ("PUT".equals(method) || "POST".equals(method) || "DELETE".equals(method)) {
            return true;
        }
        return false;
    }
對於跨域問題的解決可以採用以下方式
 
  @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin(ORIGIN);
        config.addAllowedHeader("Origin");
        config.addAllowedHeader("X-Requested-With");
        config.addAllowedHeader("Content-Type");
        config.addAllowedHeader("Accept");
        config.setMaxAge(3600L);
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章