独立使用zuul网关分发不同服务的请求、权限控制,非SpringCloud

版权声明:本文为博主武伟峰原创文章,转载请注明地址http://blog.csdn.net/tianyaleixiaowu。

 
 
 

网关api Gateway的重要性不言而喻,网关负责统一接收所有请求,然后根据不同的规则进行转发到不同的服务。使用网关能够统一的管理请求日志、进行权限控制、过滤等,这样就能避免在每个单体应用中做重复的工作。

这一篇主要是讲zuul的独立使用,就是只作为一个独立的项目进行请求转发,而不关联SpringCloud的那一堆Eureka、Ribbon等,因为很多时候我们的项目并不都是基于springcloud的微服务,或者不想搞那么麻烦用注册中心什么的,就只想做个简单的请求转发代理和权限控制。

zuul是可以进行开发的,里面可以自定义一些自己的规则,譬如涉及查表之类的,能够完成颗粒很细的需求。

这里我们打算完成如下的功能,当访问ip/user时就进入到User的独立项目中,访问ip/club时就进入到club的独立项目中。入口是zuul,在zuul里做权限控制,譬如查表过滤黑名单、限制同一个userId单位时间内的访问次数等。

请求转发

使用zuul很简单,新建一个Springboot项目,创建时勾选zuul即可。pom.xml如下

 

[html] view plain copy
 
 print?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  4.     <modelVersion>4.0.0</modelVersion>  
  5.   
  6.     <groupId>com.tianyalei</groupId>  
  7.     <artifactId>testzuul</artifactId>  
  8.     <version>0.0.1-SNAPSHOT</version>  
  9.     <packaging>jar</packaging>  
  10.   
  11.     <name>testzuul</name>  
  12.     <description>Demo project for Spring Boot</description>  
  13.   
  14.     <parent>  
  15.         <groupId>org.springframework.boot</groupId>  
  16.         <artifactId>spring-boot-starter-parent</artifactId>  
  17.         <version>1.5.6.RELEASE</version>  
  18.         <relativePath/> <!-- lookup parent from repository -->  
  19.     </parent>  
  20.   
  21.     <properties>  
  22.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  23.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  24.         <java.version>1.8</java.version>  
  25.         <spring-cloud.version>Dalston.SR3</spring-cloud.version>  
  26.     </properties>  
  27.   
  28.     <dependencies>  
  29.         <dependency>  
  30.             <groupId>org.springframework.cloud</groupId>  
  31.             <artifactId>spring-cloud-starter-zuul</artifactId>  
  32.         </dependency>  
  33.   
  34.         <dependency>  
  35.             <groupId>org.springframework.boot</groupId>  
  36.             <artifactId>spring-boot-starter-test</artifactId>  
  37.             <scope>test</scope>  
  38.         </dependency>  
  39.     </dependencies>  
  40.   
  41.     <dependencyManagement>  
  42.         <dependencies>  
  43.             <dependency>  
  44.                 <groupId>org.springframework.cloud</groupId>  
  45.                 <artifactId>spring-cloud-dependencies</artifactId>  
  46.                 <version>${spring-cloud.version}</version>  
  47.                 <type>pom</type>  
  48.                 <scope>import</scope>  
  49.             </dependency>  
  50.         </dependencies>  
  51.     </dependencyManagement>  
  52.   
  53.     <build>  
  54.         <plugins>  
  55.             <plugin>  
  56.                 <groupId>org.springframework.boot</groupId>  
  57.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  58.             </plugin>  
  59.         </plugins>  
  60.     </build>  
  61.   
  62.   
  63. </project>  
然后在Application类加上@EnableZuulProxy注解即可,该项目就具备了zuul的功能了

 

 

[java] view plain copy
 
 print?
  1. @EnableZuulProxy  
  2. @SpringBootApplication  
  3. public class TestzuulApplication {  
  4.   
  5.     public static void main(String[] args) {  
  6.         SpringApplication.run(TestzuulApplication.class, args);  
  7.     }  
  8. }  
然后关键的地方在application.yml配置里,规则在这里配置
[html] view plain copy
 
 print?
  1. server:  
  2.   port: 9000  
  3. zuul:  
  4.   routes:  
  5.     api-1:  
  6.       path: /user/**  
  7.       url: http://localhost:8081/  
  8.     api-2:  
  9.       path: /club/**  
  10.       url: http://localhost:8082/  
主要就是配置zuul.routes相关,api-1名字随便起,主要是配置里面的path和url这个是固定的

通过源码可以看到支持serviceId,url两种,path是固定的,代表访问zuul时的路径,url代表访问该路径时会被转发到哪个url上,serviceId是给springcloud用的,代表在Eureka上注册的服务id,也是确定是转发到哪一个服务的。

 

这里我们配置的是url,当访问localhost:9000/user/abc时,就相当于访问localhost:8081/abc.

到这里就已经完成了请求转发了,如果你本地跑了两个项目,端口分别是8081,8082,就已经可以通过请求zuul配置的url规则访问到了。

 

[java] view plain copy
 
 print?
  1. @RequestMapping("club")  
  2.     public String index() {  
  3.         return "hello,我来自Club客户端";  
  4.     }  

权限控制

在zuul里新建一个AccessFilter类,如下的写法。
[java] view plain copy
 
 print?
  1. package com.tianyalei.testzuul;  
  2.   
  3. import com.netflix.zuul.ZuulFilter;  
  4. import com.netflix.zuul.context.RequestContext;  
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.stereotype.Component;  
  8.   
  9. import javax.servlet.http.HttpServletRequest;  
  10.   
  11. @Component  
  12. public class AccessFilter extends ZuulFilter {  
  13.   
  14.     private static Logger log = LoggerFactory.getLogger(AccessFilter.class);  
  15.   
  16.     @Override  
  17.     public String filterType() {  
  18.         //前置过滤器  
  19.         return "pre";  
  20.     }  
  21.   
  22.     @Override  
  23.     public int filterOrder() {  
  24.         //优先级,数字越大,优先级越低  
  25.         return 0;  
  26.     }  
  27.   
  28.     @Override  
  29.     public boolean shouldFilter() {  
  30.         //是否执行该过滤器,true代表需要过滤  
  31.         return true;  
  32.     }  
  33.   
  34.     @Override  
  35.     public Object run() {  
  36.         RequestContext ctx = RequestContext.getCurrentContext();  
  37.         HttpServletRequest request = ctx.getRequest();  
  38.   
  39.         log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());  
  40.   
  41.         //获取传来的参数accessToken  
  42.         Object accessToken = request.getParameter("accessToken");  
  43.         if(accessToken == null) {  
  44.             log.warn("access token is empty");  
  45.             //过滤该请求,不往下级服务去转发请求,到此结束  
  46.             ctx.setSendZuulResponse(false);  
  47.             ctx.setResponseStatusCode(401);  
  48.             ctx.setResponseBody("{\"result\":\"accessToken is empty!\"}");  
  49.             return null;  
  50.         }  
  51.         //如果有token,则进行路由转发  
  52.         log.info("access token ok");  
  53.         //这里return的值没有意义,zuul框架没有使用该返回值  
  54.         return null;  
  55.     }  
  56.   
  57. }  

 

别的先不管,看看run方法,在这里可以获取到用户传来的所有参数,然后可以配置自己的规则来决定是否往最终的服务转发请求,false为不给最终的服务发送这次请求,默认为true。在这里,我们设置如果accessToken为空,就停止转发,直接给客户端返回结果。需要注意一点,Filter是可以配置多个的,按照order从小到大依次执行,即使设置了setSendZuulResponse(false),也是会继续执行下一个Filter的。

注意,路由转发的停止和继续是由ctx.setSendZuulResponse来控制的,与下面的return null无关,这个方法的return值没有意义,并没有使用。

效果如图

下一篇来详细看看Filter的配置。

posted @ 2017-11-03 17:22  Bigben  阅读(1279)  评论(0编辑  收藏  举报