Springboot統一異常處理並儲存到資料庫
阿新 • • 發佈:2018-12-23
一.統一異常處理
之前我們平時在專案中遇到異常,用try-catch這種標準的捕獲方式處理就可以解決問題,但是在每個介面中都這麼寫,這種重複造輪子的事情對於我們程式設計師當然是不太願意的。
然而我們可以在springboot專案中利用@ControllerAdvice 這個註解可以更好的實現異常的捕獲處理。
@ControllerAdvice,是spring3.2提供的新註解,從名字上就可以看出大體的意思是控制器增強。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface ControllerAdvice { }
沒有什麼特別之處,該註解使用@Component註解,這樣的話當我們使用<context:component-scan>掃面時也能掃描到。
@ControllerAdvice註解內部可以使用@ExceptionHandler、@InitBinder、@ModelAttribute的方法應用到所有的@RequestMapping註解的方法。不過我們這裡只使用@ExceptionHandler。
二.建立ExceptionController類
建立 ExceptionController,並新增 @ControllerAdvice註解。
package com.left.config; import com.left.druid.utils.Exception.ErrorLogsUtil; import com.left.enums.CodeEnums; import com.left.pub.LpayException; import com.left.pub.ResponseData; 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.bind.annotation.ResponseBody; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; /** * Created by pillar on 2017/3/27. * qq 347637454 */ @ControllerAdvice public class ExceptionHandlers { Logger logger = LoggerFactory.getLogger(ExceptionHandlers.class); @ExceptionHandler(value = Exception.class) @ResponseBody public ResponseData handle(Exception e) { ErrorLogsUtil.error(e); //將異常寫入資料庫 if (e instanceof LpayException) { LpayException pillarException = (LpayException) e; return new ResponseData(pillarException.getStatus()); }else if (e instanceof MethodArgumentTypeMismatchException){ return new ResponseData(CodeEnums.PARAM_TYPE_ERROR,(Object)((MethodArgumentTypeMismatchException) e).getName()); }else { logger.info(e.toString()); e.printStackTrace(); return new ResponseData(CodeEnums.ERROR); } } }
其中ResponseData類為封裝的統一返回物件。
ResponseData:
package com.left.pub; import com.fasterxml.jackson.annotation.JsonInclude; import com.left.enums.CodeEnums; import java.io.Serializable; /** * * @date 2017/3/27 * qq 347637454 * 統一返回物件 */ public class ResponseData implements Serializable{ /** * 返回資料 */ private Object data; /** * 錯誤描述 */ private String msg; private int code; @JsonInclude(JsonInclude.Include.NON_NULL) private String sign; public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public ResponseData(CodeEnums status) { this.msg = status.getMessage(); this.code = status.getCode(); } public ResponseData() { } public ResponseData(Object data,String api_key){ this.data = data; this.msg = CodeEnums.SUCCESS.getMessage(); this.code = CodeEnums.SUCCESS.getCode(); this.sign = api_key; } public ResponseData(CodeEnums enums,Object data) { this.data = data; this.msg = enums.getMessage(); this.code = enums.getCode(); } public ResponseData(int code,String msg){ this.code =code; this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } @Override public String toString() { return "ResponseData{" + "data=" + data + ", msg='" + msg + '\'' + ", code=" + code + ", sign='" + sign + '\'' + '}'; } }
其中還有句程式碼為將異常寫入資料庫,需要ErrorLogsUtil.java工具類
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @Date 14:29 2018/05/29
* @Description 錯誤日誌工具
*/
public class ErrorLogsUtil {
/**
* @param: [e]
* @return void
* @Description 列印錯誤日誌並儲存到資料庫
*/
public static void error(Exception e) {
StackTraceElement stackTraceElement= e.getStackTrace()[0];
Connection con = null;
try {
Class.forName(MySqlConfig.driver);
con = (Connection) DriverManager.getConnection(MySqlConfig.url, MySqlConfig.username, MySqlConfig.password);
} catch (SQLException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
PreparedStatement ps = null;
String sql = "INSERT INTO itc_error_logs VALUES (UUID(), NOW(), ?, ?)";
try {
ps = con.prepareStatement(sql);
//列印日誌,錯在第幾行
String errorInfo = e.toString()+",errorMassage:"+stackTraceElement+","+"errorLine:"+stackTraceElement.getLineNumber();
ps.setString(1, errorInfo);
ps.execute();
} catch (SQLException e1) {
e1.printStackTrace();
} finally {
try {
if(ps != null) {
ps.close();
}
if(con != null) {
con.close();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
}
MySqlConfig類:
import com.alibaba.druid.pool.DruidDataSource;
import com.left.druid.utils.DataSourceEnum;
import com.left.druid.utils.LocalThreadDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**********************************************
* @author pillar
* @date ${DATE}
**********************************************/
@Configuration
@MapperScan(basePackages = MySqlConfig.PACKAGE)
public class MySqlConfig{
static final String PACKAGE = "com.left";
@Value("${spring.datasource.url}")
public static String url;
@Value("${spring.datasource.username}")
public static String user;
@Value("${spring.datasource.password}")
public static String password;
@Value("${spring.datasource.driverClassName}")
public static String driverClass;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.filters}")
private String filters;
@Value("${spring.datasource.publicKey}")
private String publicKey;}
這樣後臺的異常資訊就可以統一儲存到資料庫了。
最後如果你們公司的前端夠閒的話,最好是做個前端頁面展示,這樣就不用連資料庫檢視,直接在前端展示,更為直觀方便。