• springboot ControllerAdvice 类似上传超出文件大小异常无法捕获问题详解及解决方式


      spring boot/mvc通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理

        在spring web项目开发中,我们经常会遇到各种exception,这些exception根据业务或者场景不同抛出不同的信息和返回类型,有的exception需要返回json数据格式的错误,有的exception又需要跳转到某个错误页面。这里将会讲解常见的几个exception统一处理。

    通过注解@RestControllerAdvice统一处理rest接口的异常信息。

    注意@RestControllerAdvice注解一般在spring boot接口项目中使用。spring普通项目也支持不过需要高版本的spring才有@RestControllerAdvice注解标签。

    @ControllerAdvice和@RestControllerAdvice都可以指向控制器的一个子集:
    
    // 指向所有带有注解@RestController的控制器
    @ControllerAdvice(annotations = RestController.class)
    public class AnnotationAdvice {}
    
    // 指向所有指定包中的控制器
    @ControllerAdvice("org.example.controllers")
    public class BasePackageAdvice {}
    
    // 指向所有带有指定签名的控制器
    @ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
    public class AssignableTypesAdvice {}

    问题不是怎么设置文件大小,而是超过设置的最大值后,异常怎么捕获,因为在进controller之前都已经抛出异常了。

    配置文件 修改上传文件大小限制

    spring.servlet.multipart.max-file-size=2MB

    方式一:

    增加异常捕获类

    @RestControllerAdvice
    public class MyExceptionHandler {
            /* spring默认上传大小1MB 超出大小捕获异常MaxUploadSizeExceededException */
        @ExceptionHandler(MaxUploadSizeExceededException.class)
        public Map handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
            return Map.of("code", 500, "msg", "文件大小超出1MB限制, 请压缩或降低文件质量! ");
        }
    }

    或者 

    
     
    @RestControllerAdvice
    public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
     private static final Logger logger = 
        LoggerFactory.getLogger(GlobalExceptionHandler.class);
     
     /**
         * 处理上传异常
         * @param t
         * @return
         */
        @ExceptionHandler(MultipartException.class)
        public ResponseEntity<Result> handleAll(Throwable t) throws Exception {
            // TODO do Throwable t
            logger.error("=>"+t.getMessage());
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type","application/json;charset=UTF-8");
            return new ResponseEntity<>(new Result(-1,"上传文件异常!",null),headers, HttpStatus.OK);
        }
     
     
    

    注解@ControllerAdvice的类可以拥有@ExceptionHandler, @InitBinder或 @ModelAttribute注解的方法,并且这些方法会被应用到控制器类层次的所有@RequestMapping方法上。

     此处注意使用

    @RestControllerAdvice

    而不能

    
    @ControllerAdvice(
        annotations = {RestController.class}
    )

    方式二

    文件大小的校验是在controller之前的,可以通过继承CommonsMultipartResolver类,覆盖parseRequest方法,捕获异常后自己处理 

    在使用Spring Security时,CommonsMultipartResolver不会作为“multipartResolver”bean添加,而是作为“filterMultipartResolver”:

    @Bean(name="filterMultipartResolver")
    CommonsMultipartResolver filterMultipartResolver() {
        CommonsMultipartResolver filterMultipartResolver = new CommonsMultipartResolver();
        filterMultipartResolver.setMaxUploadSize(MAXSIZE);
        return filterMultipartResolver;
    }

    如果我设置filterMultipartResolver.setResolveLazily(true);没什么区别.

    如果我用自己的子类化CommonsMultipartResolver,并用捕获MaxUploadSizeExceededException并返回一个空的MultipartParsingResult的东西来覆盖parseRequest()方法,我会得到一个“403 Forbidden”错误:

    public class ExtendedCommonsMultipartResolver extends CommonsMultipartResolver {
        protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
            String encoding = determineEncoding(request);
            try {
                return super.parseRequest(request);
            } catch (MaxUploadSizeExceededException e) {
                return parseFileItems(Collections.<FileItem> emptyList(), encoding);
            }
        }
    }

    最后,实现某种本地或全局的ExceptionHandler没有任何意义,因为它永远不会被调用. 

    尝试使用@ControllerAdvice创建一个单独的类,这将处理来自所有控制器的异常。

    @ControllerAdvice 
    public class ExceptionControllerAdvice { 
    
        @ExceptionHandler(MaxUploadSizeExceededException.class) 
    public String handleException(MaxUploadSizeExceededException e, RedirectAttributes redirectAttributes) { 
        redirectAttributes.addFlashAttribute("uploadErrorMessage", e.getCause().getMessage()); 
        return "redirect:/page"; 
    } 
    } 

    因此,如果我们在@ControllerAdvice类中定义的方法上我们@ExceptionHandler注解,它将被应用到所有控制器。

    正因为当初对未来做了太多的憧憬,所以对现在的自己尤其失望。生命中曾经有过的所有灿烂,终究都需要用寂寞来偿还。
  • 相关阅读:
    【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类
    JAVA详设——UML(用例图、类图、时序图)
    FreeTDS-SQL Server在linux和unix下的免费驱动
    【转】移动oracle LOB索引到其他表空间
    [转载]JDBC读写Oracle的CLOB、BLOB
    JProgressBar与Timer的配套使用
    网页美工设计及源码
    分析SignalTap的仿真结果
    用SignalTap进行硬件仿真
    单周期CPU设计的理论基础
  • 原文地址:https://www.cnblogs.com/candlia/p/11919945.html
Copyright © 2020-2023  润新知