一、背景
在SpringMVC和SpringBoot开发中,我们不可避免地要进行异常处理,目前SpringMVC框架也给我们提供了很多中异常处理地方式,今天介绍基于HandlerExceptionResolver
接口处理所有异常。
二、准备工作
1.创建一个SpringBoot Web工程,编写一个简单的Controller
@RestController
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/test")
public Result test(@RequestParam(value = "flag", defaultValue = "false") boolean flag) {
if (flag) {
throw BusinessException.error("业务异常信息");
}
return Result.success();
}
}
2.提供一个统一返回格式
package com.example.demo.model;
import lombok.Data;
//返回实体封装
@Data
public class Result {
private int status = 200;
private String msg = "success";
private String error;
private Object data;
private Result() {
}
public static Result success(String msg, Object data) {
Result result = new Result();
result.setMsg(msg);
result.setData(data);
return result;
}
public static Result success() {
Result result = new Result();
return result;
}
public static Result success(String msg) {
Result result = new Result();
result.setMsg(msg);
return result;
}
public static Result error(String msg, String error) {
Result result = new Result();
result.setStatus(500);
result.setMsg(msg);
result.setError(error);
return result;
}
public static Result error(String error) {
Result result = new Result();
result.setStatus(500);
result.setError(error);
return result;
}
}
3.创建一个业务异常类
//处理业务异常
public class BusinessException extends RuntimeException {
private BusinessException(String message) {
super(message);
}
public static BusinessException error(String error){
BusinessException exception = new BusinessException(error);
return exception;
}
}
4.编写一个自定义异常解析器
@Component
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver, Ordered {
// 设置优先级最高,由该异常解析器解析异常处理
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Result error = Result.error("程序异常,请联系管理员!");
// 处理业务异常
if (ex instanceof BusinessException) {
error.setError(ex.getMessage());
}
String json = "";
try {
ObjectMapper mapper = new ObjectMapper();
json = mapper.writeValueAsString(error);
} catch (JsonProcessingException e) {
json = e.getMessage();
}
String finalJson = json;
ModelAndView modelAndView = new ModelAndView();
// 将异常信息封装成 View
View view = (model, req, resp) -> {
resp.setCharacterEncoding("UTF-8");
resp.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
resp.setContentType("application/json;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print(finalJson);
writer.close();
};
modelAndView.setView(view);
return modelAndView;
}
}
三、测试
1.浏览器测试结果
2.使用postman模拟ajax请求结果
四、扩展
1.有的情况我们可能在没有进入到异常解析器,此时的异常会有tomcat请求转发一个新的请求,默认请求地址为:/error
,在SpringBoot里面,我们可以参考org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
该类的处理方式,编写一个ErrorController
的实现类作为controller来处理
2.对于采用前后端分离且涉及到分布式微服务开发的,开发过程中难免会遇到使用openFeign远程调用,而openFeign远程调用获取的返回值为Result
格式,难免有点鸡肋,此时我们可以采用Aop来处理controller返回结果的类型,不过值得注意的是,采用该种方式所有controller的返回格式都应该是object。
五、源码地址
Gitee源码地址:https://gitee.com/shphuang/shphuang.git