spring 自定义全局异常
在 springmvc 的 controller 中程序员经常要封装错误对象返回错误, 前端显示错误文案. 通过 spring 的异常处理器, 来进行自定义异常处理
学习目标
学习全局异常拦截器处理 controller 所有的异常的返回封装
定义枚举异常码, 设计自定义异常
案列
创建枚举异常码, 定义系统异常情况
/**
* @author tianjz
*/
public enum ResultEnum {
SUCCESS("0", "成功"),
PARAMETER_ERROR("1000", "请求参数错误"),
UNKNOWN_DATA_FORMAT("1001", "未知数据格式"),
UNDEFINED("1002", "未定义或者错误的接口"),
ERROR("2000", "响应错误"),
EMPTY("2001", "空数据");
private String code;
private String msg;
ResultEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
import com.cms2.imitative.commons.ResultEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author tianjz
*/
@Data
@AllArgsConstructor
public class StudyRuntimeException extends RuntimeException {
/**
* 异常码
*/
private ResultEnum errorCode;
/**
* 异常描述
*/
private String errorMessage;
/**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public StudyRuntimeException(ResultEnum errorCode) {
this.errorCode = errorCode;
}
}
具体拦截逻辑 :
通过异常 instanceof 判断出自定义异常
取出异常码, 通过 JSON 方式返回给前端
具体拦截流程:
springboot :< 不要忘记注入 >
springmvc :
请在 xml 中自行注入
import com.alibaba.fastjson.JSONObject;
import com.cms2.imitative.commons.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.Web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author tianjz
*/
@Component
@Slf4j
public class GlobalExceptionInterceptor implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
ModelAndView view = new ModelAndView();
Home("全局异常拦截");
try {
if (e instanceof StudyRuntimeException) {
setJsonErrorResponse(response, ((StudyRuntimeException) e).getErrorCode());
} else {
setJsonErrorResponse(response, ResultEnum.ERROR);
}
} catch (IOException ex) {
ex.printStackTrace();
log.error("全局异常捕获失败, 原因 :{},{}",ex.getMessage(),GlobalExceptionInterceptor.class);
return null;
}
return view;
}
private void setJsonErrorResponse(HttpServletResponse response, ResultEnum error) throws IOException {
Map<String, String> map = new LinkedHashMap<>();
// 设置状态码
response.setStatus(HttpStatus.OK.value());
// 设置 ContentType
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// 避免乱码
response.setCharacterEncoding("UTF-8");
map.put("code", error.getCode());
map.put("msg", error.getMsg());
Object JSON = JSONObject.toJSON(map);
response.getWriter().write(JSON.toString());
}
}
demo 代码 :
/**
* @author tianjz
*/
@RestController
@RequestMapping("/error")
public class ExceptionTest {
@GetMapping("/{errorCode}")
public String test(@PathVariable("errorCode")String error) {
switch (error) {
case "1000":
throw new StudyRuntimeException(ResultEnum.PARAMETER_ERROR);
case "2001":
throw new StudyRuntimeException(ResultEnum.EMPTY);
default:
System.out.println("啥也没有");
}
return null;
}
}
测试效果 :
1000
2001