SpringMVC_异常处理HandlerExceptionResolver(笔记)

  1. 异常处理概述

  1. Spring MVC 通过 HandlerExceptionResolver  处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。
  2. SpringMVC 提供的 HandlerExceptionResolver 的实现类

  1. HandlerExceptionResolver

DispatcherServlet  默认装配的 HandlerExceptionResolver

  • 没有使用 <mvc:annotation-driven/> 配置:

  • 使用了 <mvc:annotation-driven/> 配置

  1. 实验代码
  • 页面链接

<a href="testExceptionHandlerExceptionResolver?i=1">testExceptionHandlerExceptionResolver</a>

  • 控制器方法

package com.atguigu.springmvc.crud.handlers;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

 

@Controller

public class ExceptionHandler {

@RequestMapping("/testExceptionHandlerExceptionResolver")

public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i){

System.out.println("10/"+i+"="+(10/i));

return "success";

}

}

  • 测试,出现异常情况

处理异常,跳转到error.jsp

  • 在控制器中增加处理异常的方法

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public String handleException(Exception ex){

System.out.println("出现异常啦L"+ex);

return "error";

}

  • 增加error.jsp

<h3>Error Page</h3>

  1. 如何将异常对象从控制器携带给页面,做异常信息的获取

  • 异常对象不能通过Map集合方式传递给成功页面。(Map不可以

// @ExceptionHandler(value={java.lang.ArithmeticException.class})

public String handleException(Exception ex,Map<String,Object> map){

System.out.println("出现异常啦:"+ex);

map.put("exception",ex);

return "error";

}

  • 可以通过ModelAndView将异常对象传递给成功页面上

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public ModelAndView handleException(Exception ex){

System.out.println("出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

return mv;

}

  1. 匹配异常类型,执行顺序问题

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public ModelAndView handleException(Exception ex){

System.out.println("出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

return mv;

}

 

@ExceptionHandler(value={java.lang.RuntimeException.class})

public ModelAndView handleException2(Exception ex){

System.out.println("RuntimeException-出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

return mv;

}

  1. 公共的处理异常的类@ControllerAdvice

  • 定义公共的处理异常的类

package com.atguigu.springmvc.exceptionAdvice;

 

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.servlet.ModelAndView;

 

@ControllerAdvice

public class ExceptionAdviceHandler {

 

/*        

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public ModelAndView handleException(Exception ex){

 

System.out.println("出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

 

return mv; 

}*/

 

@ExceptionHandler(value={java.lang.RuntimeException.class})

public ModelAndView handleException2(Exception ex){

 

System.out.println("RuntimeException-出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

 

return mv;

}

}

  1. ExceptionHandlerExceptionResolver

  • 主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
  • @ExceptionHandler 注解定义的方法优先级问题:例如发生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
  • ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法
  1. 异常处理_ResponseStatusExceptionResolver

  • 在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
  • 定义一个 @ResponseStatus 注解修饰的异常类
  • 若在处理器方法中抛出了上述异常:若ExceptionHandlerExceptionResolver 不解析上述异常。由于触发的异常 UnauthorizedException 带有@ResponseStatus 注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。 关于其他的响应码请参考 HttpStatus 枚举类型源码。

org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver

Implementation of the HandlerExceptionResolver interface that uses the @ResponseStatus annotation to map exceptions to HTTP status codes.

This exception resolver is enabled by default in the

 org.springframework.web.servlet.DispatcherServlet.

  1. 实验代码

  • 页面链接

<a href="testResponseStatusExceptionResolver?i=10">testResponseStatusExceptionResolver</a>

  • 自定义异常类

package com.atguigu.springmvc.exception;

 

import org.springframework.http.HttpStatus;

import org.springframework.web.bind.annotation.ResponseStatus;

 

/**

 * 自定义异常类

HttpStatus.FORBIDDEN 不允许的,禁用的

 */

@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名称和密码不匹配")

public class UsernameNotMatchPasswordException extends RuntimeException{}

  • 控制器方法

@RequestMapping(value="/testResponseStatusExceptionResolver")

public String testResponseStatusExceptionResolver(@RequestParam("i") int i){

if(i==13){

throw new UsernameNotMatchPasswordException();

}

System.out.println("testResponseStatusExceptionResolver...");

return "success";

}

  • 出现的错误消息
  • 没使用注解时:@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名称和密码不匹配")

  • 使用注解时:@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名称和密码不匹配")

  1. 测试在方法上使用注解

@ResponseStatus(value=HttpStatus.NOT_FOUND,reason="测试方法上设置响应状态码")

@RequestMapping(value="/testResponseStatusExceptionResolver")

public String testResponseStatusExceptionResolver(@RequestParam("i") int i){

if(i==13){

throw new UsernameNotMatchPasswordException();

}

System.out.println("testResponseStatusExceptionResolver...");

return "success";

}

  • ResponseStatus

package org.springframework.web.bind.annotation;

 

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

import org.springframework.http.HttpStatus;

 

/**

 * Marks a method or exception class with the status code and reason that should be returned. The status code is applied

 * to the HTTP response when the handler method is invoked, or whenever said exception is thrown.

 *

 * @author Arjen Poutsma

 * @see org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver

 * @since 3.0

 */

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface ResponseStatus {

 

HttpStatus value();

 

String reason() default "";

 

}

  • HttpStatus
  1. 异常处理_DefaultHandlerExceptionResolver

  • 对一些特殊的异常进行处理,比如:
    • NoSuchRequestHandlingMethodException、
    • HttpRequestMethodNotSupportedException
    • HttpMediaTypeNotSupportedException、
    • HttpMediaTypeNotAcceptableException等。
  • javadoc

org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

Default implementation of the HandlerExceptionResolver interface that resolves standard Spring exceptions and translates them to corresponding HTTP status codes.

This exception resolver is enabled by default in the org.springframework.web.servlet.DispatcherServlet.

  • 实验代码

  • 增加页面链接:GET请求

<a href="testDefaultHandlerExceptionResolver">testDefaultHandlerExceptionResolver</a>

增加处理器方法

//@RequestMapping(value="/testDefaultHandlerExceptionResolver")

@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST)  //不支持GET请求

public String testDefaultHandlerExceptionResolver(){

System.out.println("testDefaultHandlerExceptionResolver...");

return "success";

}

  • 出现异常错误

  • 出现异常交给DefaultHandlerExceptionResolver处理

@Override

protected ModelAndView doResolveException(

HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

 

try {

if (ex instanceof NoSuchRequestHandlingMethodException) {

return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) ex, request, response,

handler);

}

else if (ex instanceof HttpRequestMethodNotSupportedException) {

return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, request,

response, handler);

}

else if (ex instanceof HttpMediaTypeNotSupportedException) {

return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, request, response,

handler);

}

else if (ex instanceof HttpMediaTypeNotAcceptableException) {

return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, request, response,

handler);

}

else if (ex instanceof MissingServletRequestParameterException) {

return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, request,

response, handler);

}

else if (ex instanceof ServletRequestBindingException) {

return handleServletRequestBindingException((ServletRequestBindingException) ex, request, response,

handler);

}

else if (ex instanceof ConversionNotSupportedException) {

return handleConversionNotSupported((ConversionNotSupportedException) ex, request, response, handler);

}

else if (ex instanceof TypeMismatchException) {

return handleTypeMismatch((TypeMismatchException) ex, request, response, handler);

}

else if (ex instanceof HttpMessageNotReadableException) {

return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, request, response, handler);

}

else if (ex instanceof HttpMessageNotWritableException) {

return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);

}

else if (ex instanceof MethodArgumentNotValidException) {

return handleMethodArgumentNotValidException((MethodArgumentNotValidException) ex, request, response, handler);

}

else if (ex instanceof MissingServletRequestPartException) {

return handleMissingServletRequestPartException((MissingServletRequestPartException) ex, request, response, handler);

}

else if (ex instanceof BindException) {

return handleBindException((BindException) ex, request, response, handler);

}

else if (ex instanceof NoHandlerFoundException) {

return handleNoHandlerFoundException((NoHandlerFoundException) ex, request, response, handler);

}

}

catch (Exception handlerException) {

logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);

}

return null;

}

  1. 异常处理_SimpleMappingExceptionResolver

  1. 如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常

  1. 实验代码
  • 增加页面链接

<a href="testSimpleMappingExceptionResolver?i=1">testSimpleMappingExceptionResolver</a>

  • 增加控制器方法

@RequestMapping("/testSimpleMappingExceptionResolver")

public String testSimpleMappingExceptionResolver(@RequestParam("i") int i){

System.out.println("testSimpleMappingExceptionResolver..."); 

String[] s = new String[10]; 

System.out.println(s[i]); 

return "success";

}

  • 出现异常情况:参数i的值大于10

  • 配置异常解析器:自动将异常对象信息,存放到request范围内

<!-- 配置SimpleMappingExceptionResolver异常解析器 -->

<bean id="simpleMappingExceptionResolver"

 class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

<!-- exceptionAttribute默认值(通过ModelAndView传递给页面):

exception   ->  ${requestScope.exception}

public static final String DEFAULT_EXCEPTION_ATTRIBUTE = "exception";

-->

<property name="exceptionAttribute" value="exception"></property>

<property name="exceptionMappings">

<props>

<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>

</props>

</property>

</bean>

error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

 "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body> 

<h3>Error Page</h3> 

${exception }

${requestScope.exception } 

</body>

</html>

  • 源码分析

SimpleMappingExceptionResolver    L187 L339 

@Override

protected ModelAndView doResolveException(HttpServletRequest request,

 HttpServletResponse response,Object handler, Exception ex) {

 

// Expose ModelAndView for chosen error view.

String viewName = determineViewName(ex, request);

if (viewName != null) {

// Apply HTTP status code for error views, if specified.

// Only apply it if we're processing a top-level request.

Integer statusCode = determineStatusCode(request, viewName);

if (statusCode != null) {

applyStatusCodeIfPossible(request, response, statusCode);

}

return getModelAndView(viewName, ex, request);

}else {

return null;

}

}

/**

 * Return a ModelAndView for the given view name and exception.

 * <p>The default implementation adds the specified exception attribute.

 * Can be overridden in subclasses.

 * @param viewName the name of the error view

 * @param ex the exception that got thrown during handler execution

 * @return the ModelAndView instance

 * @see #setExceptionAttribute

 */

protected ModelAndView getModelAndView(String viewName, Exception ex) {

ModelAndView mv = new ModelAndView(viewName);

if (this.exceptionAttribute != null) {

if (logger.isDebugEnabled()) {

logger.debug("Exposing Exception as model attribute '" + this.exceptionAttribute + "'");

}

mv.addObject(this.exceptionAttribute, ex);

}

return mv;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring MVC中,可以通过实现HandlerExceptionResolver接口来进行自定义异常处理。这个接口定义了一个resolveException()方法,当请求处理过程中出现异常时会被调用。通过实现这个方法,我们可以自定义异常处理的逻辑。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springmvc的自定义异常处理](https://blog.csdn.net/Sunking_Yin/article/details/52744151)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [SpringMVC自定义异常处理](https://blog.csdn.net/A_jungle/article/details/82386793)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [ssm_异常处理](https://download.csdn.net/download/csdn_kenneth/10251825)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值