SpringMVC统一异常处理(返回异常数据而不是跳转到某个页面的方法)

Posted lhever_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC统一异常处理(返回异常数据而不是跳转到某个页面的方法)相关的知识,希望对你有一定的参考价值。

关于SpringMVC统一异常处理的问题,网搜一大把。网上搜的关于如何进行统一异常处理不外乎如下三种方式:

Spring MVC处理异常有3种方式:
(1) 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
(2) 实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;
(3) 使用@ExceptionHandler注解实现异常处理;

然而,大家都在介绍异常发生的时候如何跳转到一个特定的页面。如何在跳转到的页面呈现异常信息等等。

然而,上述处理方式对于我的需求并没有什么卵用。我想要的结果是在发生异常之后,不是调转到某个页面,而是将异常信息以数据的形式(比如json数据)返回。

不过本人不才,目前仅仅发现使用ExceptionHandler注解实现统一异常处理的方式,也是可以返回异常信息而不是跳转到某个页面呈现异常信息的。大家有新的发现不妨告诉我咯。统一异常处理的好处我就不说了,能够将异常信息统一捕捉并组装成固定格式的数据返回的好处,我想在ajax回调处理中好处可多了, 回调得到的数据因为格式统一,前端可以很方便的通过某种控件进行呈现或友好提示 。 虽然我们也可以手动在Controller层的方法返回的结果中添加异常信息,但是只会徒增代码量,却不能使我们更好的专注于业务逻辑。

解决办法如下:
1、增加BaseExceptionHandleAction类,并在类中同时使用@ExceptionHandler和@ResponseBody注解声明异常处理,代码如下:


import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.core.exception.BusinessException;
import com.core.util.JsonUtil;

public class BaseExceptionHandleAction 

    protected HttpServletRequest getServletRequest() 
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    

    protected ServletContext getServletContext() 
        HttpServletRequest request = getServletRequest();
        if (request != null) 
            return request.getSession().getServletContext();
        

        return null;
    

    protected HttpServletResponse getServletResponse() 
        return RequestResponseContext.getResponse();
    

    protected void writeResponse(ActionResult result) throws IOException 
        HttpServletResponse response = getServletResponse();
        response.setContentType("text/html; charset=utf-8");
        OutputStream stream = response.getOutputStream();
        stream.write(JsonUtil.toJson(result).getBytes("utf-8"));
        stream.flush();
        stream.close();
    

    /** 基于@ExceptionHandler异常处理 */
    /*@ExceptionHandler
    public ModelAndView  handleAndReturnPage(HttpServletRequest request, HttpServletResponse response, Exception ex) 

        ModelAndView  mv = new ModelAndView("Exception") ;
        mv.addObject("ex", ex);

        // 根据不同错误转向不同页面
        if (ex instanceof BusinessException) 
            return mv;
         else 
            return mv; //返回Exception.jsp页面
        
    */

    /** 基于@ExceptionHandler异常处理 */
    @ExceptionHandler
    @ResponseBody
    public Map<String, Object>  handleAndReturnData(HttpServletRequest request, HttpServletResponse response, Exception ex) 

        Map<String, Object> data = new HashMap<String, Object>();
        if(ex instanceof BusinessException) 
            BusinessException e = (BusinessException)ex;
            data.put("code", e.getCode());
        
        data.put("msg", ex.getMessage());
        data.put("excetion", ex.getClass().getSimpleName());
        return data;
    

2、修改代码,使所有需要异常处理的Controller都继承该类,如下所示,修改后的ExceptionTestController类继承于BaseExceptionHandleAction:


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.core.exception.BusinessException;
import com.core.springmvc.BaseExceptionHandleAction;

@Controller
public class ExceptionTestController extends BaseExceptionHandleAction 

    // http://localhost:8080/SSM/exceptionTest?id=10
    @RequestMapping(value = "/exceptionTest", method = RequestMethod.GET)
    public void controller(HttpServletRequest request, HttpServletResponse response, Integer id) 
        if (id == 10) 
            throw new BusinessException(10, "该异常代表用户信息不完整");

         else if (id == 20) 
            throw new BusinessException(20, "该异常代表用户信息泄露");

         else 
            throw new BusinessException(30, "该异常代表用户不存在");
        
    


3、本人的BusinessException类的代码如下


public class BusinessException extends RuntimeException 

    /**
     */
    private static final long serialVersionUID = -7638041501183925225L;

    private Integer code;

    public BusinessException(Integer code, String msg) 
        super(msg);
        this.code = code;
    

    public BusinessException(Integer code, String msg, Throwable cause) 
        super(msg, cause);
        code = code;
    

    public Integer getCode() 
        return code;
    

    public void setCode(Integer code) 
        this.code = code;
    






4、启动测试项目,本人项目名称为SSM,通过访问路径http://localhost:8080/SSM/exceptionTest?id=20,得到的结果如下:


“msg “:” 该异常代表用户信息泄露”,
“code” : 20,
“excetion” : “BusinessException”

5、至此,需求完美解决。只需要@ExceptionHandler和@ResponseBody两个注解同时使用即可完美解决需求。注意:我的BaseExceptionHandleAction类中还有一个注释了的方法,该方法仅仅使用了注解@ExceptionHandler,所以该注释了的方法可以在发生异常时候跳转到某个指定页面。但是注意,这两个方法不能同时存在,否则spring MVC不知道异常发生时该使用哪个方法来处理异常。

以上是关于SpringMVC统一异常处理(返回异常数据而不是跳转到某个页面的方法)的主要内容,如果未能解决你的问题,请参考以下文章

javaweb异常提示信息统一处理(使用springmvc,附源码)

springmvc请求参数异常处理

统一异常处理@ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

SpringMVC统一异常处理

SpringMVC学习07SpringMVC中的统一异常处理

springboot统一异常处理