1. 程式人生 > >springboot全域性異常處理ControllerAdvice示例區分方法返回型別json還是頁面

springboot全域性異常處理ControllerAdvice示例區分方法返回型別json還是頁面

如果返回是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;
	}
	
	
	
	
}