三行代码解决Springboot框架自带异常

简介: 近期一个原业务图片上传的接口偶发会报异常,原有高可用方案是当上传七牛云失败上传腾讯云,都失败才会报异常,或者会存在目录创建失败的异常

欢迎订阅关注公众号:赵KK日常技术记录

近期一个原业务图片上传的接口偶发会报异常,原有高可用方案是当上传七牛云失败上传腾讯云,都失败才会报异常,或者会存在目录创建失败的异常,此类异常重试即可解决,但近期异常如下

org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 10485760 bytes.
  at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.handleParseFailure(StandardMultipartHttpServletRequest.java:121) ~[spring-web-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:114) ~[spring-web-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:87) ~[spring-web-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:87) ~[spring-web-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1175) ~[spring-webmvc-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1010) ~[spring-webmvc-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) ~[spring-webmvc-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:665) ~[javax.servlet-api-4.0.1.jar!/:4.0.1]
  at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.4.RELEASE.jar!/:5.1.4.RELEASE]
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:750) ~[javax.servlet-api-4.0.1.jar!/:4.0.1]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.14.jar!/:9.0.14]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar!/:9.0.14]
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.14.jar!/:9.0.14]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar!/:9.0.14]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar!/:9.0.14]
  at com.yh.csx.tms.core.security.TokenAuthenticationFilter.doFilter(TokenAuthenticationFilter.java:64) ~[csx-b2b-tms-core-3.1.1-SNAPSHOT.jar!/:3.1.1-SNAPSHOT]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.14.jar!/:9.0.14]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.14.jar!/:9.0.14]
  at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90) ~[spring-boot-actuator-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  

大意就是超过了限制10M大小从而引发报错,第一时间并没有点击源码进行查看,想的是针对此类异常进行catch后报正常错误,代码改造如下:

} catch (MaxUploadSizeExceededException e) {
            log.error("上传图片超过限制:{}MB 操作人:{} 绝对路径:{} 异常:{} 轨迹:{}", size, userManager.getLocationCode() + userManager.getUserName() + userManager.getTelPhone(), tempFile.getAbsolutePath(), e.getMessage(), e);
            ExceptionDetails details = ExceptionDetails.createBuilder(code(),msg())
                    .setBizLevel(5).setBizScope("上传图片超过限制")
                    .setBizDetails(msg()).build();
            throw  new Exception(details);
}
  

测试效果:

{
  "code": 99990500,
  "message": "未知异常"
}
  

image.png

仍旧报错,溯源源码,过程不在此啰嗦,大意是创建Http请求是在servlet请求的mock中会校验请求的大小

protected void handleParseFailure(Throwable ex) {
    String msg = ex.getMessage();
    if (msg != null && msg.contains("size") && msg.contains("exceed")) {
      throw new MaxUploadSizeExceededException(-1, ex);
    }
    throw new MultipartException("Failed to parse multipart servlet request", ex);
  }
  

也就是请求是发生在dofilter的前置阶段,尝试在filter阶段加catch仍然没效果,然后针对RestController层进行异常处理,RestControllerAdvice即使指定异常处理的,实现如下:

@RestControllerAdvice(annotations = {Controller.class, RestController.class})
public class FileUploadExceptionHandler {

    @ExceptionHandler(MultipartException.class)
    public CommonResponse uploadExcepttion(MultipartException e){
        return CommonResponse.error(code(),msg());
    }
}
  

配置如下:

#spring.servlet.multipart.max-file-size = 10MB
#spring.servlet.multipart.max-request-size = 10MB
#spring.servlet.multipart.resolve-lazily=true
#server.tomcat.max-swallow-size = 10MB
  

模拟请求如下:
image.png

测试效果:

image.png

查询日志调用链,原有业务是针对图片上传的,就算是市面上所有手机也不可能单张图片大于10M才对,溯源后发现,此类业务是由上游针对PDF调用的,但查询关联数据后发现PDF仅仅三行数据,外加电子签名超过10M导致失败,且用户无法感知此类错误,因为是由后台根据电子签名生成PDF的,此类错误即便报正常提示用户也体验不好。最终解决方案应有生成PDF端去压缩大小后控制在一定范围内,并根据调用解决来处理逻辑,这里的配置10M是不合理的,因为在特殊情况下的单据是有可能大于10M的,所有应由压缩端处理,调的挺好,下次别调了图片

目录
相关文章
|
2月前
|
Java Spring
聊聊你对SpringBoot框架的理解 ?
SpringBoot是Spring家族中流行的子项目,旨在简化Spring框架开发的繁琐配置。它主要提供三大功能:starter起步依赖简化依赖管理,自动配置根据条件创建Bean,以及内嵌Web服务器支持Jar包运行,极大提升了开发效率。
101 0
|
2月前
|
NoSQL Java 数据库连接
SpringBoot框架
Spring Boot 是 Spring 家族中最流行的框架,旨在简化 Spring 应用的初始搭建与开发。它通过自动配置、起步依赖和内嵌服务器三大核心功能,大幅减少配置复杂度,提升开发效率。开发者可快速构建独立运行的 Web 应用,并支持多种数据访问技术和第三方集成。
|
3月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
464 1
Spring boot 使用mybatis generator 自动生成代码插件
|
3月前
|
Java API 网络架构
基于 Spring Boot 框架开发 REST API 接口实践指南
本文详解基于Spring Boot 3.x构建REST API的完整开发流程,涵盖环境搭建、领域建模、响应式编程、安全控制、容器化部署及性能优化等关键环节,助力开发者打造高效稳定的后端服务。
381 1
|
2月前
|
缓存 安全 Java
Spring 框架核心原理与实践解析
本文详解 Spring 框架核心知识,包括 IOC(容器管理对象)与 DI(容器注入依赖),以及通过注解(如 @Service、@Autowired)声明 Bean 和注入依赖的方式。阐述了 Bean 的线程安全(默认单例可能有安全问题,需业务避免共享状态或设为 prototype)、作用域(@Scope 注解,常用 singleton、prototype 等)及完整生命周期(实例化、依赖注入、初始化、销毁等步骤)。 解析了循环依赖的解决机制(三级缓存)、AOP 的概念(公共逻辑抽为切面)、底层动态代理(JDK 与 Cglib 的区别)及项目应用(如日志记录)。介绍了事务的实现(基于 AOP
|
2月前
|
存储 缓存 NoSQL
Spring Cache缓存框架
Spring Cache是Spring体系下的标准化缓存框架,支持多种缓存(如Redis、EhCache、Caffeine),可独立或组合使用。其优势包括平滑迁移、注解与编程两种使用方式,以及高度解耦和灵活管理。通过动态代理实现缓存操作,适用于不同业务场景。
217 0
|
2月前
|
消息中间件 NoSQL Java
SpringBoot框架常见的starter你都用过哪些 ?
本节介绍常见的Spring Boot Starter,分为官方(如Web、AOP、Redis等)与第三方(如MyBatis、MyBatis Plus)两类,用于快速集成Web开发、数据库、消息队列等功能。
181 0
|
2月前
|
缓存 安全 Java
第五章 Spring框架
第五章 Spring框架
|
2月前
|
缓存 Java 数据库
第五章 Spring框架
第五章 Spring框架