spring-boot的异常处理机制       掌握一些注解的使用

1.首先spring-boot后台遇到异常的时候,会被捕获,默认情况下跳转到全局的error页面。也就是src/main/resource/templates/error.html

当这个页面没有就会报错。

spring boot Scheduled抛出异常之后还会执行吗 springboot异常处理机制_spring-boot 异常处理

框架会将错误信息输出到显示层   key是exception

spring boot Scheduled抛出异常之后还会执行吗 springboot异常处理机制_异常处理_02

spring boot Scheduled抛出异常之后还会执行吗 springboot异常处理机制_异常处理_03


但是我们的项目可能有多种异常的处理,也就是有多种异常页面。

我们可以在控制器中添加异常处理的方法,添加@ExceptionHandler注解

package com.jiayun.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.jiayun.server.UserServerImpl;

@Controller
public class IndexController {
	
	@Autowired
	private UserServerImpl userServer;
	
	/**
	 * controller中异常1
	 * NullPointerException
	 */
	@SuppressWarnings("null")
	@RequestMapping("/index1")
	public String index1(){
		
		String str = null;
		str.length();
		return "index1";
	}
	
	/**
	 * controller中异常2
	 * ArithmeticException
	 */
	@SuppressWarnings("unused")
	@RequestMapping("/index2")
	public String index2(){
		
		int i = 5/0;
		return "index2";
	}
	
	/**
	 * controller中异常2
	 * ArrayIndexOutOfBoundsException
	 */
	@RequestMapping("/index3")
	public String index3(){
		
		// 添加代码让异常发生在当前类的调用类中  异常也可以捕获到,走错误页面
		// 但是异常在其他控制器中@ExceptionHandler就捕获不到
		userServer.getUserList();
		int[] i = {};
		System.out.println(i[1]);
		
		return "index3";
	}
	
	/**
	 * 处理index1和index2方法中的异常,可以同时捕获多个异常
	 * 该方法需要返回一个ModelAndView:目的是可以让我们封装异常信息以及视图的指定
	 * 参数Exception e:会将产生异常对象注入到方法中
	 */
	@ExceptionHandler(value={java.lang.NullPointerException.class,java.lang.ArithmeticException.class})
	public ModelAndView error1AndError2(Exception e){
		ModelAndView mv = new ModelAndView();
		mv.addObject("error", e.toString());// 前台exception中就没有值了
		if(e instanceof NullPointerException){
			// NullPointerException
			// some code
			mv.setViewName("errors/error1");
		}else {
			// ArithmeticException
			// some code
			mv.setViewName("errors/error2");
		}
		return mv;
	}
	
	/**
	 * 只捕获一个异常
	 * java.lang.ArrayIndexOutOfBoundsException
	 * 该方法需要返回一个ModelAndView:目的是可以让我们封装异常信息以及视图的指定
	 * 参数Exception e:会将产生异常对象注入到方法中
	 */
	@ExceptionHandler(value={java.lang.ArrayIndexOutOfBoundsException.class})
	public ModelAndView nullPointerExceptionHandler(Exception e){
		ModelAndView mv = new ModelAndView();
		mv.addObject("error", e.toString());
		mv.setViewName("errors/error3");
		return mv;
	}
	

}

当前类中的异常处理的方法可以捕获当前类或者调用的其他类的异常。但是其他情况的类中发生的异常就捕获不到。

那么我们如何解决方法注解@ExceptionHandler能够处理全局的异常而不是某一个类中的呢。

那就是把方法提到一个类中,类用@ControllerAdvice注解

/**
 * 
 * 全局异常处理
 *
 */
@ControllerAdvice // 该注解里面的方法可以捕获全局累的异常
public class Exceptions {

在全局异常处理类中被@ExceptionHandler注解的方法可以给前台页面赋值。以及做一些代码处理。

如果只需要根据不同的异常返回不同的静态页面,那么全局异常处理类中的方法就可以省略,把异常类和对应的返回页面写到配置文件中

/**
	 * 该方法返回值类型必须是:SimpleMappingExceptionResolver
	 */
	@Bean
	public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
		SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
		
		Properties mappings = new Properties();
		
		/**   
		 * 就不写配置文件了...
		 * 参数一:异常的类型,注意必须是异常类型的全名
		 * 参数二:视图名称
		 */
		mappings.put("java.lang.ArithmeticException", "error1");
		mappings.put("java.lang.NullPointerException","error2");
	
		resolver.setExceptionMappings(mappings);
		
		return resolver;
	}

最后一种比较高级一点的全局异常处理类的写法    实现HandlerExceptionResolver 接口

package com.jiayun.exception;

import java.util.Properties;

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

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

/**
 * 通过实现HandlerExceptionResolver接口做全局异常处理
 *
 */
@Configuration
public class GlobalException implements HandlerExceptionResolver {

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

		if(ex instanceof ArithmeticException){
			mv.setViewName("error1");
		}
		
		if(ex instanceof NullPointerException){
			mv.setViewName("error2");
		}
		mv.addObject("error", ex.toString());
		
		return mv;
	}
}