SpringMVC——异常处理

本文介绍了SpringMVC中四种异常处理方式:使用内置异常处理器、自定义异常处理器、使用@ExceptionHandler注解以及使用@ControllerAdvice注解。每种方式都详细讲解了实现步骤及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 SpringMVC为我们提供了异常的统一处理机制,有以下四种方式。需要注意的是如果我们想使用统一的异常处理机制,那么就不要将需要统一处理的异常进行try…catch…处理,而是统一的交给异常处理器处理。

一、利用SpringMVC为我们提供的异常处理器
 SpringMVC中定义了一个HandlerExceptionResolver接口,用来统一处理异常。

public interface HandlerExceptionResolver {
	ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex);
}

 SpringMVC为我们提供了HandlerExceptionResolver接口的几个实现类,我们可以直接利用这些实现类进行异常的统一处理。
在这里插入图片描述
 下面以SimpleMappingExceptionResolver为例,说一下这种方式下异常的统一处理:
  ①自定义异常:

public class MyException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	public MyException(String message) {
		super(message);
	}
}

  ②在SpringMVC的容器配置文件中配置异常处理器:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<!-- 默认的异常展示页面:当抛出的异常不是exceptionMappings中特别指定的异常类型时返回该页面 -->
	<property name="defaultErrorView" value="error"></property>
	<!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
	<property name="exceptionAttribute" value="ex"></property>
	<!-- 需要特殊处理的异常列表:key为异常的类名或完全路径名,值为抛出该异常时的展示页面 -->
	<property name="exceptionMappings">
		<props>
			<!-- 这里配置的是自定义的异常 -->
			<prop key="com.bdm.exceptions.MyException">error1</prop>
			<prop key="com.bdm.exceptions.MyException1">error2</prop>
		</props>
	</property>
</bean>

  Tip
   1️⃣异常处理页面的位置须在配置的视图解析器的前缀目录下
   2️⃣在页面获取异常信息时使用的变量和exceptionAttribute属性的值要一致,比如在error1.jsp中获取异常信息

<span style="color: red">${ex.message}</span>

二、自定义HandlerExceptionResolver接口的实现
 除了直接使用SpringMVC为我们提供的异常处理器,我们也可以自定义异常处理器。自定义异常处理器的方式,能够是我们设置和获取到更丰富的异常信息,步骤如下:
 ①自定义异常处理器类:实现HandlerExceptionResolver接口

public class MyExceptionHandler implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {

		Map<String, Object> model = new HashMap<String, Object>();
		// 定义页面获取异常信息的变量
		model.put("ex", ex);
		// 这里我们可以放置更多的异常信息

		// 根据不同异常转向不同页面
		if (ex instanceof MyException) {
			return new ModelAndView("error1", model);
		} else if (ex instanceof MyException1) {
			return new ModelAndView("error2", model);
		} else {
			return new ModelAndView("error", model);
		}
	}
}

 ②在SpringMVC的容器中配置自定义的异常处理器

<bean class="com.bdm.handlers.MyExceptionHandler" />

 ③在Controller中只要抛出了相应的异常,就会按照对应的异常处理方式进行处理

三、在Controller中使用@ExceptionHandler
 我们可以在每个Controller类中增加一个或多个使用@ExceptionHandler注解的方法,当然也可以抽取一个公共父类,将该处理方法在父类中定义:

@RestController
public class TestController {

	@RequestMapping("/testException/{id}")
	public String testException(@PathVariable Integer id) {
		if (id == 1)
			throw new MyException(">>>>exception");
		return "success";
	}

	@ExceptionHandler
	public String exp(HttpServletRequest request, Exception ex) {

		request.setAttribute("ex", ex);
		request.setAttribute("msg", "yichang");

		// 根据不同错误转向不同页面
		if (ex instanceof MyException) {
			return "error1";
		} else if (ex instanceof MyException1) {
			return "error2";
		} else {
			return "error";
		}
	}
}

Tip
  1️⃣@ExceptionHandler注解的方法的优先级高于自定义的HandlerExceptionResolver,该Controller中出现的异常如果在@ExceptionHandler注解的方法中得到了处理就不会再被HandlerExceptionResolver的子类拦截了
  2️⃣@ExceptionHandler注解的方法的返回值和该类的定义有关,比如此处类上标注了@RestController,则方法的返回值将是对象本身而不再是页面的地址了
  3️⃣这种方式的异常处理的局限性在于只能处理该Controller中抛出的异常,而不能全局处理,当然也可以抽取一个公共父类来定义@ExceptionHandler注解的方法
  4️⃣在@ExceptionHandler中可以指定处理的异常

@ExceptionHandler(RuntimeException.class)
public String exp(HttpServletRequest request, Exception ex) {

	request.setAttribute("ex", ex);
	request.setAttribute("msg", "yichang");

	// 根据不同错误转向不同页面
	if (ex instanceof MyException) {
		return "error1";
	} else if (ex instanceof MyException1) {
		return "error2";
	} else {
		return "error";
	}
}

四、使用@ControllerAdvice
 上面介绍的@ExceptionHandler的方式只能处理当前Controller中抛出的异常,SpringMVC还为我们提供了@ControllerAdvice,可以监控指定包下的Controller中抛出的异常,步骤如下:
 ①定义相关切面:指定切面作用的包

@ControllerAdvice(basePackages = "com.bdm.controllers")
public class MyControllerAdvice {

	@ExceptionHandler(MyException.class)
	public ModelAndView myExceptionHandler(MyException ex) {
		ex.printStackTrace();
		Map<String, Object> map = new HashMap<>();
		map.put("ex", ex);
		return new ModelAndView("error1", map);
	}
}

 ②在SpringMVC的容器中注册切面类

<bean class="com.bdm.handlers.MyControllerAdvice" />

 ③在Controller中抛出相应的异常:会被切面方法拦截处理

@RestController
public class TestController {

	@RequestMapping("/testException/{id}")
	public String testException(@PathVariable Integer id) {
		if (id == 1)
			throw new MyException(">>>>exception");
		return "success";
	}
}

Tip
  1️⃣@ControllerAdvice切面类的处理优先级低于HandlerExceptionResolver的实现类
  2️⃣@ControllerAdvice标注的方法并不是只能进行异常处理,它其实可以监控所有Controller中的所有方法,具体可参考Spring MVC之@ControllerAdvice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值