Spring cloud Zuul网关异常处理
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();
}
最新文章
- Spring Boot入门实例
- Windows中遇到的些问题及解决办法
- PostgreSQL保存文件到数据库
- 小米手机(HM1SW)高通开发android程序全过程
- 菲涅尔反射(Fresnel Reflection)
- jmeter也有loadrunner一样的图像
- 基于html5实现的愤怒的小鸟网页游戏
- oracle 之路目录
- AES加密算法原理
- jQuery.mobile.changePage() | jQuery Mobile API Documentation
- bootstrap-wysihtml5设置值
- [SCOI2007]最大土地面积
- 《剑指offer》和为S的两个数字
- HTML/CSS 速写神器 Emmet语法
- apache伪静态配置(URL重写)
- 在JS中统计函数执行次数与执行时间
- python魔法方法-属性访问控制
- js复制内容到剪切板
- 短信API——短信验证码
- 关于softnet的加密硬件狗 也就是所谓的赛孚耐
热门文章
- java编码规范_缩进和注释
- day 09 课后作业
- POJ1095 Trees Made to Order(JAVA)
- iOS应用发布中的一些细节
- Linux 线程调度策略与线程优先级
- Mac下包管理平台homebrew的使用
- (转)AIX的SVMON命令详解
- springmvc执行原理及自定义mvc框架
- 《LeetBook》leetcode题解(3):Longest Substring Without Repeating Characters[M]——哈希判断重复
- 多功能电子通讯录(涉及到了双向链表的使用,Linux文件编程等等)