springcloud-zuul详解

源码解析

  • Spring.factories中加载了ZuulServerAutoConfiguration和ZuulProxyAutoConfiguration
  • ZuulServerAutoConfiguration中注册了FilterRegistrationBean
  • FilterRegistrationBean设置new了一个ZuulServletFilter
  • ZuulServletFilter实现了Filter接口,并在doFilter中调用了zuul的几个filter
try {
                preRouting();
            } catch (ZuulException e) {
                error(e);
                postRouting();
                return;
            }
            
            // Only forward onto to the chain if a zuul response is not being sent
            if (!RequestContext.getCurrentContext().sendZuulResponse()) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            
            try {
                routing();
            } catch (ZuulException e) {
                error(e);
                postRouting();
                return;
            }
            try {
                postRouting();
            } catch (ZuulException e) {
                error(e);
                return;
            }
  • 只有在pre阶段设置zuulResponse为false,才能阻止之后过滤器的执行
  • Post过滤器主要有两个
    • sendError:order=0,
    • sendResponse:order=1000,优先在responseBody中获取数据,其次在responseDataStream中获取。可以在error过滤器中设置错误信息,在errorController中获取,返回详细错误信息。
  • 过滤器中的异常处理

在sendErrorFilter中是这样判断异常的

所以在过滤器中要设置异常,

springcloud-zuul详解_第1张图片

  • 默认异常信息源码解析
    1. SendErrorFilter会转发到/error端点
    2. /error端点由BasicErrorController来提供
    3. 调用getErrorAttributes来组织错误信息
    4. 利用ErrorAttributes接口的实现,默认实现是DefaultErrorAttributes
    5. 该实现有注解@ConditionalOnMissingBean

应用

  • 自定义异常信息,多种方式
    1. 提供一个ErrorAttributes的实现类
    2. 有异常信息时使用,将请求转发到/error,可以通过实现errorController,并在里面添加/error的requestMapping方法,自定义错误信息
    3. 禁用error过滤器,自定义error过滤器返回数据
  • 获取接口调用的返回值,可以参考SendResponseFilter的实现,获取完之后一定要重新设置返回值,例如
@Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        if(ctx.getResponseBody() != null){
            System.out.println(ctx.getResponseBody());
        }else{
            InputStream is = ctx.getResponseDataStream();
            try {
                byte[] b = new byte[10];

                int len = -1;
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                while ((len = is.read(b)) != -1){
                    bos.write(b, 0, len);
                }

                String r = new String(bos.toByteArray());
                System.out.println(r);
                //次处很重要
                ctx.setResponseBody(r);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

 

你可能感兴趣的:(SpringCloud,zuul)