一. 构建工程
1. 引入依赖
- <!--SpringBoot2.0 以上版本需引入该依赖 -->
- <dependency>
- <groupId>
- org.springframework.cloud
- </groupId>
- <artifactId>
- spring-cloud-starter-netflix-zuul
- </artifactId>
- </dependency>
- <dependency>
- <groupId>
- org.springframework.cloud
- </groupId>
- <artifactId>
- spring-cloud-starter-consul-discovery
- </artifactId>
- </dependency>
2. 创建主类
- @SpringBootApplication
- @EnableDiscoveryClient
- @EnableZuulProxy
- @RestController
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
3. 配置 application.properties
- zuul.routes.API-a.path=/API-a/**
- zuul.routes.API-a.service-id=API-a
- zuul.routes.API-b.path=/API-b/**
- zuul.routes.API-b.service-id=API-b
- 这里存在 API-a 和 API-b 两个微服务应用, 当请求 http://localhost:port/API-a/helloWorld, 会被路由转发至 API-a 服务的 /helloWorld 接口, 当请求 http://localhost:port/API-b/helloWorld, 会被路由转发至 API-b 服务的 /helloWorld 接口. 当请求 URL 符合配置规则时, 了解 springcloud 架构可以加求求: 三五三六二四七二五九, 就会被转发至 service-id 对应的微服务应用接口.
- 5.4. 配置请求过滤
- SpringCloud Zuul 还有另一个和核心功能: 请求过滤. Zuul 允许开发者在 API 网关上通过定义过滤器来实现对请求的拦截与过滤, 实现方法非常简单, 只需继承 ZuulFilter 抽象类并实现它定义的 4 个抽象函数就可以完成对请求的拦截和过滤.
- public class MyGatewayFilter extends ZuulFilter {
- /*4 种过滤器类型,
- pre: 可以在请求被路由之前调用,
- route: 在路由请求时候被调用,
- post: 在 route 和 error 过滤器之后被调用,
- error: 处理请求时发生错误时被调用 */
- @Override
- public String filterType() {
- return "pre";
- }
- @Override
- public int filterOrder() {
- return 0; // 优先级为 0, 数字越大, 优先级越低
- }
- @Override
- public boolean shouldFilter() {
- return true; // 是否执行该过滤器, 此处为 true, 说明需要过滤
- }
- @Override
- public Object run() {
- RequestContext ctx = RequestContext.getCurrentContext();
- HttpServletRequest request = ctx.getRequest();
- log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
- Object accessToken = request.getParameter("token"); // 获取 token 参数
- if (accessToken == null) {
- log.warn("token is empty");
- ctx.setSendZuulResponse(false); // 过滤该请求, 不对其进行路由
- ctx.setResponseStatusCode(401); // 返回错误码
- ctx.setResponseBody("token is null!"); // 返回错误内容
- return null; //Zuul 还未对返回数据做处理
- }
- return null;
- }
创建过滤器后, 它并不会直接生效, 我们还需为其创建具体的 Bean 才能启动该过滤器.
- @SpringBootApplication
- @EnableDiscoveryClient
- @EnableZuulProxy
- @RestController
- public class LixjApplication {
- public static void main(String[] args) {
- SpringApplication.run(LixjApplication.class, args);
- }
- @Bean
- public MyGatewayFilter myGatewayFilter(){
- return new MyGatewayFilter();
- }
- }
二. 路由详解
1. 路径匹配规则
/API-a/? 可以匹配 /API-a/ 之后拼接一个任务字符的路径 , 比如 /API-a/a , /API-a/b , /API-a/c
/API-a/ 可以匹配 /API-a/ 之后拼接任意字符的路径, 比如 /API-a/a, /API-a/aaa, /API-a/bbb . 但它无法匹配 /API-a/a/b 这种多级目录路径
/API-a/ 可以匹配 /API-a/* 包含的内容之外, 还可以匹配形如 /API-a/a/b 的多级目录路径
**
2. 路由匹配顺序
随着版本的迭代, 我们需要对一个服务做一些功能拆分, 将原属于 API-a 服务的某些功能拆分到另一个全新的服务 API-a-part 中, 而这些拆分的外部调用 URL 路径希望能够符合规则 /API-a/part/ .*
- zuul.routes.API-a.path=/API-a/**
- zuul.routes.API-a.service-id=API-a
- zuul.routes.API-a-part.path=/API-a/part/**
- zuul.routes.API-a-part.service-id=API-a-part
在源码中, 路由规则是通过 LinkedHashMap 保存的, 也就是说, 路由规则的保存时有序的, 而内容的加载是通过遍历配置文件中路由规则依次加入的, 所以导致问题的根本原因是对配置文件中内容的读取, 但上述 properties 配置无法保证路由规则加载顺序, 我们需要使用 YAML 文件来配置, 以实现有序的路由规则.
- zuul:
- routes:
- API-a-part:
- path=/API-a/part/service-id=API-a-part
- API-a:
- path=/API-a/
- service-id=API-a
来源: http://www.bubuko.com/infodetail-3382737.html