简介
Zuul包含了对请求的路由和过滤两个最主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
注意:Zuul服务最终还是会注册进Eureka
官方资料
新建zuul模块
引入相关依赖
1 2 3 4 5 6 7 8
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
|
启动类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication @EnableEurekaClient @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class,args); } }
|
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| server: port: 8089 spring: application: name: spring-cloud-zuul eureka: instance: instance-id: zuul:${server.port} prefer-ip-address: true client: service-url: defaultZone: http:
#路由访问映射规则 zuul: routes: zuul.serviceId: feign-server zuul.path: /zuul-user-service
|
访问 http://192.168.137.1:8089/felix/zuul-user-service/user/list
正常显示,
服务过滤
zuul不仅只是路由,并且还能过滤,做一些安全验证。继续改造工程;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
@Component @Slf4j public class CustomerFilter extends ZuulFilter { @Override public String filterType() { return "pre"; }
@Override public int filterOrder() { return 0; }
@Override public boolean shouldFilter() { return true; }
@Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString())); Object accessToken = request.getParameter("token"); if (accessToken == null) { log.warn("token is empty"); ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); try { ctx.getResponse().getWriter().write("token is empty"); } catch (Exception e) { } return null; } log.info("ok"); return null; } }
|
- filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
- pre:路由之前
- routing:路由之时
- post: 路由之后
- error:发送错误调用
- filterOrder:过滤的顺序
- shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
- run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import com.alibaba.fastjson.JSONObject; import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse;
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream;
public class ZuulFallback implements FallbackProvider { @Override public String getRoute() { return "*"; }
@Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; }
@Override public int getRawStatusCode() throws IOException { return HttpStatus.OK.value(); }
@Override public String getStatusText() throws IOException { return HttpStatus.OK.getReasonPhrase(); }
@Override public void close() {
}
@Override public InputStream getBody() throws IOException { JSONObject json =new JSONObject(); json.put("state","501"); json.put("msg","后台接口错误"); return new ByteArrayInputStream(json.toJSONString().getBytes("UTF-8")); }
@Override public HttpHeaders getHeaders() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); return httpHeaders; } }; } }
|
浏览器访问
http://192.168.137.1:8089/felix/zuul-user-service/user/list
出现 token is empty 说明zuul起到了保护的作用
添加token
再次访问
http://192.168.137.1:8089/felix/zuul-user-service/user/list?token=%22token%22
访问正常
参考
forezp