注解解读:
@ControllerAdvice:它定义在一个类上,和@Component类似,它使得@ExceptionHandler、@InitBindler、@ModelAttribute注解可以作用在所有@RequestMapping注解上。
@ExceptionHandler:它定义在Controller的方法上,作用是捕获指定的异常,然后进行统一处理并返回最后的结果。
理解了@ControllerAdvice和@ExceptionHandler注解,就可以用它们做全局统一捕获异常了(注意:这里说的全局是指的Controler层)。首先编写全局异常处理类,这里我分两种返回值类型,一种是Json字符串(直接输出到页面),一种是ModelAndView(可以使用前端模版引擎freemarker或者thymeleaf进行渲染)
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Map exceptionHandler(HttpServletRequest req,HttpServletResponse resp,Exception e){
Map map = new HashMap();
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的全局处理类
@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依赖:
org.springframework.boot
spring-boot-starter-freemarker
在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:
Hello Freemarker
<#if status == true>
${data.name}
#if>
error.html:
ERROR
${msg}
此时我们访问http://localhost:8881/exception/test2?id=1,会发现会抛出一个NumberFormatException异常,最后返回视图error。
当我们访问http://localhost:8881/exception/test2?id=2,将正常返回视图freemarker。