代码信息
本篇文章涉及代码版本
组件 | 版本 |
---|---|
Spring Boot | 2.0.8.RELEASE |
Spring Cloud | Finchley.SR1 |
本篇文章涉及应用
应用 | 说明 |
---|---|
base-eureka | 服务发现 |
base-zuul-upload | 配置上传限制的路由网关 |
base-producer-upload | 提供文件上传的应用 |
上一篇使用zuul实现了路由网关,既然zuul可以实现统一的网关控制那么使用zuul同样可以尝试文件大小控制
创建一个接收文件上传的服务
构建maven依赖
需要添加spring的web的相关支持。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
参数配置application.yml
此处为了测试zuul的文件拦截是否生效将client的文件大小上调至50MB
spring:
application:
name: base-producer-upload
servlet:
multipart:
enabled: true
max-file-size: 50MB
server:
port: 8105
eureka:
client:
service-url:
# 服务发现项目的地址
defaultZone: http://localhost:8000/eureka/
logging:
file: ${spring.application.name}.log
代码编写
上传代码
@RestController
public class FileUploadController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test()
throws IOException {
return "test";
}
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String handleFileUpload(@RequestParam(value = "file") MultipartFile file)
throws IOException {
byte[] bytes = file.getBytes();
File fileToSave = new File(file.getOriginalFilename());
FileCopyUtils.copy(bytes, fileToSave);
return fileToSave.getAbsolutePath();
}
}
zuul的配置
在zuul中将文件上传大小限制为10MB
spring:
application:
name: base-zuul-upload
servlet:
multipart:
enabled: true
max-file-size: 10Mb
server:
port: 8301
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
logging:
file: ${spring.application.name}.log
zuul:
routes:
consumer:
path: /client/**
serviceId: base-producer-upload
consumer:
ribbon:
listOfServers: http://localhost:8105/
测试
为了方便测试本地编写了一个上传页面
首先我们测试一个小图片
可以看到成功上传了。
异常拦截处理
因为使用了form表单点击后页面会进行跳转,无法看到错误内容。所以我编写了个错误处理类进行处理。
/**
* @author daify
* @date 2019-07-08
*/
@ControllerAdvice
@Slf4j
public class ZuulRestControllerAdvice {
/**
* 全局异常处理,反正异常返回统一格式的map
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public String exceptionHandler(Exception ex){
log.error("------------------------------------");
log.error("发生了异常");
log.error(ex.getMessage());
return "error";
}
}
然后我们上传一个超过10MB但是小于50MB的内容。可以看到控制台打印了错误内容。
2019-07-08 22:15:44.580 ERROR 6592 --- [nio-8301-exec-2] d.z.c.ZuulRestControllerAdvice : ------------------------------------
2019-07-08 22:15:44.580 ERROR 6592 --- [nio-8301-exec-2] d.z.c.ZuulRestControllerAdvice : 发生了异常
2019-07-08 22:15:44.580 ERROR 6592 --- [nio-8301-exec-2] d.z.c.ZuulRestControllerAdvice : Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (18084623) exceeds the configured maximum (10485760)
首先可以看到我发起了一次申请却出现了错误的日志
zuul的异常处理逻辑
上面最开始我是尝试使用上一篇中使用的ZuulFilter进行错误处理。但是实际上发现并没有起到任何作用,然后我又仔细看了ZuulFilter的处理过程。
这是ZuulFilter异常处理过程。
从上面可以看出来ZuulFilter其实主要处理的是pre、routing、post阶段时候发生的异常。而文件上传的限制是zuul应用作为一个springboot项目自身的限制。这个时候使用ZuulFilter自然无法拦截。
新建一个ZuulFilter的异常处理
@Slf4j
@Component
public class ErrorFilter extends ZuulFilter {
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return -1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
try {
RequestContext ctx = RequestContext.getCurrentContext();
Throwable throwable = ctx.getThrowable();
if (throwable != null && throwable instanceof ZuulException) {
log.error("Zuul failure --------------------------------- ");
ZuulException zuulException = (ZuulException)throwable;
log.error("Zuul failure detected: " + zuulException.getMessage(), zuulException);
ctx.remove("error.status_code");
ctx.setResponseBody("Overriding Zuul Exception Body");
ctx.getResponse().setContentType("application/json");
ctx.setResponseStatusCode(500);
}
} catch (Exception ex) {
log.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}
在之前这个异常处理已经在项目中存在,但是在文件大小超过上限的错误这个过滤器并没有发挥作用。之前在base-producer-upload
编写了一个测试方法test,我们之前的调用是没有问题的。现在我们关闭掉base-producer-upload
项目,然后发起请求可以看到控制台打印下面内容。
2019-07-08 22:54:40.282 ERROR 21476 --- [nio-8301-exec-1] dailearn.zuul.filter.ErrorFilter : Zuul failure ---------------------------------
2019-07-08 22:54:40.285 ERROR 21476 --- [nio-8301-exec-1] dailearn.zuul.filter.ErrorFilter : Zuul failure detected: Filter threw Exception
com.netflix.zuul.exception.ZuulException: Filter threw Exception
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:227) ~[zuul-core-1.3.1.jar:1.3.1]
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157) ~[zuul-core-1.3.1.jar:1.3.1]
at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:118) ~[zuul-core-1.3.1.jar:1.3.1]
at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:96) ~[zuul-core-1.3.1.jar:1.3.1]
at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:116) ~[zuul-core-1.3.1.jar:1.3.1]
at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:81) ~[zuul-core-1.3.1.jar:1.3.1]
at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:165) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequest(ZuulController.java:44) [spring-cloud-netflix-zuul-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:981) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:873) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.37.jar:8.5.37]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:858) [spring-webmvc-5.0.12.RELEASE.jar:5.0.12.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.37.jar:8.5.37]
......
这个时候才是ZuulFilter发挥作用的时候。
总结
可以这么简单的理解
- zuul项目本身请求导致的错误可以使用springboot的异常处理逻辑。
- zuul远程调用时发生的错误可以使用ZuulFilter的error来进行处理。
本篇文章并未贴出所有代码,涉及的源码下载地址:https://gitee.com/daifylearn/cloud-learn
ps.上述的所有项目都是可以成功运行的。但是在后期为了实现每个应用端口尽量不冲突会有些许调整,而后续某次作死调整结构和名称可能会导致部分项目无法运行o(╯□╰)o,如果发现请留言我进行修改。