Spring Cloud Zuul路由网关服务过滤实现代码

作者:彭超 时间:2021-08-26 10:56:07 

Zuul 简介

Zuul 的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如 /api/admin 转发到到 Admin 服务,/api/member 转发到到 Member 服务。Zuul 默认和 Ribbon 结合实现了负载均衡的功能。

引入依赖

在 pom.xml 中主要添加 spring-cloud-starter-netflix-eureka-server 和 spring-cloud-starter-netflix-zuul 依赖


<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

相关配置

在 application.yml 中主要添加 Zuul 路由配置


zuul:
routes:
 api-a:
  path: /api/ribbon/**
  serviceId: hello-spring-cloud-web-admin-ribbon
 api-b:
  path: /api/feign/**
  serviceId: hello-spring-cloud-web-admin-feign

路由说明:

以 /api/ribbon 开头的请求都转发给 spring-cloud-web-admin-ribbon 服务
以 /api/feign 开头的请求都转发给 spring-cloud-web-admin-feign 服务
在 Application 入口类中添加 @EnableZuulProxy 注解开启 zuul 功能


@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulApplication {
 public static void main(String[] args) {
   SpringApplication.run(ZuulApplication.class, args);
 }
}

配置网关路由失败时的回调

创建 WebAdminFeignFallbackProvider 回调类


/**
* 路由 hello-spring-cloud-web-admin-feign 失败时的回调
*/
@Component
public class WebAdminFeignFallbackProvider implements FallbackProvider {

@Override
 public String getRoute() {
   // ServiceId,如果需要所有调用都支持回退,则 return "*" 或 return null
   return "hello-spring-cloud-web-admin-feign";
 }

/**
  * 如果请求服务失败,则返回指定的信息给调用者
  * @param route
  * @param cause
  * @return
  */
 @Override
 public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
   return new ClientHttpResponse() {
     /**
      * 网关向 api 服务请求失败了,但是消费者客户端向网关发起的请求是成功的,
      * 不应该把 api 的 404,500 等问题抛给客户端
      * 网关和 api 服务集群对于客户端来说是黑盒
      * @return
      * @throws IOException
      */
     @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 {
       ObjectMapper objectMapper = new ObjectMapper();
       Map<String, Object> map = new HashMap<>();
       map.put("status", 200);
       map.put("message", "无法连接");
       return new ByteArrayInputStream(objectMapper.writeValueAsString(map).getBytes("UTF-8"));
     }

@Override
     public HttpHeaders getHeaders() {
       HttpHeaders headers = new HttpHeaders();
       // 和 getBody 中的内容编码一致
       headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
       return headers;
     }
   };
 }
}

测试路由访问

依次运行 EurekaApplication > ServiceAdminApplication > WebAdminRibbonApplication > WebAdminFeignApplication > ZuulApplication 各服务

访问:http://localhost:8769/api/ribbon/hi?message=zuul

浏览器显示

port : 8763,message : zuul

访问:http://localhost:8769/api/feign/hi?message=zuul

浏览器显示

port : 8763,message : zuul

至此说明 Zuul 的路由功能配置成功。

使用 Zuul 的服务过滤功能

Zuul 不仅仅只是路由,还有很多强大的功能。比如用在安全验证方面。

创建服务过滤器


/**
* Zuul 的服务过滤演示
*/
@Component
public class LoginFilter extends ZuulFilter {

private static final Logger logger = LoggerFactory.getLogger(LoginFilter.class);

/**
  * 配置过滤类型,有四种不同生命周期的过滤器类型
  * 1. pre:路由之前
  * 2. routing:路由之时
  * 3. post:路由之后
  * 4. error:发送错误调用
  * @return
  */
 @Override
 public String filterType() {
   return "pre";
 }

/**
  * 配置过滤的顺序
  * @return
  */
 @Override
 public int filterOrder() {
   return 0;
 }

/**
  * 配置是否需要过滤:true/需要,false/不需要
  * @return
  */
 @Override
 public boolean shouldFilter() {
   return true;
 }

/**
  * 过滤器的具体业务代码
  * @return
  * @throws ZuulException
  */
 @Override
 public Object run() throws ZuulException {
   RequestContext context = RequestContext.getCurrentContext();
   HttpServletRequest request = context.getRequest();
   String token = request.getParameter("token");
   if (token == null) {
     logger.warn("Token is empty");
     context.setSendZuulResponse(false);
     context.setResponseStatusCode(401);
     try {
       context.getResponse().getWriter().write("Token is empty");
     } catch (IOException e) {
     }
   } else {
     logger.info("OK");
   }
   return null;
 }
}

测试过滤器

访问:http://localhost:8769/api/feign/hi?message=zuul

网页显示

Token is empty

访问:http://localhost:8769/api/feign/hi?message=zuul&token=1

网页显示

port : 8763,message : zuul

来源:https://antoniopeng.com/2019/11/16/springcloud/SpringCloudZuul%E8%B7%AF%E7%94%B1%E7%BD%91%E5%85%B3%E5%8F%8A%E6%9C%8D%E5%8A%A1%E8%BF%87%E6%BB%A4/

标签:Spring,Cloud,Zuul,路由,过滤
0
投稿

猜你喜欢

  • java读取xml配置参数代码实例

    2023-11-25 03:03:17
  • springboot如何统一设置时区

    2022-01-26 18:16:39
  • java实现冒泡排序算法

    2023-10-17 20:44:01
  • MyBatis图文并茂讲解注解开发多对多查询

    2022-10-27 17:05:04
  • Springboot初始化项目并完成登入注册的全过程

    2023-07-31 15:09:09
  • Maven构建时跳过部分测试的实例

    2022-08-30 03:42:50
  • springboot中使用rabbitt的详细方法

    2023-06-17 09:57:43
  • Java实现俄罗斯方块的源码分享

    2023-02-17 04:20:48
  • android压力测试命令monkey详解

    2023-06-17 00:36:29
  • JAVA设计模式之备忘录模式原理与用法详解

    2023-08-24 13:23:37
  • Spring如何在一个事务中开启另一个事务

    2021-08-30 17:29:15
  • Java Annotation(Java 注解)的实现代码

    2023-01-09 00:36:17
  • SpringBoot整合MybatisPlus实现增删改查功能

    2022-10-31 05:24:15
  • Java正则验证正整数的方法分析【测试可用】

    2022-08-02 21:50:05
  • 一篇文章带你了解JVM垃圾回收

    2023-08-06 23:42:20
  • Swagger注解-@ApiModel和@ApiModelProperty的用法

    2023-02-05 23:57:48
  • java8中:: 用法示例(JDK8双冒号用法)

    2023-11-25 06:21:21
  • C# Winform消息通知系统托盘气泡提示框ToolTip控件

    2023-01-13 23:31:02
  • javaweb 项目初始配置的方法步骤

    2021-12-23 17:34:23
  • springboot中使用redis并且执行调试lua脚本

    2022-02-15 08:49:52
  • asp之家 软件编程 m.aspxhome.com