我是靠谱客的博主 舒心小懒猪,最近开发中收集的这篇文章主要介绍springboot2 springcloud Greenwich.SR3 构建微服务--7.服务网关zuul综合使用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

下面来讲一下zuul的综合使用, 在限流, 请求的校验, 请求处理后的添加处理方面的应用. 

这个就是网关的优势了.

 

zuul 中不同组件的作用

/**
 * 前置  pre
 * 限流   鉴定权限   参数校验  请求转发
 *
 * 后置  post
 * 统计  日志
 *
  因为zuul 和eureka 一样都是作为微服务中最基本的服务存在, 当zuul 挂了之后, 
就请求不到后面的服务了,所以很有必要最zuul进行高可用的设置.
 *  zuul的高可用. 注册多个zuul的节点.
 */

 

我们做下面的几个功能

1.在所有返回中添加一个头部信息

自定义的过滤器, 需要继承 ZuulFilter 这个类, 

filterType 标明是前置过滤器, 还是后置的过滤器, 

filterOrder 是过滤器的顺序, 因为存在多个过滤器, 需要排序,一一的经过

shouldFilter 是否过滤, 只有为true 才过滤,否则直接跳过了

run 真正的过滤的方法


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * 返回的时候,在请求头里面添加内容
 */
@Component
public class AddResponseFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_FORWARD_FILTER_ORDER - 1;
    }

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


    /**
     * 往返回里面添加东西
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("AddResponseFilter");
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response = requestContext.getResponse();
        //在请求头里面加了一个返回.
        response.setHeader("x-foo", UUID.randomUUID().toString());
        return null;
    }
}

 

2. 限流

我们使用google guava的令牌桶算法.



import com.example.zuulserver.exception.RateLimitException;
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;


/**
 * 限流, 使用令牌桶算法
 */
@Component
public class RateLimitFilter extends ZuulFilter {

    //guava的实现, 1s放入100个令牌
    private final static RateLimiter rateLimiter = RateLimiter.create(100);

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

    @Override
    public int filterOrder() {
        return FilterConstants.SERVLET_DETECTION_FILTER_ORDER - 1;
    }

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

    @Override
    public Object run() throws ZuulException {
        System.out.println("RateLimitFilter");
        //没有拿到令牌
        if(!rateLimiter.tryAcquire()){
            /*RequestContext requestContext = RequestContext.getCurrentContext();
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);*/
            throw new RateLimitException();
        }
        return null;
    }
}

3. token验证, 就是要求请求的链接必须带上一个token ,否则直接返回.



import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义token的验证器
 */
@Component
public class TokenFilter extends ZuulFilter {


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

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

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

    /**
     * 过滤的具体逻辑
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("TokenFilter");
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        //这是从url参数中获取, 也可以从header 和cookie中获取
        String token = request.getParameter("token");
        if(StringUtils.isBlank(token)){
            //因为测试,这里先注释掉了
            //context.setSendZuulResponse(false);
            //context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
        }
        return null;
    }
}

4. 买家权限鉴定


import com.example.common.util.CookieUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * 权限的校验,买家的
 */
@Component
public class BuyerFilter extends ZuulFilter {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

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

    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * true 就进行校验, false 不校验
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
//根据请求的路径判断
        if ("/order/create".equals(request.getRequestURI())) {
            return true;
        }
        return false;
    }


    /**
     * 权限的校验,买家和卖家的
     * /order/create 只能买家(cookie 中有openid)
     * /order/finish  只能卖家(cookie中有token, redis中有值)
     * /product/list  都可以访问
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        Cookie cookie = CookieUtil.getCookie(request, "openid");
        if (cookie == null || StringUtils.isBlank(cookie.getValue())) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
        }
        return null;
    }
}

 

5.卖家权限鉴定


import com.example.common.util.CookieUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * 权限的校验,卖家的
 */
@Component
public class SellerFilter extends ZuulFilter {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

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

    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * true 就进行校验, false 不校验
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
//根据请求的路径判断
        if ("/order/finish".equals(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    /**
     * 权限的校验,买家和卖家的
     * /order/create 只能买家(cookie 中有openid)
     * /order/finish  只能卖家(cookie中有token, redis中有值)
     * /product/list  都可以访问
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        //常量没有弄过来....
        Cookie cookie = CookieUtil.getCookie(request, "token");
        String value = cookie.getValue();
        Object user = stringRedisTemplate.opsForHash().get("user", value);
        if (cookie == null || StringUtils.isBlank(value) || (user == null)) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
        }
        return null;
    }
}

关于Zuul支持的cookie跨域问题, 可以添加配置


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;


/**
 * 跨域可以使用nginx上处理
 */
@Configuration
public class ZuulConfig {

    @Bean
    public CorsFilter corsFilter(){
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);//支持cookie跨域
        //设置原始域,http://www.a.com
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        //方法, post 还是 get
        configuration.setAllowedMethods(Arrays.asList("*"));
        //时间, 多长时间不检查
        configuration.setMaxAge(3000L);

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",configuration);
        CorsFilter filter = new CorsFilter(source);
        return filter;
    }


}

 

再多啰嗦一点,

其实RequestContext  就是个Map,还是实现了并发的Map,源码如下, 使用ThreadLocal实现的.

public class RequestContext extends ConcurrentHashMap<String, Object> {

private static RequestContext testContext = null;

    protected static final ThreadLocal<? extends RequestContext> threadLocal = new ThreadLocal<RequestContext>() {
        @Override
        protected RequestContext initialValue() {
            try {
                return contextClass.newInstance();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
    };
....
}

 

 

整个代码地址是:

https://github.com/changhe626/micro-service

Java Framework,欢迎各位前来交流java相关
QQ群:965125360

最后

以上就是舒心小懒猪为你收集整理的springboot2 springcloud Greenwich.SR3 构建微服务--7.服务网关zuul综合使用的全部内容,希望文章能够帮你解决springboot2 springcloud Greenwich.SR3 构建微服务--7.服务网关zuul综合使用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部