springmvc自定義全域性異常處理
springmvc全域性異常
- 實現步驟
- 在web層下新建一個類
- 通過實現spring的HandlerExceptionResolver介面來捕獲所有的異常。
- 寫一個異常處理類實現HandlerExceptionResolver介面
如下:
public class MvcWholeExceptionResolver implements HandlerExceptionResolver
{
private static final Logger logger = Logger.getLogger(MvcWholeExceptionResolver.class);
//mvc捕獲異常
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception exception)
{
//可以在mv裡放異常的頁面地址和異常的資訊
ModelAndView mv=new ModelAndView();
if(exception!=null)
{
//自定義封裝的業務異常丟擲類
BizException bizException = null;
logger.warn("MVC全域性異常捕捉類捕捉到異常");
if(exception instanceof LoginException)
{
logger.warn("捕捉到業務異常子類登入異常丟擲類:LoginException");
bizException=(BizException)exception;
}}else{ logger.warn("捕捉到系統未知異常:UNCLASSFY_EXCEPTION"); logger.warn("UNCLASSFY_EXCEPTION: "+exception); bizException=BizException.UNCLASSFY_EXCEPTION; //要捕捉更多業務類的異常,在自定義更多像LoginException的子類即可,或者在建立像BizException一樣的類,這裡就舉這兩個例子,其它仿照拓展 } logger.warn("異常程式碼:"+bizException.getCode()+" 異常資訊:"+bizException.getMessage()); //如果前端是通過ajax請求的後臺丟擲異常,那麼無需返回異常頁面,只需要返回異常資訊,方法如下: //在request作用域裡儲存異常的程式碼和資訊 request.setAttribute(UsualConstants.RETURN_ERROR_CODE_KEY, bizException.getCode()); request.setAttribute(UsualConstants.RETURN_ERROR_MSG_KEY, bizException.getMessage()); //在通過轉發到controller裡的方法,返回@ResponsBody方式,前臺ajax裡自然會捕捉到,如下: try{ logger.warn("轉發到ajax的統一異常處理方法"); request.getRequestDispatcher("/manage/login/jsonException").forward(request, response); }catch(Exception e){ logger.warn("轉發到ajax統一異常處理出錯"); e.printStackTrace(); } } //雖然ajax的異常在前面已經返回給前端了,但是還會執行到這裡,如果在mv裡沒有加任何東西或者只加異常資訊,return時會報錯,但不影響前端,前端已經捕捉到ajax的異常了 //如果在mv裡有加入跳轉的異常頁面,那麼前端也會跳轉,根據具體需要要不要跳轉具體異常頁面,這裡不放具體頁面 mv.addObject(UsualConstants.RETURN_ERROR_MSG_KEY,bizException.getMessage()); return mv; }
- 在springMVC的配置檔案中要指定全域性異常處理類的位置,如下:
- ajax的統一異常處理方法,如下:
@RequestMapping("jsonException")
@ResponseBody
public ResultJson jsonException(HttpServletRequest request,Map map)
{
logger.warn("統一異常處理方法,取出異常程式碼和異常資訊封裝到ResultJson,方法通過@ResponseBody方式返回ResultJson,前臺得到資訊為json格式");
Integer errorCode=(Integer)request.getAttribute(UsualConstants.RETURN_ERROR_CODE_KEY);
String errorMsg=(String)request.getAttribute(UsualConstants.RETURN_ERROR_MSG_KEY);
ResultJson rj=new ResultJson();
rj.setKey(errorCode);
rj.setMessage(errorMsg);
logger.warn("返回的ResultJson物件為:"+rj);
return rj;
}
- 在springMVC的配置檔案中要指定全域性異常處理類的位置,如下:
在service層或者dao層裡,自定義統一業務異常丟擲類,如下:
package cn.hj.yzp_app1.common.tools.exception;
import cn.hj.yzp_app1.common.tools.constantsTools.StatusConstants;
//業務異常基類,所有業務異常都必須繼承於此異常
public class BizException extends RuntimeExceptionAware
{
//RuntimeExceptionAware是自定義的執行時異常類,下面例子會貼出程式碼
private static final long serialVersionUID = -697081422076812812L;
//定義系統未知異常
public static final BizException UNCLASSFY_EXCEPTION = new BizException(StatusConstants.UNCLASSFY_EXCEPTION_CODE, StatusConstants.UNCLASSFY_EXCEPTION_MSG);
}//異常編號 protected int code; //異常資訊 protected String msg; //例項化異常 public BizException newInstance(String message, Object... args) { return new BizException(this.code, message, args); } public BizException(int code, String message, Object... args) { //父級變數 super(message); this.code = code; this.msg = String.format(message, args); } public BizException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public BizException(String message) { super(message); // TODO Auto-generated constructor stub } public BizException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } public BizException() { super(); // TODO Auto-generated constructor stub } /** * @return the code */ public int getCode() { return code; } /** * @param code the code to set */ public void setCode(int code) { this.code = code; } /** * @return the msg */ public String getMsg() { return msg; } /** * @param msg the msg to set */ public void setMsg(String msg) { this.msg = msg; } /** * @return the serialversionuid */ public static long getSerialversionuid() { return serialVersionUID; }
執行時異常處理類
package cn.hj.yzp_app1.common.tools.exception;
public class RuntimeExceptionAware extends RuntimeException{
//RuntimeException是系統的執行時異常類
private static final long serialVersionUID = -4896922247366620859L;
}public RuntimeExceptionAware() { super(); // TODO Auto-generated constructor stub } public RuntimeExceptionAware(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public RuntimeExceptionAware(String message) { super(message); // TODO Auto-generated constructor stub } public RuntimeExceptionAware(Throwable cause) { super(cause); // TODO Auto-generated constructor stub }
自定義的登入異常丟擲類:LoginException,如下:
package cn.hj.yzp_app1.common.tools.exception;
import org.apache.log4j.Logger;
import cn.hj.yzp_app1.common.tools.exception.BizException;
//自定義登入異常
public class LoginException extends BizException{
//屬於業務異常BizException的子類
private static final long serialVersionUID = -6160637178050783184L;
private static final Logger logger = Logger.getLogger(LoginException.class);
public LoginException() {
super();
// TODO Auto-generated constructor stub
}
}public LoginException(int code, String message, Object... args) { super(code, message, args); // TODO Auto-generated constructor stub } public LoginException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public LoginException(String message) { super(message); // TODO Auto-generated constructor stub } public LoginException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub }
丟擲異常例子,如下:
@RequestMapping("loginVerify")
@ResponseBody
public ResultJson loginVerify(UserExtend user,HttpSession session) {
ResultJson rj=new ResultJson();
try{
userServiceImpl.login(user);
}catch(NullPointerException e){
//如登入操作時,捕獲到空指標異常了,就可以認為是登入異常,丟擲後在MvcWholeExceptionResolver裡就可以捕捉到,然後在返回前端提示給使用者
throw new LoginException(StatusConstants.NO_LOGINMSG_CODE,StatusConstants.NO_LOGINMSG_MSG);
}
}