@ControllerAdvice全局异常拦截
@ControllerAdvice 拦截异常并统一处理
在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。参考:@ControllerAdvice 文档
一、介绍
创建 MyControllerAdvice,并添加 @ControllerAdvice注解。
package com.sam.demo.controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
 * controller 增强器
 * @author sam
 * @since 2017/7/17
 */
@ControllerAdvice
public class MyControllerAdvice {
    /**
     * 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {}
    /**
     * 把值绑定到Model中,使全局@RequestMapping可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("author", "Magical Sam");
    }
    /**
     * 全局异常捕捉处理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception ex) {
        Map map = new HashMap();
        map.put("code", 100);
        map.put("msg", ex.getMessage());
        return map;
    }
}
启动应用后,被 @ExceptionHandler、@InitBinder、@ModelAttribute 注解的方法,都会作用在 被 @RequestMapping 注解的方法上。
@ModelAttribute:在Model上设置的值,对于所有被 @RequestMapping 注解的方法中,都可以通过 ModelMap 获取,如下:
@RequestMapping("/home")
public String home(ModelMap modelMap) {
    System.out.println(modelMap.get("author"));
}
//或者 通过@ModelAttribute获取
@RequestMapping("/home")
public String home(@ModelAttribute("author") String author) {
    System.out.println(author);
}@ExceptionHandler 拦截了异常,我们可以通过该注解实现自定义异常处理。其中,@ExceptionHandler 配置的 value 指定需要拦截的异常类型,上面拦截了 Exception.class 这种异常。
二、自定义异常处理(全局异常处理)
spring boot 默认情况下会映射到 /error 进行异常处理,但是提示并不十分友好,下面自定义异常处理,提供友好展示。
1、编写自定义异常类:
package com.sam.demo.custom;
/**
 * @author sam
 * @since 2017/7/17
 */
public class MyException extends RuntimeException {
    public MyException(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private String code;
    private String msg;
    // getter & setter
}
注:spring 对于 RuntimeException 异常才会进行事务回滚。
2、编写全局异常处理类
创建 MyControllerAdvice.java,如下:
package com.sam.demo.controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
 * controller 增强器
 *
 * @author sam
 * @since 2017/7/17
 */
@ControllerAdvice
public class MyControllerAdvice {
    /**
     * 全局异常捕捉处理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception ex) {
        Map map = new HashMap();
        map.put("code", 100);
        map.put("msg", ex.getMessage());
        return map;
    }
    /**
     * 拦截捕捉自定义异常 MyException.class
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MyException.class)
    public Map myErrorHandler(MyException ex) {
        Map map = new HashMap();
        map.put("code", ex.getCode());
        map.put("msg", ex.getMsg());
        return map;
    }
}
3、controller中抛出异常进行测试。
@RequestMapping("/home")
public String home() throws Exception {
//        throw new Exception("Sam 错误");
    throw new MyException("101", "Sam 错误");
}启动应用,访问:http://localhost:8080/home ,正常显示以下json内容,证明自定义异常已经成功被拦截。
{"msg":"Sam 错误","code":"101"}* 如果不需要返回json数据,而要渲染某个页面模板返回给浏览器,那么MyControllerAdvice中可以这么实现:
@ExceptionHandler(value = MyException.class)
public ModelAndView myErrorHandler(MyException ex) {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("error");
    modelAndView.addObject("code", ex.getCode());
    modelAndView.addObject("msg", ex.getMsg());
    return modelAndView;
}在 templates 目录下,添加 error.ftl(这里使用freemarker) 进行渲染:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>错误页面</title>
</head>
<body>
    <h1>${code}</h1>
    <h1>${msg}</h1>
</body>
</html>重启应用,http://localhost:8080/home 显示自定的错误页面内容。
补充:如果全部异常处理返回json,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,这样在方法上就可以不需要添加 @ResponseBody。
@ControllerAdvice全局异常拦截的更多相关文章
- Spring 全局异常拦截根据业务返回不同格式数据 自定义异常
		1.全局异常拦截:针对所有异常进行拦截 可根据请求自定义返回格式 2.自定义异常类 处理不同业务的异常 接下来开始入手代码: 1).自定义异常类 @ControllerAdvice//添加注解 记得开 ... 
- SpringBoot全局异常拦截
		SpringBoot全局异常捕获 使用到的技能 @RestControllerAdvice或(@ControllerAdvice+@ResponseBody) @ExceptionHandler 代码 ... 
- SpringBoot 全局异常拦截捕获处理
		一.全局异常处理 //Result定义全局数据返回对象 package com.xiaobing.demo001.domain; public class Result { private Integ ... 
- Asp.Netcore使用Filter来实现接口的全局异常拦截,以及前置拦截和后置拦截
		原文链接:https://blog.csdn.net/qq_38762313/article/details/85234594 全局异常拦截器: 解决写每个接口都需要去做容错而添加try{ ... 
- springboot全局异常拦截源码解读
		在springboot中我们可以通过注解@ControllerAdvice来声明一个异常拦截类,通过@ExceptionHandler获取拦截类抛出来的具体异常类,我们可以通过阅读源码并debug去解 ... 
- Spring  Cloud Gateway之全局异常拦截器
		/** * @version 2019/8/14 * @description: 异常拦截器 * @modified: */ @Slf4j public class JsonExceptionHand ... 
- Spring MVC中@ControllerAdvice注解实现全局异常拦截
		在网上很多都把Advice翻译成增强器,其实从翻译工具上看到,这个单词翻译是忠告,通知的意思. 首先这个注解实在Spring Web包下,而Spring MVC离不开Spring Web的依赖,所以经 ... 
- SpringCloud整合分布式事务Seata 1.4.1 支持微服务全局异常拦截
		项目依赖 SpringBoot 2.5.5 SpringCloud 2020.0.4 Alibaba Spring Cloud 2021.1 Mybatis Plus 3.4.0 Seata 1.4. ... 
- spring自定义controller全局异常拦截
		--异常类可以按需要自定义package com.dhht.wechat.exception; import com.alibaba.fastjson.JSONObject;import org.sp ... 
随机推荐
- 【WinHec启发录】透过Windows 10技术布局,谈微软王者归来
			每一个时代都有王者,王者的成功,往往是由于恰逢其时地公布了一个成功的产品(具有里程碑意义,划时代的产品).Windows 95的成功标示着微软是PC时代的王者:WinXP的成功标示着微软是互联网时代的 ... 
- IE7下兼容问题总结
			1.<LI> border-bottom 不显示 解决办法 加个height:100%; 2.border:none;不好使,要用 border:0; 
- 【codevs1306】广播操的游戏
			求字符串内的非空子串的数量 后缀数组!!! #include<algorithm> #include<cstdlib> #include<cstring> #inc ... 
- Open Source Computer Vision Library
			https://opencv.org/ OpenCV (Open Source Computer Vision Library) is released under a BSD license and ... 
- sql加一个%号是什么意思
			sql%notfound 是异常SQL%ROWCOUNT SQL语句执行影响的行数SQL%FOUND SQL语句是否成功执行SQL%NOTFOUND SQL语句是否成功执行SQL%ISOPEN 游标是 ... 
- Codeforces Round #369 (Div. 2) 套题
			A:模拟水题不说 #include <iostream> #include <string.h> #include <algorithm> #include < ... 
- 4.7.5 Efficient Construction of LALR Parsing Tables
			4.7.5 Efficient Construction of LALR Parsing Tables There are several modifications we can make to A ... 
- 关于Flask的默认session
			Flask的默认session利用了Werkzeug的SecureCookie,把信息做序列化(pickle)后编码(base64),放到cookie里了. 过期时间是通过cookie的过期时间实现的 ... 
- bzoj4031 [HEOI2015]小Z的房间——矩阵树定理
			题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4031 矩阵树定理的模板题(第一次的矩阵树定理~): 有点细节,放在注释里了. 代码如下: # ... 
- jquery autocomplete自动补全
			简单用法: $(function(){ var data = "the People's Republic of China".split(" "); $(&q ... 
