天天看點

統一處理異常demo

異常定義

**1. 通用異常:**就是系統産生的異常

(1)狀态碼

(2)提示資訊

/***
 * 通用異常定義
 */
public enum CommonException {
    SYSTEM_EXCEPTION(-1,"系統繁忙,請稍後重試");

    private Integer code;
    private String message;

    CommonException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    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;
    }
}
           

**2.業務異常:**如使用者登入失敗等

(1) 狀态碼

(2) 提示資訊

/***
 * 使用者業務異常
 */
public enum  UserException {
    USER_PASSWORD_ERROR(1001,"使用者名或密碼錯誤");
    private Integer code;
    private String message;

    UserException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    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;
    }
}
           

業務中調用

此處的ReturnResultUtils.returnFail方法是我自己定義的一個傳回值的方法,可以檢視[統一傳回資料](https://blog.csdn.net/qq_40664795/article/details/105570986)
ReturnResultUtils.returnFail(CommonException.SYSTEM_EXCEPTION.getCode(),Com
monException.SYSTEM_EXCEPTION.getMessage());
           

統一異常處理

實作步驟

① 編寫攔截器,攔截抛出的異常

/***
 * 異常統一處理的攔截器
 */
public class ExceptionInterceptor implements HandlerInterceptor{

    /**
     * 方法處理前
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");//這一步主要是前後端分離統一在方法處理前進行攔截解決跨域問題
        return true;//true開啟攔截功能
    }

    /**
     * 方法處理後,傳回前
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    /***
     * 方法處理完成後
     * @param request
     * @param response
     * @param o
     * @param e
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
        //出現異常進行處理
        if(EmptyUtils.isNotEmpty(e)){
            response.setContentType("text/html;charset=UTF-8");//設定傳回值的編碼格式
            PrintUtil printUtil=new PrintUtil(response);  //自己封裝的一個輸出流工具,由于該方法是void,是以不能把異常return回去,通過流的方式處理
            ReturnResult returnResult=ReturnResultUtils.returnFail(CommonException.SYSTEM_EXCEPTION.getCode(),CommonException.SYSTEM_EXCEPTION.getMessage());//傳回異常資訊
            printUtil.print(JSONObject.toJSON(returnResult));//轉成JSONObject
        }
    }
}
           

printUtil工具

import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintUtil {
	//列印日志
	static Logger logger=Logger.getLogger(PrintUtil.class);

	public HttpServletResponse response;

	public PrintUtil(HttpServletResponse response, String contentType){
		this.response=response;
		this.response.setContentType(contentType);
	}
	public PrintUtil(HttpServletResponse response){
		this.response=response;
	}
	public void print(Object msg){
        PrintWriter writer=null;
		try {
            if(null != response){
				//如果系統打開了outputStream 那麼将其關閉
                writer=new PrintWriter(response.getOutputStream());
				String temp=new String(String.valueOf(msg));
                writer.write(temp);
                writer.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
				writer.close();
		}
    }
}
           
統一處理異常demo

② 判斷異常,進行資料傳回

引入處理json依賴
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.54</version>
</dependency>

捕獲了異常進行處理
/***
     * 方法處理完成後
     * @param request
     * @param response
     * @param o
     * @param e
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
        //出現異常進行處理
        if(EmptyUtils.isNotEmpty(e)){
            response.setContentType("text/html;charset=UTF-8");//設定傳回值的編碼格式
            PrintUtil printUtil=new PrintUtil(response);  //自己封裝的一個輸出流工具,由于該方法是void,是以不能把異常return回去,通過流的方式處理
            ReturnResult returnResult=ReturnResultUtils.returnFail(CommonException.SYSTEM_EXCEPTION.getCode(),CommonException.SYSTEM_EXCEPTION.getMessage());//傳回異常資訊
            printUtil.print(JSONObject.toJSON(returnResult));//轉成JSONObject
        }
    }
           

第3步

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/***
 * 配置攔截器
 */
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

    /**
     * 把ExceptionInterceptor異常交給springIOC管理,如果定義了多個異常類,那也要像這樣添加多個
     * @return
     */
    @Bean
    public ExceptionInterceptor exceptionInterceptor(){
        return new ExceptionInterceptor();
    }

    /**
     * 定義的登入異常資訊
     * @return
     */
    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }

    /**
     * 要實作WebMvcConfigurerAdapter的addInterceptors這個方法
     * 在ExceptionInterceptor異常裡凡是api/後面的都進行攔截
     * 在LoginInterceptor異常裡凡是api/v/後面的都進行攔截
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(exceptionInterceptor()).addPathPatterns("/api/**");
        registry.addInterceptor(loginInterceptor()).addPathPatterns("/api/v/**");
        super.addInterceptors(registry);
    }
}
           

在業務中處理異常不再需要try-cartch進行捕獲異常了,直接抛出即可(也就是有異常不處理,抛給攔截器進行統一處理),應該如果有異常會在攔截器攔截時進行攔截處理

/***
     * 根據使用者名和密碼生成token
     * @param phone
     * @param password
     * @return
     */
    public ReturnResult validateToken(String phone, String password)throws Exception{
        ReturnResult returnResult=null;
        QgUser qgUser=null;
        String token=null;
        qgUser=qgUserService.queryQgUserByPhoneAndPwd(phone,password);
        if(null!=qgUser){
            //如果驗證成功,生成token放在redis
            String oldToken=redisUtil.getStr(qgUser.getId());
            if(EmptyUtils.isNotEmpty(oldToken)){
                redisUtil.del(oldToken);
                redisUtil.del(qgUser.getId());
            }
            token=Constants.tokenPrefix+TokenUtils.createToken(qgUser.getId(),qgUser.getPhone());
            redisUtil.setStr(token, JSONObject.toJSONString(qgUser), Constants.loginExpire);
            redisUtil.setStr(qgUser.getId(), token,Constants.loginExpire);
            Map<String,Object> result=new HashMap<String,Object>();
            result.put("token",token);
            returnResult= ReturnResultUtils.returnSuccess(result);
        }else{
            returnResult= ReturnResultUtils.returnFail(UserException.USER_PASSWORD_ERROR.getCode(),UserException.USER_PASSWORD_ERROR.getMessage());
        }
        return returnResult;
    }
           

繼續閱讀