前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「 从0到1学习微服务SpringCloud 」12 Zuul的综合使用

「 从0到1学习微服务SpringCloud 」12 Zuul的综合使用

作者头像
KEN DO EVERTHING
发布2019-05-15 13:00:08
4280
发布2019-05-15 13:00:08
举报
文章被收录于专栏:KEN DO EVERTHINGKEN DO EVERTHING

过滤器

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

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

代码语言:javascript
复制
@Component
public class TokenFilter extends ZuulFilter {

    /**
     * 过滤器类型
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     *  优先级,数字越大,优先级越低
     *  只做一般过滤,没有特殊要求的,可以放在内置过滤器后面
     * @return
     */
    @Override
    public int filterOrder() {
        //最后一个内置PRE过滤器后面
        return PRE_DECORATION_FILTER_ORDER+1;
    }

    /**
     * 是否执行该过滤器,true代表需要过滤
     * 这里可以忽略掉一些不需要过滤请求
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String token = request.getParameter("token");
        //如果没有token,则返回401
        //这里就不做校验了,只判断有无
        if(StringUtils.isEmpty(token)){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            ctx.setResponseBody("未登陆!");
             //设置返回体的编码为UTF-8
            HttpServletResponse response = ctx.getResponse();
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
        }
        return null;
    }
}

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

代码语言:javascript
复制
@Component
public class AddResponseHeaderFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return POST_TYPE;
    }

    @Override
    public int filterOrder() {
        //放在返回过滤器前
        return SEND_RESPONSE_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletResponse  response = context.getResponse();
        response.setHeader("my-response","hello");
        return null;
    }
}

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

3.测试 http://localhost:8900/myHi/hi?token=123

限流

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

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

代码实现

1.新建一个类,继承ZuulFilter

代码语言:javascript
复制
@Component
public class RateFilter extends ZuulFilter {
    /**
     * 创建令牌桶 容量为1(为了方便测试,这里设置小一点)
     */
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(1);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //设置顺序 请求转发过滤器 前
        return SERVLET_DETECTION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //获取不到令牌
        if(!RATE_LIMITER.tryAcquire()){
            //TODO 跳转到错误页面或友好提示
            throw new RuntimeException("访问人数过多,请稍后再试!");
        }
        return null;
    }
}

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

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

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

跨域

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

代码实现

代码语言:javascript
复制
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter(){
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        //是否支持Cookie跨域
        config.setAllowCredentials(true);
        //支持的原始域 *表示所有
        config.setAllowedOrigins(Arrays.asList("*"));
        //允许的头 *表示所有
        config.setAllowedHeaders(Arrays.asList("*"));
        //允许的请求方法 POST,GET等 *表示所有
        config.setAllowedMethods(Arrays.asList("*"));
        //缓存时间 表示300秒内对相同请求不需要再判断
        config.setMaxAge(300L);

        //path参数为对哪些域名进行设置 /**表示所有
        source.registerCorsConfiguration("/**",config);
        return  new CorsFilter(source);
    }
}

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

以上3种是Zuul比较常用的一些使用方式,今天就到这里,下期见~ 代码已更新至gitthub https://github.com/zhangwenkang0/springcloud-learning-from-0-to-1

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java从心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 限流
  • 跨域
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档