SpringBoot中如何做全局统一异常处理

注解解读:

@ControllerAdvice:它定义在一个类上,和@Component类似,它使得@ExceptionHandler、@InitBindler、@ModelAttribute注解可以作用在所有@RequestMapping注解上。

@ExceptionHandler:它定义在Controller的方法上,作用是捕获指定的异常,然后进行统一处理并返回最后的结果。

理解了@ControllerAdvice和@ExceptionHandler注解,就可以用它们做全局统一捕获异常了(注意:这里说的全局是指的Controler层)。首先编写全局异常处理类,这里我分两种返回值类型,一种是Json字符串(直接输出到页面),一种是ModelAndView(可以使用前端模版引擎freemarker或者thymeleaf进行渲染)

返回JSON字符串

@ControllerAdvice
public class CommonExceptionHandler {

	@ExceptionHandler(Exception.class)
	@ResponseBody
	public Map<String, Object> exceptionHandler(HttpServletRequest req,HttpServletResponse resp,Exception e){
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("respmsg", e.getStackTrace());
		map.put("url", req.getRequestURL());
		map.put("status", false);
		return map;
	}

}

使用@ResponseBody注解将以JSON字符串形式返回

@ExceptionHandler可以指定多个Exception类,没有指定的异常类不会捕获。

使用@RestontrollerAdvice也能实现上面的效果,它相当于@ResponseBody+@ControllerAdvice

接着,我们开始编写Controller类,这里为了方便直接抛出一个Exception异常

@Controller
@RequestMapping("/exception")
@Api(tags="异常处理")
public class ExceptionController {
	
	@RequestMapping("test1")
	public String test1() throws Exception{
		{
			throw new Exception("出错了");
		}
	}

}

此时,我们访问http://localhost:8881/exception/test1,页面上将会打印我们在全局处理类中保存的信息。

我们也可以使用Swagger2进行测试,有兴趣的同学可以自行百度springboot中继承swagger2做接口测试,以后会写一篇相关的博客

也可以使用postman,postman有客户端程序,也可以在页面进行测试,我这里用的是客户端程序测试的

返回ModelAndView

首先编写一个返回modelandview的全局处理类

@ControllerAdvice
public class BaseExceptionHandler {

	@ExceptionHandler(NumberFormatException.class)
	public ModelAndView defaulterror(HttpServletRequest req,HttpServletResponse resp,Exception e){
		ModelAndView view = new ModelAndView();
		view.addObject("msg", "格式化异常");
		view.addObject("status", false);
		view.addObject("stack",e.getStackTrace());
		view.setViewName("error");
		return view;
	}
	
}

Controller类:

@Controller
@RequestMapping("/exception")
@Api(tags="异常处理")
public class ExceptionController {
	
	@Autowired
	IFeUserService userService;
	
	@RequestMapping("test2")
	public ModelAndView test2(@PathParam("id") int id){
		FeUser user = userService.selectById(id);
		ModelAndView mv = new ModelAndView();
		mv.addObject("status", true);
		mv.addObject("data",user);
		if(id==1)throw new NumberFormatException("格式化错误");
		mv.setViewName("freemarker");//模版引擎路径通过视图解析器配置,或者通过application.properties配置freemarker
		return mv;
	}

}

这里我使用freemarker进行页面渲染

引入freemarker依赖:

                <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>

在application.properties文件中配置freemarker:

######################################freemarker######################################
#org.springframework.boot.autoconfigure.freemarker.FreeMarkerProperties
# Whether to enable MVC view resolution for this technology.
spring.freemarker.enabled=true
# 缓存配置 开发阶段应该配置为false 因为经常会改
spring.freemarker.cache=false

# 模版后缀名 默认为ftl
spring.freemarker.suffix=.html

# 文件编码
spring.freemarker.charset=UTF-8

# 模版加载的目录
spring.freemarker.template-loader-path=classpath:/templates/

# 配置
# locale	该选项指定该模板所用的国家/语言选项
# number_format	指定格式化输出数字的格式:currency、
# boolean_format	指定两个布尔值的语法格式,默认值是true,false
# date_format,time_format,datetime_format	定格式化输出日期的格式
# time_zone	设置格式化输出日期时所使用的时区
# 数字 千分位标识
spring.freemarker.settings.number_format=,##0.00
######################################freemarker######################################

首先要开启spring.freemarker.enabled为true,将页面后缀名改为html,spring.freemarker.suffix=.html,模版路径为classpath:/templates/,当我们mv.setViewName("index"),此时将会访问/templates下的index.html,至此freemarker配置完成。

在templates下加入error.html和freemarker.html,使用freemarker表达式进行页面渲染。

freemarker.html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
</head>
<body>
<h1>Hello Freemarker</h1>
<#if status == true>
	<h2>${data.name}</h2>
</#if>
</body>
</html>

error.html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
</head>
<body>
<h1>ERROR</h1>
<h2>${msg}</h2>
</body>
</html>

此时我们访问http://localhost:8881/exception/test2?id=1,会发现会抛出一个NumberFormatException异常,最后返回视图error。

当我们访问http://localhost:8881/exception/test2?id=2,将正常返回视图freemarker。

猜你喜欢

转载自blog.csdn.net/ZixiangLi/article/details/88575094