ssm中自定义错误页面,对不同的错误进行拦截跳转

自定义ControllerExceptionHandler

package com.wh.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;

/**
 * @author wanghan
 * @description 处理异常的拦截类
 * @date 2021/1/22
 **/
@ControllerAdvice
public class ControllerExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * @description //错误异常处理
     * @param request : 出错的 URL
     *        e : 异常
     * @return ModelAndView
     * @date 2021/1/22
     * ExceptionHandler //标识异常的注解
     */
    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHandler(HttpServletRequest request, Exception e) throws Exception {
        logger.error("Request URL : {}, Exception : {}", request.getRequestURI(), e);
        ModelAndView mv = new ModelAndView();
        //放行加了状态码的异常
        if (e instanceof HttpRequestMethodNotSupportedException) {
            mv.addObject("url", request.getRequestURI());
            mv.addObject("exception", e);
            mv.setViewName("error/405");
            return mv;
        }

        if (e instanceof MissingServletRequestParameterException) {
            mv.addObject("url", request.getRequestURI());
            mv.addObject("exception", e);
            mv.setViewName("error/400");
            return mv;
        }

        if (e instanceof NoHandlerFoundException) {
            mv.addObject("url", request.getRequestURI());
            mv.addObject("exception", e);
            mv.setViewName("error/404");
            return mv;
        }


        mv.addObject("url", request.getRequestURI());
        mv.addObject("exception", e);
        mv.setViewName("error/500");
        return mv;
    }
}

springmvc.xml增加配置

<context:component-scan base-package="com.wh" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<mvc:annotation-driven />

说明,加入注解的扫描,避免自定义的ControllerExceptionHandler类未装配,从而不起作用

web.xml的配置

    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置DispatcherServlet的初始化參數:设置文件的路径和文件名称 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--默认的找不到是抛出的,这里修改下-->
        <init-param>
            <param-name>throwExceptionIfNoHandlerFound</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--加载的时候就创建-->
        <load-on-startup>1</load-on-startup>
    </servlet>

在DispatcherServlet源码中,找不到处理器时候的异常是不抛出的,因此需要设置为抛出,否则404的异常,无法被我们自定义的类给捕捉

	/** Throw a NoHandlerFoundException if no Handler was found to process this request? **/
	private boolean throwExceptionIfNoHandlerFound = false;

原因分析

在系统中出现异常后都会去交由ExceptionResolver异常处理器处理

@RequestMapping方法抛出异常后,Spring框架 try-catch的方法捕获异常,  正常逻辑发不发生异常都会走processDispatchResult流程 ,区别在于异常的参数是否为null 。

如果@RequestMapping方法抛出异常,拦截器的postHandle方法不执行,进入 processDispatchResult,判断入参 dispatchException,不为null , 代表发生异常,调用processHandlerException处理,

@Controller和@ControllerAdvice类可以具有 @ExceptionHandler处理控制器方法异常的方法

@ControllerAdvice

  • @ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。
  • Spring4之前,@ControllerAdvice在同一调度的Servlet中协助所有控制器。Spring4已经改变:@ControllerAdvice支持配置控制器的子集,而默认的行为仍然可以利用。
  • 在Spring4中, @ControllerAdvice通过annotations(), basePackageClasses(), basePackages()方法定制用于选择控制器子集。
@Controller
public class SimpleController {

    // ...

    @ExceptionHandler
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}

此方法优先级最高

@ControllerAdvice
public class GlobalExceptionHandler {

    // ...

    @ExceptionHandler
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}

优先级次之

 

@ExceptionHandler 方法支持以下参数:

方法参数描述

异常类型

用于访问引发的异常。

HandlerMethod

用于访问引发异常的控制器方法。

WebRequest, NativeWebRequest

对请求参数以及请求和会话属性的一般访问,而无需直接使用Servlet API。

javax.servlet.ServletRequest, javax.servlet.ServletResponse

选择任何特定的请求或响应类型(例如ServletRequest或 HttpServletRequest或Spring的MultipartRequestMultipartHttpServletRequest)。

javax.servlet.http.HttpSession

强制会话的存在。结果,这种论据永远不会null
请注意,会话访问不是线程安全的。考虑将RequestMappingHandlerAdapter实例的synchronizeOnSession标志设置 为true是否允许多个请求同时访问会话。

java.security.Principal

当前经过身份验证的用户-可能是特定的Principal实现类(如果已知)。

HttpMethod

请求的HTTP方法。

java.util.Locale

当前请求的语言环境,取决于最具体的LocaleResolver可用语言(实际上是配置的LocaleResolver或)LocaleContextResolver

java.util.TimeZone, java.time.ZoneId

与当前请求关联的时区,由决定LocaleContextResolver

java.io.OutputStream, java.io.Writer

用于访问原始响应主体,如Servlet API所公开。

java.util.Maporg.springframework.ui.Modelorg.springframework.ui.ModelMap

用于访问模型以进行错误响应。永远是空的。

RedirectAttributes

指定在重定向的情况下要使用的属性(将附加到查询字符串中)和flash属性,这些属性将临时存储直到重定向后的请求。

@SessionAttribute

与访问由于类级@SessionAttributes声明而存储在会话中的模型属性相反,用于访问任何会话属性。

@RequestAttribute

用于访问请求属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值