热门关键字:
jquery > jquery教程 > jquery教程 > Spring Cloud学习(五):Zuul服务网关

Spring Cloud学习(五):Zuul服务网关

195
作者:管理员
发布时间:2020/4/5 15:03:21
评论数:0
转载请自觉注明原文:http://www.jq-school.com/Show.aspx?id=1192

1. Zuul介绍

Zuul在微服务中主要是做路由转发功能和请求过滤功能。

  • 路由转发:根据一定的规则,区分请求并转发到对应的服务商,比如两个请求/api/user/getUser,/api/blog/getBlog在zuul服务中分别转发到用户服务和博客服务。
  • 请求过滤:很多服务请求都有会身份验证,就可以直接在zuul中去对身份验证的token去做校验,而不用在每个服务中都去做一次校验那么麻烦

2. 准备工作

准备一个用户服务,一个博客服务,一个注册中心

2.1. 用户服务

  • application.yml
server:
  port: 4003
spring:
  application:
    name: service-user
eureka:
  client:
    service-url:
        defaultZone: http://eureka-server1:3001/eureka/
  instance:
    instance-id: 用户服务-4003
  • UserController.java
/** * @author 吕梁山
 * @date 2019/7/19 */ @RestController
@RequestMapping("/api/user") public class UserController {

    @RequestMapping(value = "/getUser", method = RequestMethod.GET) public String getUser(String userId){ return "查找用户:" + userId;
    }

    @RequestMapping(value = "/addUser", method = RequestMethod.POST) public String addUser(String userName){ return "新增用户姓名:" + userName;
    }

    @RequestMapping(value = "/updateUser", method = RequestMethod.PUT) public String updateUser(String userName){ return "更新用户姓名:" + userName;
    }

    @RequestMapping(value = "/deleteUser", method = RequestMethod.DELETE) public String deleteUser(String userId){ return "删除用户:" + userId;
    }
}

2.2. 博客服务

  • application.yml
server:
  port: 4004
spring:
  application:
    name: service-blog
eureka:
  client:
    service-url:
        defaultZone: http://eureka-server1:3001/eureka/
  instance:
    instance-id: 博客服务-4004
  • UserController.java
/** * @author 吕梁山
 * @date 2019/7/19 */ @RestController
@RequestMapping("/api/blog") public class BlogController {

    @RequestMapping(value = "/getBlog", method = RequestMethod.GET) public String getBlog(String blogId){ return "查找博客:" + blogId;
    }

    @RequestMapping(value = "/addBlog", method = RequestMethod.POST) public String addBlog(String blogName){ return "新增博客标题:" + blogName;
    }

    @RequestMapping(value = "/updateBlog", method = RequestMethod.PUT) public String updateBlog(String blogName){ return "更新博客标题:" + blogName;
    }

    @RequestMapping(value = "/deleteBlog", method = RequestMethod.DELETE) public String deleteBlog(String blogId){ return "删除博客:" + blogId;
    }
}

2.3. 注册中心

  • application.yml
server:
  port: 3001
eureka:
  instance:
    # 在服务中心显示的名称
    hostname: eureka-server1
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    # false声明是服务端
    fetch-registry: false
    service-url:
        # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
        defaultZone: http://eureka-server1:3001/eureka/
  server:
    enable-self-preservation: false

3. 创建Zuul服务

  • pom.xml
    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pikaqiu.springcloud</groupId> <artifactId>zuul</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringCloud-Zuul</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
  • SpringCloudZuulApplication.java
    @SpringCloudApplication
    @EnableEurekaClient
    @EnableZuulProxy public class SpringCloudZuulApplication { public static void main(String[] args) {
            SpringApplication.run(SpringCloudZuulApplication.class, args);
        }
        
    }
  • application.yml
    server:
      port: 5005
    spring:
      application:
        name: zuul
    eureka:
      client:
        service-url:
            defaultZone: http://eureka-server1:3001/eureka/
      instance:
        instance-id: Zuul路由服务-5005

启动后查看注册中心

Spring Cloud学习(五):Zuul服务网关

 

4. 配置Zuul

配置zuul之前先看用户服务和博客服务能否正常访问,分别访问

http://127.0.0.1:4003/api/user/getUser?userId=1
http://127.0.0.1:4004/api/blog/getBlog?blogId=1

可以看到分别返回

查找用户:1
查找博客:1

Zuul的路由转发配置主要在配置文件去配置

zuul:
  routes:
    service-user:
        path: /api/user/**
        serviceId: service-user
        stripPrefix: false
    service-blog:
        path: /api/blog/**
        serviceId: service-blog
        stripPrefix: false
  • path:匹配的规则
  • serviceId:要转发至的服务id
  • stripPrefix: 是否去掉前缀(为true的时候访问/api/user/getUser在转发到用户服务时会去除path配置的/api/user/变成/getUser)

配置好Zuul后,分别访问

http://127.0.0.1:5005/api/user/getUser?userId=1
http://127.0.0.1:5005/api/blog/getBlog?blogId=1

可以看到分别返回

查找用户:1
查找博客:1

这样就说明Zuul的路由转发成功了。

5. 请求过滤

请求过滤即将那些不符合要求的请求过滤掉,这里演示就只以请求是否带token这个参数为例

5.1. 新建一个过滤器(新建一个类去继承ZuulFilter类)

/** * @author 吕梁山
 * @date 2019/7/19 */ @Component public class MyZuulFilter extends ZuulFilter {

    Logger logger = LoggerFactory.getLogger(MyZuulFilter.class); /** * pre:路由之前
     * routing:路由之时
     * post: 路由之后
     * error:发送错误调用 */ @Override public String filterType() {
        logger.info("准备进入路由-------------->"); return "pre";
    } /** * 过滤的顺序 */ @Override public int filterOrder() { return 0;
    } /** * 这里可以写逻辑判断,是否要过滤,true为永远过滤。 */ @Override public boolean shouldFilter() { return true;
    } /** * 过滤器的具体逻辑 */ @Override public Object run() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        HttpServletResponse response = currentContext.getResponse();
        response.setHeader("Content-Type","text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        String token = request.getParameter("token"); if(StringHelper.isNullOrEmptyString(token)){
            logger.warn("token is empty");
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseStatusCode(401);
            currentContext.setResponseBody("token为空"); return null;
        } return null;
    }
}

自定义过滤器的实现,继承ZuulFilter后需要重写实现下面四个方法

  • filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型
    • pre:可以在请求被路由之前调用
    • routing:在路由请求时候被调用
    • post:在routing和error过滤器之后被调用
    • error:处理请求时发生错误时被调用
  • filterOrder:通过int值来定义过滤器的执行顺序
  • shouldFilter:返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关。在上例中,我们直接返回true,所以该过滤器总是生效。
  • run:过滤器的具体逻辑。需要注意,这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码,当然我们也可以进一步优化我们的返回,比如,通过ctx.setResponseBody(body)对返回body内容进行编辑等。

5.2. 进行测试

  • 首先不带token进行一次访问
http://127.0.0.1:5005/api/blog/getBlog?blogId=1

返回结果为

token为空
  • 然后带上token进行访问
http://127.0.0.1:5005/api/blog/getBlog?blogId=1&token=test

返回结果为

查找博客:1

至此Zuul过滤器也成功了

 欢迎留言:http://pikaqiu.vip/article/2370.html
示例代码:https://github.com/Liangshan1994/SpringCloud





如果您觉得本文的内容对您的学习有所帮助:支付鼓励



关键字:jQuery
友荐云推荐