1、logback.xml
<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- APP NAME -->
<property name="APP_NAME" value="template" />
<!-- 日誌ROOT DIR -->
<property name="LOG_ROOT_DIR" value="Logs/${APP_NAME}"/>
<!-- 格式化輸出。
%d/date{HH:mm:ss.SSS}:輸出日誌的打印日誌,模式語法與java.text.SimpleDateFormat 兼容
%-5p/le/level:級別從左顯示5個字符寬度
%t/thread 輸出產生日誌的線程名。
%logger{36} 表示logger名字最長36個字符 爲0表示只輸入logger最右邊點符號之後的字符串
%F java源文件名 *.java
%L 行
%m/msg/message:日誌內容
%n:換行符 -->
<property name="ENCODER_PATTERN" value="%d{[yyyy-MM-dd HH:mm:ss]}[%level][%logger{1}:%L] %msg%n" />
<property name="ENCODING" value="UTF-8"/>
<contextName>${APP_NAME}</contextName>
<jmxConfigurator />
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- 輸出到控制檯 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="${ENCODING}">
<pattern>${ENCODER_PATTERN}</pattern>
</encoder>
</appender>
<!-- appender 是<configuration>的子節點,是負責寫日誌的組件。有兩個必要屬性name和class。name指定appender名稱,class指定appender的全限定名 -->
<appender name="TEMPLATE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 滾動記錄文件,先將日誌記錄到指定文件,當符合某個條件時,將日誌記錄到其他文件 -->
<file>${LOG_ROOT_DIR}/template.log</file>
<encoding>${ENCODING}</encoding>
<append>true</append> <!--true:日誌被追加到文件結尾,false:清空現存文件,默認是true-->
<encoder> <!-- 對記錄事件進行格式化 -->
<pattern>${ENCODER_PATTERN}</pattern>
</encoder>
<!--
過濾器,執行一個過濾器會有返回個枚舉值,即DENY,NEUTRAL,ACCEPT其中之一。
返回DENY,日誌將立即被拋棄不再經過其他過濾器;
返回NEUTRAL,有序列表裏的下個過濾器過接着處理日誌;
返回ACCEPT,日誌會被立即處理,不再經過剩餘過濾器。
-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch> <!--用於配置符合過濾條件的操作-->
<onMismatch>DENY</onMismatch> <!--用於配置不符合過濾條件的操作-->
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_ROOT_DIR}/template_%d{yyyy-MM-dd}.log.gz</fileNamePattern><!-- 壓縮後的文件名設置 -->
</rollingPolicy>
<!--日誌文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--日誌異步到數據庫 -->
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<!--日誌異步到數據庫 -->
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<!--連接池 -->
<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
<driverClass>com.mysql.jdbc.Driver</driverClass>
<url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
<user>root</user>
<password>root</password>
</dataSource>
</connectionSource>
</appender>
<!-- 郵件發送相關 -->
<property name="smtpHost" value="smtp.exmail.qq.com"/>
<property name="username" value="[email protected]"/>
<property name="smtpPort" value="25"/>
<property name="password" value="xx"/>
<property name="SSL" value="false"/>
<property name="email_to" value="[email protected]"/>
<property name="email_from" value="[email protected]"/>
<property name="email_subject" value="【Error:${APP_NAME}】%logger{20}:%L"/>
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>${smtpHost}</smtpHost>
<smtpPort>${smtpPort}</smtpPort>
<username>${username}</username>
<password>${password}</password>
<SSL>${SSL}</SSL>
<asynchronousSending>false</asynchronousSending>
<to>${email_to}</to>
<from>${email_from}</from>
<subject>${email_subject}</subject>
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%d{[yyyy-MM-dd HH:mm:ss]}[%level][%logger:%L] %msg</pattern>
</layout>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
</appender>
<!-- 郵件發送相關 -->
<root level="DEBUG">
<appender-ref ref="TEMPLATE_FILE"/>
<appender-ref ref="console"/>
<!--<appender-ref ref="DB"/>
<appender-ref ref="EMAIL"/>-->
</root>
<!-- 配置獨立包 -->
<logger name="com.alibaba.dubbo" level="WARN">
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="console"/>
</logger>
</configuration>
2、Controller
import com.saohuobang.payment.service.JMXConfigService;
import javax.annotation.Resource;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 作者 yaohua.liu
* 日期 2015-11-24 11:32
* 說明 日誌等級動態控制接口
*/
@RequestMapping(value = "/log")
@Controller
public class JMXConfigController extends BackdoorController{
@Resource
private JMXConfigService JMXConfigService;
@RequestMapping(value = "/startJMXConfig.api")
@ResponseBody
public Object startJMXConfig(@RequestParam(required = false) String port) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {
String result = JMXConfigService.startJMXConfig(port);
return result;
}
@RequestMapping(value = "/stopJMXConfig.api")
@ResponseBody
public Object stopJMXConfig() throws Exception {
String result = JMXConfigService.stopJMXConfig();
return result;
}
}
3、Service
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
/**
* 作者 yaohua.liu
* 日期 2015-11-25 13:50
* 說明 ...
*/
public interface JMXConfigService {
public String startJMXConfig(String port) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException;
public String stopJMXConfig() throws Exception;
}
4、impl實現
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.jmx.JMXConfigurator;
import com.google.common.base.Strings;
import com.saohuobang.payment.service.JMXConfigService;
import com.sun.jdmk.comm.HtmlAdaptorServer;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
* 作者 yaohua.liu
* 日期 2015-11-25 14:23
* 說明 ...
*/
@Service
public class JMXConfigServiceImpl implements JMXConfigService {
private Logger logger = LoggerFactory.getLogger(JMXConfigService.class);
public final String DOMAIN_NAME = "logback_jmx";
public final String RELOAD_CONFIG_NAME = "reloadConfig";
public final String CONNECTOR_NAME = "htmlConnector";
private MBeanServer mBeanServer;
private JMXConfigurator reloadConfig;
private HtmlAdaptorServer connector;
public LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
private int defaultPort = 10110;
@Override
public String startJMXConfig(String portStr) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {
mBeanServer = MBeanServerFactory.createMBeanServer(DOMAIN_NAME);
int port = 0;
try {
if (Strings.isNullOrEmpty(portStr)) {
port = defaultPort;
} else {
port = Integer.parseInt(portStr);
}
} catch (Exception e) {
logger.error("格式化JMX端口:{}失敗,使用默認端口:{}", portStr, defaultPort);
port = defaultPort;
}
// 註冊服務
ObjectName on = new ObjectName(DOMAIN_NAME + ":name=" + RELOAD_CONFIG_NAME);
reloadConfig = new JMXConfigurator(loggerContext, mBeanServer, on);
mBeanServer.registerMBean(reloadConfig, new ObjectName(DOMAIN_NAME + ":name=" + RELOAD_CONFIG_NAME));
// 註冊連接
connector = new HtmlAdaptorServer();
connector.setPort(port);
mBeanServer.registerMBean(connector, new ObjectName(DOMAIN_NAME + ":name=" + CONNECTOR_NAME));
connector.start();
return DOMAIN_NAME + ":" + port;
}
@Override
public String stopJMXConfig() throws Exception {
if (connector != null && connector.isActive()) {
connector.stop();
}
mBeanServer = null;
reloadConfig = null;
connector = null;
return "stop success!";
}
}
5、訪問:http://127.0.0.1:10001/log/startJMXConfig.api 返回:logback_jmx:10110,說明開通的端口爲10110
頁可以在請求時指定端口:http://127.0.0.1:10001/log/startJMXConfig.api?port=101010
6、打開地址:http://127.0.0.1:10110/
7、點擊name=reloadConfig,跳轉到:http://127.0.0.1:10110/ViewObjectRes//logback_jmx%3Aname%3DreloadConfig,滾動條拉到最下面,顯示及操作如下: