Spring cloud Zuul网关异常处理

一 异常测试:

1> 创建一个pre类型的过滤器,并在该过滤器的run方法实现中抛出一个异常。比如下面的实现,在run方法中调用的doSomething方法将抛出RuntimeException异常

package com.xbchen.springcloud.filter.post;

import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class ThrowExceptionPostFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(ThrowExceptionPostFilter.class); @Override
public String filterType() {
return "post";
} @Override
public int filterOrder() {
return 10;
} @Override
public boolean shouldFilter() {
return true;
} @Override
public Object run() {
log.info("This is a post filter, it will throw a RuntimeException");
doSomething();
return null;
} private void doSomething() {
throw new RuntimeException("Exist some errors...");
} }

2> 在启动类中为过滤器创建Bean

@Bean
public ThrowExceptionFilter throwExceptionFilter() {
return new ThrowExceptionFilter();
}

3> 运行启动类

4> 发现后台并没抛出异常信息

二 问题分析:

查看postRoute阶段的异常处理过滤器SendErrorFilter中的方法shouldFilter

注意: 新版本中已经修复了该问题,取消了error.status_code的判断。

即: 只有上线文中包含error.status_code,才能被SendErrorFilter处理。

以此需要自行处理。

处理方式1: 在抛异常时,自行捕获设置error.status_code

@Override
public Object run() {
log.info("This is a post filter, it will throw a RuntimeException");
//doSomething();
RequestContext context=RequestContext.getCurrentContext();
try{
doSomething();
}catch (Exception e){
context.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
context.set("error.exception",3);
}
return null;
}

处理方式2:新增一个error处理的过滤器

@Component
public class ErrorFilter extends ZuulFilter {
Logger log = LoggerFactory.getLogger(ErrorFilter.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 20;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
Throwable throwable = RequestContext.getCurrentContext().getThrowable();
log.error("this is a ErrorFilter : {}", throwable.getCause().getMessage());
ctx.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
ctx.set("error.exception", throwable.getCause());
return null;
} }

三:遗留问题:路由包括3阶段, 正常处理过程:preRoute-->route-->postRoute

其中preRoute 和route异常时,会被捕获直接进入postRoute;

会经过postRoute的过滤器(SendErrorFilter extends ZuulFilter)

但是postRoute阶段的异常,是没有处理的过滤器的。以此需要针对postRoute阶段的异常进行单独处理。

处理方式:

新增处理类,扩展过滤器处理类FilterProcessor的processZuulFilter方法

public class DidiFilterProcessor extends FilterProcessor {

    @Override
public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
try {
return super.processZuulFilter(filter);
} catch (ZuulException e) {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.set("failed.exception", e);
ctx.set("failed.filter", filter);
throw e;
}
}
}

在启动类中设置处理类

@SpringBootApplication
@EnableZuulProxy
public class GatewayApplication { public static void main(String[] args) {
FilterProcessor.setProcessor(new DidiFilterProcessor());
SpringApplication.run(GatewayApplication.class, args);
}
}

新增post阶段的异常处理过滤器

/**
* 从POST抛出的异常,使用该过滤器返回错误信息
*/
@Component
public class ErrorExtFilter extends SendErrorFilter {
Logger log = LoggerFactory.getLogger(ErrorExtFilter.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 30;
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
ZuulFilter failedFilter = (ZuulFilter) ctx.get("failed.filter");
if(failedFilter != null && failedFilter.filterType().equals("post")) {
return true;
}
return false;
}
}

四:异常自定义

以上异常已经正常抛出,但是格式并不一定符合项目要求,或者有时并不需要将异常返回给客户端。

由于异常信息格式是在DefaultErrorAttributes定义的,以此可对该类进行扩展。

比如:异常异常信息,避免返回到客户端。

public class DidiErrorAttributes extends DefaultErrorAttributes {

    @Override
public Map<String, Object> getErrorAttributes (
RequestAttributes requestAttributes, boolean includeStackTrace){
Map<String, Object> result = super.getErrorAttributes(requestAttributes, includeStackTrace);
result.remove("exception");
return result;
}
}

在启动类中新增异常属性扩展类的Bean创建。

@Bean
public DefaultErrorAttributes errorAttributes() {
return new DidiErrorAttributes();
}

最新文章

  1. Spring Boot入门实例
  2. Windows中遇到的些问题及解决办法
  3. PostgreSQL保存文件到数据库
  4. 小米手机(HM1SW)高通开发android程序全过程
  5. 菲涅尔反射(Fresnel Reflection)
  6. jmeter也有loadrunner一样的图像
  7. 基于html5实现的愤怒的小鸟网页游戏
  8. oracle 之路目录
  9. AES加密算法原理
  10. jQuery.mobile.changePage() | jQuery Mobile API Documentation
  11. bootstrap-wysihtml5设置值
  12. [SCOI2007]最大土地面积
  13. 《剑指offer》和为S的两个数字
  14. HTML/CSS 速写神器 Emmet语法
  15. apache伪静态配置(URL重写)
  16. 在JS中统计函数执行次数与执行时间
  17. python魔法方法-属性访问控制
  18. js复制内容到剪切板
  19. 短信API——短信验证码
  20. 关于softnet的加密硬件狗 也就是所谓的赛孚耐

热门文章

  1. java编码规范_缩进和注释
  2. day 09 课后作业
  3. POJ1095 Trees Made to Order(JAVA)
  4. iOS应用发布中的一些细节
  5. Linux 线程调度策略与线程优先级
  6. Mac下包管理平台homebrew的使用
  7. (转)AIX的SVMON命令详解
  8. springmvc执行原理及自定义mvc框架
  9. 《LeetBook》leetcode题解(3):Longest Substring Without Repeating Characters[M]——哈希判断重复
  10. 多功能电子通讯录(涉及到了双向链表的使用,Linux文件编程等等)