springboot全域性異常處理ControllerAdvice示例區分方法返回型別json還是頁面
阿新 • • 發佈:2018-11-17
如果返回是json,收到異常則返回預設的異常包裝型別
如果返回是頁面,收到異常則返回預設的異常頁面
判斷返回型別的實現方法是,加一個攔截器,在preHandler中取得HandlerMethod,判斷其方法的返回型別,以及方法的註解和類的註解
import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; public class BaseInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod)) { return true; } HandlerMethod hm = (HandlerMethod) handler; Method method = hm.getMethod(); boolean b1 = method.getReturnType().equals(String.class); boolean b2 = !method.isAnnotationPresent(ResponseBody.class); boolean b3 = !hm.getBeanType().isAnnotationPresent(RestController.class); request.setAttribute("method_return_is_view", b1 && b2 && b3); return true; } }
method_return_is_view 這個表示返回的型別是頁面
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.json.MappingJackson2JsonView; @ControllerAdvice public class BaseControllerAdvice { private Logger logger = LoggerFactory.getLogger(this.getClass()); @ExceptionHandler public ModelAndView handleException(Exception e,HttpServletRequest request,HttpServletResponse response) throws Exception{ String parameters = ""; for(String key:request.getParameterMap().keySet()){ parameters += (key+"="+request.getParameter(key)+","); } if(parameters.length()>0){ parameters = parameters.substring(0, parameters.length()-1); } Object o = request.getAttribute("method_return_is_view"); if(o==null){ logger.error("",e); throw e; } boolean isView = (Boolean)o; boolean isParamError = (e instanceof MethodArgumentTypeMismatchException); boolean isBusiness = false; if(e instanceof BusinessException){ logger.warn("---BusinessException---"+e.getMessage()); logger.warn("RequestFail["+request.getRequestURI()+"]["+parameters+"]"); isBusiness = true; }else if(isParamError){ logger.warn("---IllegalArgument---"+e.getMessage()); logger.warn("RequestFail["+request.getRequestURI()+"]["+parameters+"]"); }else{ logger.error("---UnCaughtException---",e); logger.error("RequestFail["+request.getRequestURI()+"]["+parameters+"]"); } ModelAndView mv; if(isView){ if(isBusiness){ mv = new ModelAndView("error/400"); request.setAttribute("message", ((BusinessException)e).getMessage()); return mv; } if(isParamError){ mv = new ModelAndView("error/400"); request.setAttribute("message", "引數錯誤"); return mv; } mv = new ModelAndView("error/500"); return mv; } mv = new ModelAndView(new MappingJackson2JsonView()); Result res; if(isBusiness){ BusinessException be = (BusinessException)e; res = Result.fail(be.getCode(),e.getMessage()); }else if(isParamError){ res = Result.illegalParam(); }else{ res = Result.fail(); } mv.addObject("code",res.getCode()); mv.addObject("message",res.getMessage()); return mv; } }
涉及公共包裝類
/** * 業務異常,service層對於業務相關的提示可以用這個異常返回,BaseExceptionHandler進行識別包裝 * @author Administrator * */ public class BusinessException extends RuntimeException{ /** * */ private static final long serialVersionUID = 1L; private Integer code; public BusinessException(String message) { super(message); } public BusinessException(Integer code,String message) { super(message); this.code = code; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
/**
* 成功返回200,其他皆為失敗
* @author Administrator
*
*/
public class Result {
private Integer code = 0;
private String message;
private Object result;
/**成功返回200*/
public static Result ok(Object result){
Result r = new Result();
r.setCode(200);
r.setResult(result);
return r;
}
/**成功返回200*/
public static Result ok(){
Result r = new Result();
r.setCode(200);
r.setMessage("操作成功");
return r;
}
/**系統異常,code=500*/
public static Result fail(){
Result r = new Result();
r.setCode(500);
r.setMessage("系統異常");
return r;
}
/**請求失敗提示,code為空*/
public static Result fail(String message){
Result r = new Result();
r.setMessage(message);
return r;
}
/**請求失敗提示,自定義code*/
public static Result fail(Integer code,String message){
Result r = new Result();
if(code==null){
code = 0;
}
r.setCode(code);
r.setMessage(message);
return r;
}
public static Result illegalParam(){
Result r = new Result();
r.setCode(400);
r.setMessage("引數錯誤");
return r;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
}