动态调整(springMVC+slf4j)log等级(DEBUG/INFO/WARN/ERROR)

来源:互联网 发布:java多线程异常处理 编辑:程序博客网 时间:2024/04/30 02:52


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="xx@xx.com"/>    <property name="smtpPort" value="25"/>    <property name="password" value="xx"/>    <property name="SSL" value="false"/>    <property name="email_to" value="xx@xx.com"/>    <property name="email_from" value="xx@xx.com"/>    <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")@Controllerpublic 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 * 说明 ... */@Servicepublic 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,滚动条拉到最下面,显示及操作如下:






1 0