logback + jms + spring
一、先与spring集成
logback与spring集成,由于spring使用log4j输出日志,所以需要把log4j的输出重新输出到logback。
需要以下几个jar包:
log4j-over-slf4j jar --需要注意最后的版本号,要与slf-api jar 对应
jcl-over-slf4j jar --需要注意最后的版本号,要与slf-api jar 对应
上面两个jar包可以把log4j 和 logging 的日志输入转发到logback。
需要实现三个spring支持类:(见 -号 分割线以下)
还需要在l中配置加载
<!-- logback spring 配置 begin -->
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>/l</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.LogbackConfigListener</listener-class>
</listener>
<!-- logback spring 配置 end -->
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LogbackConfigurer.java
====================================================================================
package org.springframework.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.URL;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.joran.spi.JoranException;
/**
*
* @author piaohailin
*
*/
public abstract class LogbackConfigurer {
/** Pseudo URL prefix for loading from the class path: "classpath:" */
public static final String CLASSPATH_URL_PREFIX = "classpath:";
/** Extension that indicates a logback XML config file: ".xml" */
public static final String XML_FILE_EXTENSION = ".xml";
private static LoggerContext lc = (LoggerContext) ILoggerFactory();
private static JoranConfigurator configurator = new JoranConfigurator();
/**
* Initialize logback from the given file location, with no config file refreshing. Assumes an XML file in case of a ".xml" file extension, and a properties file otherwise.
*
* @param location
* the location of the config file: either a "classpath:" location (e.g. "classpath:mylogback.properties"), an absolute file URL (e.g. "file:C:/logback.properties), or a plain absolute path in the file system (e.g. "C:/logback.properties")
* @throws FileNotFoundException
* if the location specifies an invalid file path
*/
public static void initLogging(String location) throws FileNotFoundException {
String resolvedLocation = solvePlaceholders(location);
URL url = URL(resolvedLocation);
if (LowerCase().endsWith(XML_FILE_EXTENSION)) {
configurator.setContext(lc);
try {
configurator.doConfigure(url);
} catch (JoranException ex) {
throw new Path());
}
lc.start();
}
}
/**
* Shut down logback, properly releasing all file locks.
* <p>
* This isn't strictly necessary, but recommended for shutting down logback in a scenario where the host VM stays alive (for example, when shutting down an application in a J2EE environment).
*/
public static void shutdownLogging() {
lc.stop();
}
/**
* Set the specified system property to the current working directory.
* <p>
* This can be for test environments, for applications that leverage logbackWebConfigurer's "webAppRootKey" support in a web environment.
*
* @param key
* system property key to use, as expected in logback configuration (for example: "", used as "${}/WEB-INF/demo.log")
* @see org.springframework.web.util.logbackWebConfigurer
*/
public static void setWorkingDirSystemProperty(String key) {
System.setProperty(key, new File("").getAbsolutePath());
}
}
LogbackConfigListener.java
=====================================================================================================
package org.springframework.web.util;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
*
* @author piaohailin
*
*/
public class LogbackConfigListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
LogbackWebConfigurer.ServletContext());
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LogbackWebConfigurer.ServletContext());
}
}
LogbackWebConfigurer.java
===================================================================================================================
package org.springframework.web.util;
import java.io.FileNotFoundException;
import javax.servlet.ServletContext;
import org.springframework.util.LogbackConfigurer;
import org.springframework.util.ResourceUtils;
import org.springframework.util.SystemPropertyUtils;
public abstract class LogbackWebConfigurer {
/** Parameter specifying the location of the logback config file */
public static final String CONFIG_LOCATION_PARAM = "logbackConfigLocation";
/** Parameter specifying the refresh interval for checking the logback config file */
public static final String REFRESH_INTERVAL_PARAM = "logbackRefreshInterval";
/** Parameter specifying whether to expose the web app root system property */
public static final String EXPOSE_WEB_APP_ROOT_PARAM = "logbackExposeWebAppRoot";
/
**
* Initialize logback, including setting the web ap
p root system property.
*
* @param servletContext
* the current ServletContext
* @see WebUtils#setWebAppRootSystemProperty
*/
public static void initLogging(ServletContext servletContext) {
// Expose the web app root system property.
if (exposeWebAppRoot(servletContext)) {
WebUtils.setWebAppRootSystemProperty(servletContext);
}
// Only perform custom logback initialization in case of a config file.
String location = InitParameter(CONFIG_LOCATION_PARAM);
if (location != null) {
// Perform actual logback initialization; else rely on logback's default initialization.
try {
// Return a URL (e.g. "classpath:" or "file:") as-is;
// consider a plain file path as relative to the web application root directory.
if (!ResourceUtils.isUrl(location)) {
// Resolve system property placeholders before resolving real path.
location = solvePlaceholders(location);
location = RealPath(servletContext, location);
}
// Write log message to server log.
servletContext.log("Initializing logback from [" + location + "]");
// Initialize without refresh check, i.e. without logback's watchdog thread.
LogbackConfigurer.initLogging(location);
} catch (FileNotFoundException ex) {
throw new IllegalArgumentException("Invalid 'logbackConfigLocation' parameter: " + ex.getMessage());
}
}
}
/**
* Shut down logback, properly releasing all file locks and resetting the web app root system property.
*
* @param servletContext
* the current ServletContext
* @see WebUtils#removeWebAppRootSystemProperty
*/
public static void shutdownLogging(ServletContext servletContext) {
servletContext.log("Shutting down logback");
try {
LogbackConfigurer.shutdownLogging();
} finally {
// Remove the web app root system property.
if (exposeWebAppRoot(servletContext)) {
}
}
}
/**
* Return whether to expose the web app root system property, checking the corresponding ServletContext init parameter.
*
* @see #EXPOSE_WEB_APP_ROOT_PARAM
*/
private static boolean exposeWebAppRoot(ServletContext servletContext) {
String exposeWebAppRootParam = InitParameter(EXPOSE_WEB_APP_ROOT_PARAM);
return (exposeWebAppRootParam == null || Boolean.valueOf(exposeWebAppRootParam));
}
}
二、与jms集成
采用jms的开源实现 activeMQ 。
为什么要把日志输出到jms?
1.在集项目中,应用需要部署到多台服务器上,如果还使用文件系统做为日志输出,每一台服务器上的日志都需要处理,管理很麻烦;
2.集应用中,如果每个应用都单独记录日志,不利于对整个集的管理,把所有服务器的日志都统一记录到一个地方,可以方便地知道每一台服务器的运行情况;
3.统一的日志记录,常用的有三种方式:数据库、socket、消息服务器;
4.消息服务器(比如jms),异步接收的方式很适合日志记录,日志输出不会被阻塞,所以记录日志也不会影响到系统性能;
5.使用topic方式传输日志,单条日志也可以有多个接收者,可以方便地扩展日志分析程序。
需要的jar包:
activeMQ提供了一个activemq-all-xx.jar,但是包中的log4j模块与logback有冲突;
当使用slf4j-api控制日志输出时,LoggerFactory会按照类加载顺序加载具体的日志实现,当先加载logback时,一切都很美好,如果每加载了activemq-all包中的log4j,就会使logback失效,而且不能正常获取Logger对象。(从slf4j的日志输出可看到加载顺序)
可以只加载以下jar包:
activemq-core-5.7.0.jar
activemq-web-5.7.0.jar
geronimo-j2ee-management_1.1_spec-1.0.1.jar
geronimo-jms_1.1_spec-1.1.1.jar
logback配置:
<!-- 输出到文件 jms -->
<appender name="jms" class="ch.qos.logback.classic.JMSQueueAppender">
<InitialContextFactoryName>
org.apache.activemq.jndi.ActiveMQInitialContextFactorylog4j2配置多个日志文件
</InitialContextFactoryName>
<ProviderURL>tcp://localhost:61616</ProviderURL>
<QueueConnectionFactoryBindingName>ConnectionFactory</QueueConnectionFactoryBindingName>
<!-- 增加 dynamicQueues/ 前缀,可以省去activeMQ的jndi.properties文件 -->
<QueueBindingName>dynamicQueues/test</QueueBindingName>
</appender>
<!-- 输出到文件 jms -->
参考代码:jms日志的输出监听
@Override
public void onMessage(Message msg) {
ObjectMessage om = (ObjectMessage) msg;
Object o = null;
try {
o = om.getObject();
LoggingEventVO le = (LoggingEventVO) o;
//%-5level %d{yyyy-MM-dd HH:mm:ss} [%thread] %logger %line ---> %m
System.out.println(String.format("%-5s %s [%s] %s ---> %s",
if (le.getThrowableProxy() != null) {
System.out.println("-->" + ThrowableProxyUtil.ThrowableProxy()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论