<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);
}