SpringBoot中使用@ControllerAdvice定义全局异常 - 支持web异常和ajax请求异常

SpringMVC的@ControllerAdvice有三种使用场景:

  1. 全局异常处理
  2. 全局数据绑定
  3. 全局数据预处理

本文介绍在springboot中直接使用@ControllerAdvice定义全局异常

注:页面使用thymeleaf模板引擎

项目目录结构如下:

在exceptions中定义异常类文件

  1. 使用@ControllerAdvice注解,代表为全局异常类,项目中任意方法发生异常均会执行此方法
  2. @ExceptionHandler定义具体的异常类型,若定义为NullPointerException空指针异常,则发生ArrayIndexOutOfBoundsException数据越界异常时,不会执行此方法
  3. @Controller + @ResponseBody 组合,则方法既可返回model页面,也可返回json格式等数据
  4. GlobalExceptionHandler方法中定义判断是否为ajax请求时发生的异常,若是,则以json格式返回异常信息;若不是,则返回异常报错页面
package com.test.springboot.exceptions;

import com.test.springboot.constant.ViewConstant;
import com.test.springboot.utils.ResResultJson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;


/**
 * 融合ajax请求和普通请求 返回异常的方式
 * ajax请求 返回页面异常数据
 * 普通请求,返回前端错误页面,错误页面上可展示异常数据
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object errHandler(HttpServletRequest request, Exception e) throws Exception {
        if (isAjax(request)) return ResResultJson.err(e.getMessage());
        else {
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("exception", e.getMessage()).addObject("url", request.getRequestURL()).setViewName(ViewConstant.ERROR_VIEW);
            return modelAndView;
        }
    }

    /**
     * 判断是否为ajax请求
     * @param request
     * @return
     */
    public static boolean isAjax(HttpServletRequest request) {
        return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString()));
    }
}

ResResultJson文件如下:

定义json返回的编码code,提示信息message,返回数据data

其中返回编码code可自主定义

package com.test.springboot.utils;

/**
 *自定义返回数据结构
 */
public class ResResultJson {

    private String code;
    private String message;
    private Object data;


    public ResResultJson(String code,String message,Object data){
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public ResResultJson(String code,String message){
        this.code = code;
        this.message = message;
    }

    public static ResResultJson err(String code,String message){
        return new ResResultJson(code,message);
    }

    public static ResResultJson err(String message){
        return new ResResultJson("500",message);
    }

    public static ResResultJson reqOk(String code,String message,Object data){
        return new ResResultJson(code,message,data);
    }

    public static ResResultJson reqOk(Object data){
        return new ResResultJson("200","成功",data);
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

异常页面error.html定义:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>全局异常捕获测试</title>
</head>
<body>
    <h1>系统出现异常:</h1>
    <div th:text = "${url}">异常地址</div>
    <div th:text = "${exception}">异常信息</div>
</body>
</html>

 

在java中 1/0 会出现java.lang.ArithmeticException: / by zero 异常,方法验证如下:

1. Web请求异常

启动项目,访问http://localhost:8081/springboot/err

方法中throw new异常,同样会走全局异常捕获,error.html中会展示抛出的异常信息

@RequestMapping("/err")
public void testException() throws BussinessException {
    int num = 1 / 0;
//  throw new BussinessException("发生异常了");
    System.out.println(num);
}

error.html页面展示如下:

2. Ajax请求异常

第一步:get请求返回html页面

@RequestMapping(value = "/getJsonValue",method = RequestMethod.GET)
public Object getJsonValue(Model model,HttpServletRequest request){
    JsonTest jsonTest = new JsonTest();
    jsonTest.setName("Test99");
    model.addAttribute(jsonTest);
    return ViewConstant.REQ_VIEW;
}

第二步:html页面中定义ajax请求

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>发起请求</title>
    <script th:src = "@{/js/jquery.min.js}"></script>
</head>
<body>
    <input th:name = "personName" th:id="personName" th:value="${jsonTest.getName()}">
    <button th:onclick="'javascript:reqAjax();'" th:type="button" th:text="提交"></button>
</body>

<script type="text/javascript" th:inline="javascript">
    /*<![CDATA[*/
    function reqAjax() {
        // var name="00";
        var name=$('#personName').val();
        $.ajax({
            //ajax请求不成功jquery.js报错,url要写为全量的url(包括yml配置文件中的servlet.context-path路径)
            url:'/springboot/ajaxErr',
            type:'POST',
            async:false,
            data:{name:name},
            success:function (data) {
                if(data.code == "200" && data.message == "成功"){
                    alert("请求成功,请求数据:"+data.data['sex']+","+data.data['name']);
                }else {
                    alert("请求失败,失败信息:"+data.message);
                }

            }
        });
    }
    /*]]>*/
</script>
</html>

第三步:ajax请求后台方法,方法中设置异常

@RequestMapping(value = "/ajaxErr",method = RequestMethod.POST)
@ResponseBody
public ResResultJson testAjaxException(HttpServletRequest request, HttpServletResponse response){
     String name = request.getParameter("name");
     System.out.println("name:"+name);
     Map map = new HashMap();
     if (name.isEmpty()) {
         int num = 1 / 0;
     }
     map.put("name",name);
     map.put("sex","男");
     return ResResultJson.reqOk(map);
}

第四步:页面验证

personName有值,即前端传值时,点击【提交】,ajax请求成功,返回成功信息

personName无值,即ajax中name传值空,点击【提交】,程序有异常,则走全局异常捕获,返回异常信息

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当我们在编写 Spring MVC 应用程序时,我们可以使用 @ControllerAdvice 注解或者在 Controller 使用 @ExceptionHandler 注解来处理异常。@ControllerAdvice 注解可以用于全局异常处理,而 @ExceptionHandler 注解则用于处理特定的异常。 下面是一个使用 @ControllerAdvice 注解处理异常的示例: ``` @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ModelAndView handleException(Exception e) { ModelAndView mav = new ModelAndView(); mav.addObject("exception", e); mav.setViewName("error"); return mav; } } ``` 在上面的示例,我们定义了一个名为 GlobalExceptionHandler 的类,并使用 @ControllerAdvice 注解将其标记为全局异常处理器。我们还使用 @ExceptionHandler 注解来处理 Exception 类型的异常。当应用程序出现 Exception 类型的异常时,Spring MVC 将会调用 handleException 方法来处理该异常,并返回一个包含异常信息的 ModelAndView 对象。 如果我们想要在 Controller 处理特定的异常,我们可以使用 @ExceptionHandler 注解。下面是一个使用 @ExceptionHandler 注解处理特定异常的示例: ``` @Controller public class UserController { @ExceptionHandler(UserNotFoundException.class) public ModelAndView handleUserNotFoundException(UserNotFoundException e) { ModelAndView mav = new ModelAndView(); mav.addObject("exception", e); mav.setViewName("userNotFound"); return mav; } @GetMapping("/users/{id}") public String getUser(@PathVariable Long id) { User user = userService.getUserById(id); if (user == null) { throw new UserNotFoundException("User not found with id " + id); } return "userDetails"; } } ``` 在上面的示例,我们定义了一个名为 UserController 的类,并使用 @Controller 注解将其标记为一个 Controller。我们还使用 @ExceptionHandler 注解来处理 UserNotFoundException 类型的异常。当应用程序出现 UserNotFoundException 类型的异常时,Spring MVC 将会调用 handleUserNotFoundException 方法来处理该异常,并返回一个包含异常信息的 ModelAndView 对象。 另外,我们还定义了一个名为 getUser 的方法来获取用户信息。如果用户不存在,我们将会抛出一个 UserNotFoundException 异常,该异常将会被 handleUserNotFoundException 方法处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值