上次讲了Zuul的基本使用,这篇讲的是综合使用,比如过滤器,限流,鉴权等应用

这里继续使用api-getway这个项目

过滤器

实现token验证(前置过滤器)

1.新建一个类,继承ZuulFilter,细节方面看下面代码,还有别忘了在类上加@Component注解,否则不生效

  1. @Component
  2. public class TokenFilter extends ZuulFilter {
  3. /**
  4. * 过滤器类型
  5. * @return
  6. */
  7. @Override
  8. public String filterType() {
  9. return PRE_TYPE;
  10. }
  11. /**
  12. * 优先级,数字越大,优先级越低
  13. * 只做一般过滤,没有特殊要求的,可以放在内置过滤器后面
  14. * @return
  15. */
  16. @Override
  17. public int filterOrder() {
  18. //最后一个内置PRE过滤器后面
  19. return PRE_DECORATION_FILTER_ORDER+1;
  20. }
  21. /**
  22. * 是否执行该过滤器,true代表需要过滤
  23. * 这里可以忽略掉一些不需要过滤请求
  24. * @return
  25. */
  26. @Override
  27. public boolean shouldFilter() {
  28. return true;
  29. }
  30. @Override
  31. public Object run() throws ZuulException {
  32. RequestContext ctx = RequestContext.getCurrentContext();
  33. HttpServletRequest request = ctx.getRequest();
  34. String token = request.getParameter("token");
  35. //如果没有token,则返回401
  36. //这里就不做校验了,只判断有无
  37. if(StringUtils.isEmpty(token)){
  38. ctx.setSendZuulResponse(false);
  39. ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
  40. ctx.setResponseBody("未登陆!");
  41. //设置返回体的编码为UTF-8
  42. HttpServletResponse response = ctx.getResponse();
  43. response.setHeader("Content-type", "text/html;charset=UTF-8");
  44. response.setCharacterEncoding("UTF-8");
  45. }
  46. return null;
  47. }
  48. }

2.开启Eureka Server,api-getway,service-hi项目

3.测试

不带token http://localhost:8900/myHi/hi

带token http://localhost:8900/myHi/hi?token=123

添加Response Header(后置过滤器)

1.新建一个类,继承ZuulFilter

  1. @Component
  2. public class AddResponseHeaderFilter extends ZuulFilter {
  3. @Override
  4. public String filterType() {
  5. return POST_TYPE;
  6. }
  7. @Override
  8. public int filterOrder() {
  9. //放在返回过滤器前
  10. return SEND_RESPONSE_FILTER_ORDER - 1;
  11. }
  12. @Override
  13. public boolean shouldFilter() {
  14. return true;
  15. }
  16. @Override
  17. public Object run() throws ZuulException {
  18. RequestContext context = RequestContext.getCurrentContext();
  19. HttpServletResponse response = context.getResponse();
  20. response.setHeader("my-response","hello");
  21. return null;
  22. }
  23. }

2.开启Eureka Server,api-getway,service-hi项目

3.测试

http://localhost:8900/myHi/hi?token=123

限流

限流的功能也是经常会在网关实现,我们这里使用令牌桶算法实现,这个算法已经有相关实现了,直接用就行

令牌桶算法:一边以一个固定的速率发令牌,另一边用一个固定大小的桶装令牌,桶满了则将令牌该令牌丢弃,否则放进桶里。进来的请求尝试从桶里取令牌,取到令牌的请求放行,没有令牌的请求则会被拒绝。如下图

代码实现

1.新建一个类,继承ZuulFilter

  1. @Component
  2. public class RateFilter extends ZuulFilter {
  3. /**
  4. * 创建令牌桶 容量为1(为了方便测试,这里设置小一点)
  5. */
  6. private static final RateLimiter RATE_LIMITER = RateLimiter.create(1);
  7. @Override
  8. public String filterType() {
  9. return PRE_TYPE;
  10. }
  11. @Override
  12. public int filterOrder() {
  13. //设置顺序 请求转发过滤器 前
  14. return SERVLET_DETECTION_FILTER_ORDER - 1;
  15. }
  16. @Override
  17. public boolean shouldFilter() {
  18. return true;
  19. }
  20. @Override
  21. public Object run() throws ZuulException {
  22. //获取不到令牌
  23. if(!RATE_LIMITER.tryAcquire()){
  24. //TODO 跳转到错误页面或友好提示
  25. throw new RuntimeException("访问人数过多,请稍后再试!");
  26. }
  27. return null;
  28. }
  29. }

2.开启Eureka Server,api-getway,service-hi项目

3.测试

在过滤器run方法中打个断点,然后开3个浏览器tag访问http://localhost:8900/myHi/hi?token=123,进入断点后,点击忽略断点,再点击释放断点运行程序

结果:

至少有一个请求会被拒绝,后台抛出异常

跨域

浏览器是不允许跨域访问,通常解决跨域,可在接口类或方法加上@CrossOrigin(allowCredentials = “true”),但这种方法是很繁琐的,不可能有100个接口就加100次,所以我们这里可以使用Zuul实现跨域

代码实现

  1. @Configuration
  2. public class CorsConfig {
  3. @Bean
  4. public CorsFilter corsFilter(){
  5. final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  6. final CorsConfiguration config = new CorsConfiguration();
  7. //是否支持Cookie跨域
  8. config.setAllowCredentials(true);
  9. //支持的原始域 *表示所有
  10. config.setAllowedOrigins(Arrays.asList("*"));
  11. //允许的头 *表示所有
  12. config.setAllowedHeaders(Arrays.asList("*"));
  13. //允许的请求方法 POST,GET等 *表示所有
  14. config.setAllowedMethods(Arrays.asList("*"));
  15. //缓存时间 表示300秒内对相同请求不需要再判断
  16. config.setMaxAge(300L);
  17. //path参数为对哪些域名进行设置 /**表示所有
  18. source.registerCorsConfiguration("/**",config);
  19. return new CorsFilter(source);
  20. }
  21. }

因为跨域是需要在不同域名下,这里不太好演示,就不测试了。

以上3种是Zuul比较常用的一些使用方式,今天就到这里,下期见~

代码已更新至gitthub

https://github.com/zhangwenkang0/springcloud-learning-from-0-to-1

如果觉得不错,分享给你的朋友!

一个立志成大腿而每天努力奋斗的年轻人

伴学习伴成长,成长之路你并不孤单!

「 从0到1学习微服务SpringCloud 」12 Zuul的综合使用的更多相关文章

  1. 「 从0到1学习微服务SpringCloud 」10 服务网关Zuul

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」06 统一配置中心Spring Cloud Config 「 从0到1学习微服务SpringCloud 」07 RabbitM ...

  2. 「 从0到1学习微服务SpringCloud 」09 补充篇-maven父子模块项目

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」06 统一配置中心Spring Cloud Config 「 从0到1学习微服务SpringCloud 」07 RabbitM ...

  3. 「 从0到1学习微服务SpringCloud 」08 构建消息驱动微服务的框架 Spring Cloud Stream

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...

  4. 「 从0到1学习微服务SpringCloud 」07 RabbitMq的基本使用

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...

  5. 「 从0到1学习微服务SpringCloud 」06 统一配置中心Spring Cloud Config

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...

  6. 「 从0到1学习微服务SpringCloud 」05服务消费者Fegin

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...

  7. 「 从0到1学习微服务SpringCloud 」04服务消费者Ribbon+RestTemplate

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...

  8. 「 从0到1学习微服务SpringCloud 」03 Eureka的自我保护机制

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 Eureka的高可用需要 ...

  9. 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! Spring Cloud Eureka 基于Netflix Eureka做了二次封装(Spring Clo ...

随机推荐

  1. vue-cli 3.0 eslint

    1.关闭eslint module.exports = { configureWebpack: { devtool: 'source-map' }, lintOnSave: false } 2.修改e ...

  2. IdentityServer4 sign-in

    原文地址 Sign-in IdentityServer 代表 user 分配token之前,user必须登录IdentityServer Cookie authentication 使用 cookie ...

  3. 011.MFC_Slider

    滑块CSliderCtrl 常用函数SetLineSize() GetLineSize() SetPageSize() GetPageSize()SetRangeMax() GetRangeMax() ...

  4. Hadoop Authentication

    我被被派去做别的事情了,所以与hadoop相关的工作就只能搁下.写篇总结,把最近遇到的和kerberos相关的东西列一下. JAAS是Java 认证和授权服务(Java Authentication ...

  5. Centos 7.5安装 Nginx 1.14.1

    1. 准备工作 查看系统版本 输入命令 cat /etc/redhat-release 我的Centos版本 CentOS Linux release 7.5.1804 (Core) 安装nginx所 ...

  6. java基础 -- 关键字final的用法

    用法一(修饰变量): Final变量能被显式地初始化并且只能初始化一次.被声明为final的对象的引用不能指向不同的对象.但是final对象里的数据可以被改变.也就是说final对象的引用不能改变,但 ...

  7. ubuntu conda install ERROR missing write permission错误

    报错: ondaIOError: Missing write permissions in: /usr/local/anaconda3 # # You don't appear to have the ...

  8. 【题解】JXOI2018游戏(组合数)

    [题解]JXOI2018游戏(组合数) 题目大意 对于\([l,r]\)中的数,你有一种操作,就是删除一个数及其所有倍数.问你删除所有数的所有方案的步数之和. 由于这里是简化题意,有一个东西没有提到: ...

  9. 【题解】CF1056F Write the Contest(三分+贪心+DP)

    [题解]CF1056F Write the Contest(三分+贪心+DP) 最优化问题的三个解决方法都套在一个题里了,真牛逼 最优解应该是怎样的,一定存在一种最优解是先完成了耗时长的任务再干别的( ...

  10. 「Luogu P2508」[HAOI2008]圆上的整点 解题报告

    题面 给定圆的半径,求圆上整点数 这是一道很Nice的数学题!超爱!好吧,由于这道题,我去Study了一下复数(complex number)复杂的数 真棒!!! 有兴趣的戳这里!!!\(\huge ...