Spring boot/mvc项目中通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理。
在spring web项目开发中,我们经常会遇到各种exception,这些exception根据业务或者场景不同抛出不同的信息和返回类型,有的exception需要返回json数据格式的错误,有的exception又需要跳转到某个错误页面。这里将会讲解常见的几个exception统一处理。
注意@RestControllerAdvice注解一般在spring boot接口项目中使用。spring普通项目也支持不过需要高版本的spring才有@RestControllerAdvice注解标签。
Java代码:
import com.xqlee.business.response.Result;
import com.xqlee.system.exception.BusinessException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class RestExceptionHandler {
@ExceptionHandler(value = { BusinessException.class })
public Result business(BusinessException ex) {
return Result.fail("业务异常:"+ex.getMessage());
}
@ExceptionHandler(value = { MethodArgumentNotValidException.class })
public Result methodArgumentNotValidException(MethodArgumentNotValidException ex) {
String field=ex.getBindingResult().getFieldError().getField().replace("parameter.","");
String message=ex.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail("验证失败:字段["+field+"]"+message);
}
@ExceptionHandler(value = { Exception.class })
public Result exception(Exception ex) {
return Result.fail("系统异常:"+ex.getMessage());
}
}
import com.xqlee.common.http.result.ResultJson;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = {BusinessException.class})
@ResponseBody
public ResultJson business(BusinessException ex) {
return ResultJson.fail("业务异常:" + ex.getMessage());
}
@ExceptionHandler(value = {Exception.class})
public ModelAndView exception(Exception ex, HttpServletRequest request, HttpServletResponse response) {
String uri = request.getRequestURI();
ModelAndView modelAndView = new ModelAndView();
if (uri.contains("enterprise")) {
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
modelAndView.setView(jsonView);
modelAndView.addObject(ResultJson.fail("系统异常:" + ex.getMessage()));
return modelAndView;
} else {
RedirectView redirectView = new RedirectView("/static/error/500.jsp");
redirectView.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
modelAndView.setView(redirectView);
return modelAndView;
}
}
}
某些情况我们需要根据请求类型返回不同得view,比如ajax请求返回JSON数据,普通请求返回页面数据,
import com.alibaba.fastjson.JSON;
import net.ifok.common.utils.MapUtil;
import net.ifok.ocms.system.exception.BusinessException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import javax.servlet.http.HttpServletRequest;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.AccessDeniedException;
import java.util.List;
@ControllerAdvice
public class ControllerExceptionHandler {
/**
* 业务异常
*
* @param
* @param e
* @return
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
@ResponseBody
@ExceptionHandler(value = { BusinessException.class ,RuntimeException.class})
public ModelAndView businessExceptionHandler(HttpServletRequest request, BusinessException e)
throws IllegalAccessException, InvocationTargetException, IntrospectionException {
Log.error("业务异常:" + e.getMessage(),e, getClass());
String uri = request.getRequestURI();
boolean isJsonRequest =isAjaxRequest(request);
if (isJsonRequest) {
ModelAndView view = new ModelAndView();
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
jsonView.setAttributesMap(MapUtil.toMap(Result.fail(e.getMessage())));
view.setView(jsonView);
return view;
} else {
ModelAndView view = new ModelAndView();
view.setViewName("redirect:/503.html");
return view;
}
}
@ExceptionHandler(value = { MethodArgumentNotValidException.class})
public ModelAndView methodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e){
String message=e.getBindingResult().getFieldError().getDefaultMessage();
Log.error("验证失败:" +message,e, getClass());
boolean isJsonRequest =isAjaxRequest(request);
if (isJsonRequest) {
ModelAndView view = new ModelAndView();
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail(message))));
view.setView(jsonView);
return view;
} else {
ModelAndView view = new ModelAndView();
view.setViewName("redirect:/503.html");
return view;
}
}
@ExceptionHandler(value = { HttpRequestMethodNotSupportedException.class })
public ModelAndView methodNotSupportedException(HttpServletRequest request, HttpRequestMethodNotSupportedException e){
Log.error("HttpRequestMethodNotSupportedException:请求方法不支持:"+e.getMethod()+"\n请求地址:"
+request.getRequestURI()+"\n UA:\n" + request.getHeader("User-Agent"),getClass());
boolean isJsonRequest =isAjaxRequest(request);
if (isJsonRequest) {
ModelAndView view = new ModelAndView();
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail("请求方式["+e.getMethod()+"]不支持"))));
view.setView(jsonView);
return view;
} else {
ModelAndView view = new ModelAndView();
view.setViewName("redirect:/404.html");
return view;
}
}
@ExceptionHandler(value = { AccessDeniedException.class })
public ModelAndView accessDeniedException(HttpServletRequest request, AccessDeniedException e) {
Log.error("权限不足->\n资源地址:" + request.getRequestURI() + "\n UA:\n" + request.getHeader("User-Agent"),
this.getClass());
boolean isJsonRequest=isAjaxRequest(request);
if (isJsonRequest) {
ModelAndView view = new ModelAndView();
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail(e.getMessage()))));
view.setView(jsonView);
return view;
} else {
ModelAndView view = new ModelAndView();
view.setViewName("redirect:/403.html");
return view;
}
}
@ExceptionHandler(value = { Exception.class })
public ModelAndView exceptionHandler(HttpServletRequest reqeust, Exception e) {
Log.error(e.getMessage(), e, getClass());
boolean isJsonRequest =isAjaxRequest(reqeust);
if (isJsonRequest) {
ModelAndView view = new ModelAndView();
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail(e.getMessage()))));
view.setView(jsonView);
return view;
} else {
ModelAndView view = new ModelAndView();
view.setViewName("redirect:/503.html");
return view;
}
}
public static boolean isAjaxRequest(HttpServletRequest request) {
String requestedWith = request.getHeader("x-requested-with");
if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
return true;
} else {
return false;
}
}
}
http://blog.xqlee.com/article/428.html