package com.hepengju.hekele.common.config; import com.p6spy.engine.spy.P6DataSource; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import javax.sql.DataSource; import java.util.Properties; /** * P6Spy數據源裝飾 * * <pre> * 說明: 打印真實SQL語句(替換好變量), SQL耗時及SQL語句過濾等作用 * * 修正: 20190924 * 說明: 發現在web-zuul中的jpa接口沒有打印相關SQL日志, 檢查發現是先進行了jpa自動配置, 跳過了此后置處理器. * 因此改為實現PriorityOrdered接口 * </pre> * * @see <a href="https://p6spy.readthedocs.io/en/latest/configandusage.html">P6Spy官方配置手冊</a> * @author hepengju 20190202 */ @Configuration public class P6SpyConfig { /** * P6Spy的初始化設置: 在實際項目中都是統一配置的,因此沒有必要每個工程類路徑下都放置一個spy.properties * * <pre> * 1. 設置日期格式 * 2. 定制化輸出: 執行時間(最重要), 數據庫連接ID(用來查看是否時同一個事務), 策略查看是否時回滾的, 單行SQL語句 * 3. 排除定時驗證語句: SELECT 1 * 4. 排除無關緊要策略: 比如批量,提交等(但是回滾建議不要排除) * </pre> */ static { Properties prop = System.getProperties(); String PRE = "p6spy.config."; prop.put(PRE + "dateformat" , "yyyy-MM-dd HH:mm:ss"); prop.put(PRE + "appender" , "com.p6spy.engine.spy.appender.Slf4JLogger"); prop.put(PRE + "logMessageFormat" , "com.p6spy.engine.spy.appender.CustomLineFormat"); prop.put(PRE + "customLogMessageFormat" , "%(executionTime)ms | %(category) | %(sqlSingleLine)"); prop.put(PRE + "databaseDialectDateFormat" , "yyyy-MM-dd"); prop.put(PRE + "databaseDialectTimestampFormat" , "yyyy-MM-dd HH:mm:ss"); prop.put(PRE + "databaseDialectBooleanFormat" , "boolean"); prop.put(PRE + "filter" , "true"); prop.put(PRE + "exclude" , "^SELECT 1"); prop.put(PRE + "excludecategories" , "info,debug,result,resultset,commit"); // batch也保留吧 } /** * P6數據源包裝, 打印SQL語句 */ @Bean public P6DataSourceBeanPostProcessor p6DataSourceBeanPostProcessor() { return new P6DataSourceBeanPostProcessor(); } /** * 如果是數據源則包裝下, 否則直接返回; 並設置為最低優先級(即最后處理) */ class P6DataSourceBeanPostProcessor implements BeanPostProcessor, PriorityOrdered { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return (bean instanceof DataSource) ? new P6DataSource((DataSource) bean) : bean; } @Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE; } } }