楼主前几天写了一篇“Java子线程中的异常处理(通用)”文章,介绍了在多线程环境下3种通用的异常处理方法。

但是平时大家的工作一般是基于开发框架进行的(比如Spring MVC,或Spring Boot),所以会有相应特定的异常处理方法,这篇文章要介绍的就是web应用中的异常处理。

想快速解决问题的小伙伴可以只看“解决办法”,想进一步了解细节的小伙伴还可以看“深入剖析”部分。

适用场景

使用Spring MVC或Spring Boot框架搭建的web应用

解决办法

@ControllerAdvice注解 + @ExceptionHandler注解

实现一个异常处理类,在类上应用@ControllerAdvice注解,并在异常处理方法上应用@ExceptionHandler注解。那么在web应用中,当Controller的@RequestMapping方法抛出指定的异常类型时,@ExceptionHandler修饰的异常处理方法就会执行。

示例:

 @ControllerAdvice
 public class WebServerExceptionHandler {
     Logger log = LoggerFactory.getLogger(this.getClass());

     public WebServerExceptionHandler() {
     }

     // 指定捕获的异常类型,这里是自定义的SomeException
     @ExceptionHandler({SomeException.class})
     public ResponseEntity<WebServerExceptionResponse> handle(HttpServletResponse response, SomeException ex) {
         WebServerExceptionResponse body = new WebServerExceptionResponse();
         body.setStatus(ex.getStatus());
         body.setMessage(ex.getMessage());
         this.log.info("handle SomeException, status:{}, message:{}",  new Object[]{body.getStatus(), body.getMessage()});
         return new ResponseEntity(body, HttpStatus.valueOf(ex.getStatus()));
     }

     // 指定捕获的异常类型,这里是自定义的OtherException
     @ExceptionHandler({OtherException.class})
     public ResponseEntity<WebServerExceptionResponse> handle(HttpServletResponse response, OtherException ex) {
         WebServerExceptionResponse body = new WebServerExceptionResponse();
         body.setStatus(ex.getStatus());
         body.setMessage(ex.getMessage());
         this.log.info("handle OtherException, status:{}, message:{}",  new Object[]{body.getStatus(), body.getMessage()});
         return new ResponseEntity(body, HttpStatus.valueOf(ex.getStatus()));
     }
 }

深入剖析

@ControllerAdvice的定义如下:

 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Component
 public @interface ControllerAdvice {

     String[] value() default {};

     String[] basePackages() default {};

     Class<?>[] basePackageClasses() default {};

     Class<?>[] assignableTypes() default {};

     Class<? extends Annotation>[] annotations() default {};

 }

可以看出它应用在TYPE类型的元素上(也即class或interface),运行时生效。

作用是Controller类的帮助注解,一般搭配@ExceptionHandler注解,用来处理Controller的@RequestMapping修饰的方法抛出的异常。

楼主根据源码的注释整理了5个参数的含义,它们都是用来限定需要处理的Controller的:

  • value():等同于basePackages,表示需要被处理的Controller包名数组,例如 @ControllerAdvice("org.my.pkg")。如果不指定,就代表处理所有的Controller类
  • basePackages():表示需要被处理的Controller包名数组,例如 @ControllerAdvice(basePackages={"org.my.pkg","org.my.other.pkg"})
  • basePackageClasses():通过标记类来指定Controller包名数组
  • assignableTypes():通过类的Class对象来指定Controller包名数组
  • annotations():被注解修饰的Controller需要被处理

性能考虑:不要指定过多的参数和异常处理策略,因为异常检查和处理都是在运行时做的。

@ExceptionHandler的定义如下:

 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface ExceptionHandler {

     /**
      * Exceptions handled by the annotated method. If empty, will default to any
      * exceptions listed in the method argument list.
      */
     Class<? extends Throwable>[] value() default {};

 }

可以看出它作用在方法上面,而且参数很好理解,就是需要处理的异常类的Class对象数组。

但是,它对修饰的异常处理方法的参数和返回值有限定,楼主根据源码的注释整理如下:

(1)异常处理方法的参数限定,可以是以下类型,顺序任意:

  • 异常类对象
  • HttpServletRequest、HttpServletResponse
  • HttpSession
  • InputStream/Reader、OutputStream/Writer

(2)异常处理方法的返回值限定,最终会写入response流:

  • ResponseEntity
  • HttpServletResponse
  • ModelAndView
  • Model
  • Map
  • View 

总结

以上就是在Spring web应用中的异常处理方法:使用@ControllerAdvice搭配@ExceptionHandler修饰自定义异常处理方法,处理来自Controller类中的@RequestMapping方法抛出的异常。

使用时需要根据实际情况,合理设置@ControllerAdvice和@ExceptionHandler的参数。

web应用中的异常处理的更多相关文章

  1. ASP.NET Web API 中的异常处理(转载)

    转载地址:ASP.NET Web API 中的异常处理

  2. 【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理

    原文:[ASP.NET Web API教程]4.3 ASP.NET Web API中的异常处理 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...

  3. 2017.10.28 针对Java Web应用中错误异常处理方法的运用

    针对Java Web应用中错误异常处理方法的运用 在javaweb中其异常都需要对Checked Exception之下的Exception进行继承,并且有选择地对发生的错误和异常进行处理.Java同 ...

  4. 【Web】Web开发中的异常处理方案

    我认为最合理的做法: 1.dao层不捕获异常.不抛出异常:spring框架将底层的数据库checked异常封装成unchecked异常了 2.service层捕获异常,并抛出自定义unchecked异 ...

  5. (五)web服务中的异常处理

    一.服务端发布服务 package com.webservice; import javax.jws.WebParam; import javax.jws.WebResult; import java ...

  6. Java web的几种异常处理 (转)

    一.在servlet容器中处理异常 以下两种方式: 1. 在web.xml定义异常处理  如果没有在web的应用中作异常处理,那么异常就会抛给Servlet容器,应该说此时Servlet容器是处理异常 ...

  7. 转:Spring Boot应用中的异常处理

    引自:https://www.cnblogs.com/yangfanexp/p/7616570.html 楼主前几天写了一篇“Java子线程中的异常处理(通用)”文章,介绍了在多线程环境下3种通用的异 ...

  8. 编写高质量代码改善java程序的151个建议——[110-117]异常及Web项目中异常处理

    原创地址:http://www.cnblogs.com/Alandre/(泥沙砖瓦浆木匠),需要转载的,保留下! 文章宗旨:Talk is cheap show me the code. 大成若缺,其 ...

  9. WEB 项目中的全局异常处理

    在web 项目中,遇到异常一般有两种处理方式:try.....catch....:throw 通常情况下我们用try.....catch.... 对异常进行捕捉处理,可是在实际项目中随时的进行异常捕捉 ...

随机推荐

  1. python之VSCode安装

    [之前发布到本人的51cto博客,现转过来] 1.安装python3.5(3.6版本亲测无法实现命令补全功能) 2.安装VSCode(我的版本:VSCode-win32-1.7.2) 3.安装Pyth ...

  2. django富文本编辑器

    -------------------tinymce富文本编辑器1.下载安装 1.在网站pypi网站搜索并下载"django-tinymce-2.4.0" 2.解压:tar zxv ...

  3. C-C++到底支不支持VLA以及两种语言中const的区别

    C-C++到底支不支持VLA以及两种语言中const的区别 到底支不支持VLA VLA就是variable-length array,也就是变长数组. 最近写程序的时候无意间发现,gcc中竟然支持下面 ...

  4. 移动端适配方案以及rem和px之间的转换

    背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...

  5. 深度剖析Java变量栈&对象堆

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  6. CCIE-MPLS基础篇-实验手册

    又一部前期JUSTECH(南京捷式泰)工程师职业发展系列丛书完整拷贝. MPLS(Multi-Protocol Label Switching) 目录 1:MPLS 基础实验.... 1.1实验拓扑. ...

  7. JavaScript 的使用基础总结②DOM

    HTML DOM 通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素. 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model). HT ...

  8. 团队作业6——展示博客(Alpha)

    一.团队简介 李永豪(PM):项目经理,后台开发人员,协调团队内部的工作及开发团队之间的工作 杨海亮:后台开发人员,测试人员,熟悉java语言,编写java代码 郑靖涛:后台开发人员,测试人员,安卓程 ...

  9. 201521123063 java第一周总结

    20152112306 <Java程序设计>第一周学习总结 1.本周学习总结(2.20-2.26) java语言的特点: (1)简约且简单 (2)平台无关性 (3)面向对象 (4)多线程. ...

  10. Java课程设计—学生成绩管理系统(201521123005 杨雪莹)

    一.团队课程设计博客链接 学生成绩管理系统 二.个人负责模块或任务说明 学生成绩录入 显示所有学生信息 显示各科平均成绩 显示学生成绩(按降序排序) 三.自己的代码提交记录截图 四.自己负责模块或任务 ...