From 27dd1a7a4034bf8943cc1203b02ee8355a177bd3 Mon Sep 17 00:00:00 2001
From: fuliqi <fuliqi@qq.com>
Date: 星期五, 08 三月 2024 11:30:14 +0800
Subject: [PATCH] 日志、接口耗时、防重复提交

---
 ycl-server/src/main/java/com/ycl/filter/RepeatedlyRequestWrapper.java         |   77 +++++++
 ycl-server/src/main/java/com/ycl/interceptor/RepeatSubmitInterceptor.java     |   56 +++++
 ycl-server/src/main/resources/application.yml                                 |    1 
 /dev/null                                                                     |  129 ------------
 ycl-server/src/main/resources/logback.xml                                     |   93 +++++++++
 ycl-server/src/main/java/com/ycl/config/FilterConfig.java                     |   29 ++
 ycl-server/src/main/java/com/ycl/interceptor/impl/SameUrlDataInterceptor.java |  111 +++++++++++
 ycl-server/src/main/java/com/ycl/aop/TimeAspect.java                          |   29 ++
 ycl-server/src/main/java/com/ycl/filter/RepeatableFilter.java                 |   48 ++++
 9 files changed, 443 insertions(+), 130 deletions(-)

diff --git a/ycl-server/src/main/java/com/ycl/aop/TimeAspect.java b/ycl-server/src/main/java/com/ycl/aop/TimeAspect.java
new file mode 100644
index 0000000..5b9d8e4
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/aop/TimeAspect.java
@@ -0,0 +1,29 @@
+package com.ycl.aop;
+
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+@Aspect
+@Component
+@Slf4j
+public class TimeAspect {
+
+    // 瀹氫箟鍒囩偣Pointcut
+    @Pointcut("execution(public * com.ycl..*.*Controller.*(..))")
+    public void excudeService() {
+    }
+
+    @Around("excudeService()")
+    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
+    	long start=System.currentTimeMillis();
+        Object result = pjp.proceed();
+        long end=System.currentTimeMillis();
+        log.debug("鎺ュ彛鎬昏鑰楁椂:{}ms",end-start);
+        return result;
+    }
+}
diff --git a/ycl-server/src/main/java/com/ycl/config/FilterConfig.java b/ycl-server/src/main/java/com/ycl/config/FilterConfig.java
new file mode 100644
index 0000000..2f5a4dd
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/config/FilterConfig.java
@@ -0,0 +1,29 @@
+package com.ycl.config;
+
+import com.ycl.filter.RepeatableFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Filter閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class FilterConfig
+{
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    public FilterRegistrationBean someFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new RepeatableFilter());
+        registration.addUrlPatterns("/*");
+        registration.setName("repeatableFilter");
+        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
+        return registration;
+    }
+
+}
diff --git a/ycl-server/src/main/java/com/ycl/filter/RepeatableFilter.java b/ycl-server/src/main/java/com/ycl/filter/RepeatableFilter.java
new file mode 100644
index 0000000..dd1f5e9
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/filter/RepeatableFilter.java
@@ -0,0 +1,48 @@
+package com.ycl.filter;
+
+import jakarta.servlet.*;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.http.MediaType;
+import utils.StringUtils;
+
+import java.io.IOException;
+
+/**
+ * Repeatable 杩囨护鍣�
+ * 
+ * @author ruoyi
+ */
+public class RepeatableFilter implements Filter
+{
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException
+    {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException
+    {
+        ServletRequest requestWrapper = null;
+        if (request instanceof HttpServletRequest
+                && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
+        {
+            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
+        }
+        if (null == requestWrapper)
+        {
+            chain.doFilter(request, response);
+        }
+        else
+        {
+            chain.doFilter(requestWrapper, response);
+        }
+    }
+
+    @Override
+    public void destroy()
+    {
+
+    }
+}
diff --git a/ycl-server/src/main/java/com/ycl/filter/RepeatedlyRequestWrapper.java b/ycl-server/src/main/java/com/ycl/filter/RepeatedlyRequestWrapper.java
new file mode 100644
index 0000000..d1995bf
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/filter/RepeatedlyRequestWrapper.java
@@ -0,0 +1,77 @@
+package com.ycl.filter;
+
+import com.ycl.utils.http.HttpHelper;
+import constant.Constants;
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * 鏋勫缓鍙噸澶嶈鍙杋nputStream鐨剅equest
+ * 
+ * @author ruoyi
+ */
+public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
+{
+    private final byte[] body;
+
+    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
+    {
+        super(request);
+        request.setCharacterEncoding(Constants.UTF8);
+        response.setCharacterEncoding(Constants.UTF8);
+
+        body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException
+    {
+        return new BufferedReader(new InputStreamReader(getInputStream()));
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException
+    {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+        return new ServletInputStream()
+        {
+            @Override
+            public int read() throws IOException
+            {
+                return bais.read();
+            }
+
+            @Override
+            public int available() throws IOException
+            {
+                return body.length;
+            }
+
+            @Override
+            public boolean isFinished()
+            {
+                return false;
+            }
+
+            @Override
+            public boolean isReady()
+            {
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener)
+            {
+
+            }
+        };
+    }
+}
diff --git a/ycl-server/src/main/java/com/ycl/interceptor/RepeatSubmitInterceptor.java b/ycl-server/src/main/java/com/ycl/interceptor/RepeatSubmitInterceptor.java
new file mode 100644
index 0000000..0cb7905
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/interceptor/RepeatSubmitInterceptor.java
@@ -0,0 +1,56 @@
+package com.ycl.interceptor;
+
+import annotation.RepeatSubmit;
+import com.alibaba.fastjson2.JSON;
+import com.ycl.system.AjaxResult;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+import utils.ServletUtils;
+
+import java.lang.reflect.Method;
+
+/**
+ * 闃叉閲嶅鎻愪氦鎷︽埅鍣�
+ *
+ * @author ruoyi
+ */
+@Component
+public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
+{
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
+    {
+        if (handler instanceof HandlerMethod)
+        {
+            HandlerMethod handlerMethod = (HandlerMethod) handler;
+            Method method = handlerMethod.getMethod();
+            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
+            if (annotation != null)
+            {
+                if (this.isRepeatSubmit(request, annotation))
+                {
+                    AjaxResult ajaxResult = AjaxResult.error(annotation.message());
+                    ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    /**
+     * 楠岃瘉鏄惁閲嶅鎻愪氦鐢卞瓙绫诲疄鐜板叿浣撶殑闃查噸澶嶆彁浜ょ殑瑙勫垯
+     *
+     * @param request
+     * @return
+     * @throws Exception
+     */
+    public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
+}
diff --git a/ycl-server/src/main/java/com/ycl/interceptor/impl/SameUrlDataInterceptor.java b/ycl-server/src/main/java/com/ycl/interceptor/impl/SameUrlDataInterceptor.java
new file mode 100644
index 0000000..21010ad
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/interceptor/impl/SameUrlDataInterceptor.java
@@ -0,0 +1,111 @@
+package com.ycl.interceptor.impl;
+
+import annotation.RepeatSubmit;
+import com.alibaba.fastjson2.JSON;
+import com.ycl.filter.RepeatedlyRequestWrapper;
+import com.ycl.interceptor.RepeatSubmitInterceptor;
+import com.ycl.utils.http.HttpHelper;
+import com.ycl.utils.redis.RedisCache;
+import constant.CacheConstants;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import utils.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 鍒ゆ柇璇锋眰url鍜屾暟鎹槸鍚﹀拰涓婁竴娆$浉鍚岋紝
+ * 濡傛灉鍜屼笂娆$浉鍚岋紝鍒欐槸閲嶅鎻愪氦琛ㄥ崟銆� 鏈夋晥鏃堕棿涓�10绉掑唴銆�
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
+{
+    public final String REPEAT_PARAMS = "repeatParams";
+
+    public final String REPEAT_TIME = "repeatTime";
+
+    // 浠ょ墝鑷畾涔夋爣璇�
+    @Value("${token.header}")
+    private String header;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
+    {
+        String nowParams = "";
+        if (request instanceof RepeatedlyRequestWrapper)
+        {
+            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
+            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
+        }
+
+        // body鍙傛暟涓虹┖锛岃幏鍙朠arameter鐨勬暟鎹�
+        if (StringUtils.isEmpty(nowParams))
+        {
+            nowParams = JSON.toJSONString(request.getParameterMap());
+        }
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
+        // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
+        String url = request.getRequestURI();
+
+        // 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
+        String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
+
+        // 鍞竴鏍囪瘑锛堟寚瀹歬ey + url + 娑堟伅澶达級
+        String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
+
+        Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
+        if (sessionObj != null)
+        {
+            Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
+            if (sessionMap.containsKey(url))
+            {
+                Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
+                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
+                {
+                    return true;
+                }
+            }
+        }
+        Map<String, Object> cacheMap = new HashMap<String, Object>();
+        cacheMap.put(url, nowDataMap);
+        redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇鍙傛暟鏄惁鐩稿悓
+     */
+    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
+    {
+        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
+        String preParams = (String) preMap.get(REPEAT_PARAMS);
+        return nowParams.equals(preParams);
+    }
+
+    /**
+     * 鍒ゆ柇涓ゆ闂撮殧鏃堕棿
+     */
+    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
+    {
+        long time1 = (Long) nowMap.get(REPEAT_TIME);
+        long time2 = (Long) preMap.get(REPEAT_TIME);
+        if ((time1 - time2) < interval)
+        {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/ycl-server/src/main/resources/application.yml b/ycl-server/src/main/resources/application.yml
index 7b858c4..d08e1c8 100644
--- a/ycl-server/src/main/resources/application.yml
+++ b/ycl-server/src/main/resources/application.yml
@@ -69,7 +69,6 @@
   level:
     org.springframework: warn
     com.ycl : debug
-  config: classpath:logback-plus.xml
 
 # security閰嶇疆
 security:
diff --git a/ycl-server/src/main/resources/logback-plus.xml b/ycl-server/src/main/resources/logback-plus.xml
deleted file mode 100644
index cf804e0..0000000
--- a/ycl-server/src/main/resources/logback-plus.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<configuration>
-    <property name="log.path" value="./logs"/>
-    <property name="console.log.pattern"
-              value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
-    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
-
-    <!-- 鎺у埗鍙拌緭鍑� -->
-    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder>
-            <pattern>${console.log.pattern}</pattern>
-            <charset>utf-8</charset>
-        </encoder>
-    </appender>
-
-    <!-- 鎺у埗鍙拌緭鍑� -->
-    <appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <file>${log.path}/sys-console.log</file>
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
-            <fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <!-- 鏃ュ織鏈�澶� 1澶� -->
-            <maxHistory>1</maxHistory>
-        </rollingPolicy>
-        <encoder>
-            <pattern>${log.pattern}</pattern>
-            <charset>utf-8</charset>
-        </encoder>
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <!-- 杩囨护鐨勭骇鍒� -->
-            <level>INFO</level>
-        </filter>
-    </appender>
-
-    <!-- 绯荤粺鏃ュ織杈撳嚭 -->
-    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <file>${log.path}/sys-info.log</file>
-        <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
-            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
-            <maxHistory>60</maxHistory>
-        </rollingPolicy>
-        <encoder>
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-        <filter class="ch.qos.logback.classic.filter.LevelFilter">
-            <!-- 杩囨护鐨勭骇鍒� -->
-            <level>INFO</level>
-            <!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
-            <onMatch>ACCEPT</onMatch>
-            <!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
-            <onMismatch>DENY</onMismatch>
-        </filter>
-    </appender>
-
-    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <file>${log.path}/sys-error.log</file>
-        <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
-            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
-            <maxHistory>60</maxHistory>
-        </rollingPolicy>
-        <encoder>
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-        <filter class="ch.qos.logback.classic.filter.LevelFilter">
-            <!-- 杩囨护鐨勭骇鍒� -->
-            <level>ERROR</level>
-            <!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
-            <onMatch>ACCEPT</onMatch>
-            <!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
-            <onMismatch>DENY</onMismatch>
-        </filter>
-    </appender>
-
-    <!-- info寮傛杈撳嚭 -->
-    <appender name="async_info" class="ch.qos.logback.classic.AsyncAppender">
-        <!-- 涓嶄涪澶辨棩蹇�.榛樿鐨�,濡傛灉闃熷垪鐨�80%宸叉弧,鍒欎細涓㈠純TRACT銆丏EBUG銆両NFO绾у埆鐨勬棩蹇� -->
-        <discardingThreshold>0</discardingThreshold>
-        <!-- 鏇存敼榛樿鐨勯槦鍒楃殑娣卞害,璇ュ�间細褰卞搷鎬ц兘.榛樿鍊间负256 -->
-        <queueSize>512</queueSize>
-        <!-- 娣诲姞闄勫姞鐨刟ppender,鏈�澶氬彧鑳芥坊鍔犱竴涓� -->
-        <appender-ref ref="file_info"/>
-    </appender>
-
-    <!-- error寮傛杈撳嚭 -->
-    <appender name="async_error" class="ch.qos.logback.classic.AsyncAppender">
-        <!-- 涓嶄涪澶辨棩蹇�.榛樿鐨�,濡傛灉闃熷垪鐨�80%宸叉弧,鍒欎細涓㈠純TRACT銆丏EBUG銆両NFO绾у埆鐨勬棩蹇� -->
-        <discardingThreshold>0</discardingThreshold>
-        <!-- 鏇存敼榛樿鐨勯槦鍒楃殑娣卞害,璇ュ�间細褰卞搷鎬ц兘.榛樿鍊间负256 -->
-        <queueSize>512</queueSize>
-        <!-- 娣诲姞闄勫姞鐨刟ppender,鏈�澶氬彧鑳芥坊鍔犱竴涓� -->
-        <appender-ref ref="file_error"/>
-    </appender>
-
-    <!-- 鏁村悎 skywalking 鎺у埗鍙拌緭鍑� tid -->
-    <!--    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
-    <!--        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
-    <!--            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
-    <!--                <pattern>[%tid] ${console.log.pattern}</pattern>-->
-    <!--            </layout>-->
-    <!--            <charset>utf-8</charset>-->
-    <!--        </encoder>-->
-    <!--    </appender>-->
-
-    <!-- 鏁村悎 skywalking 鎺ㄩ�侀噰闆嗘棩蹇� -->
-    <!--    <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
-    <!--        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
-    <!--            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
-    <!--                <pattern>[%tid] ${console.log.pattern}</pattern>-->
-    <!--            </layout>-->
-    <!--            <charset>utf-8</charset>-->
-    <!--        </encoder>-->
-    <!--    </appender>-->
-
-    <!--绯荤粺鎿嶄綔鏃ュ織-->
-    <root level="info">
-        <appender-ref ref="console" />
-        <appender-ref ref="async_info" />
-        <appender-ref ref="async_error" />
-        <appender-ref ref="file_console" />
-        <!--        <appender-ref ref="sky_log"/>-->
-    </root>
-
-</configuration>
diff --git a/ycl-server/src/main/resources/logback.xml b/ycl-server/src/main/resources/logback.xml
new file mode 100644
index 0000000..77d7d62
--- /dev/null
+++ b/ycl-server/src/main/resources/logback.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 鏃ュ織瀛樻斁璺緞 -->
+	<property name="log.path" value="./logs" />
+    <!-- 鏃ュ織杈撳嚭鏍煎紡 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 鎺у埗鍙拌緭鍑� -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+	
+	<!-- 绯荤粺鏃ュ織杈撳嚭 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 杩囨护鐨勭骇鍒� -->
+            <level>INFO</level>
+            <!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+	
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 杩囨护鐨勭骇鍒� -->
+            <level>ERROR</level>
+			<!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+	
+	<!-- 鐢ㄦ埛璁块棶鏃ュ織杈撳嚭  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 鎸夊ぉ鍥炴粴 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+	
+	<!-- 绯荤粺妯″潡鏃ュ織绾у埆鎺у埗  -->
+	<logger name="com.ycl" level="info" />
+	<!-- Spring鏃ュ織绾у埆鎺у埗  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+	
+	<!--绯荤粺鎿嶄綔鏃ュ織-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+	
+	<!--绯荤粺鐢ㄦ埛鎿嶄綔鏃ュ織-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration> 
\ No newline at end of file

--
Gitblit v1.8.0