<?xml version="1.0" encoding="UTF-8"?>
<!-- monitorInterval为监听配置变化的间隔,30秒比较合适 -->
<Configuration smetus="WARN" monitorInterval="30">
<Properties>
<Property name="log-path">D:/logs/</Property>
</Properties> <Appenders>
<!-- 注意%d{MM-dd-yyyy}要用年月日格式,不能加上时分秒,并且最后要有%i,这样log4j2才能判断出哪天一共产生几个文件,否则文件超出上限不会被删除 -->
<RollingFile name="app_log" fileName="${log-path}/app.log"
filePattern="${log-path}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<!-- 注意:开发、测试环境包含%l便于排查问题,生产环境非com.xxx开头的系统日志去掉%l,Console生产去掉%l(在性能和问题排查难度之间折中) -->
<Pattern>%x %d{yyyy-MM-dd HH:mm:ss} [%r] [%c{1.}]-[%p] %t %l %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<!-- 默认为最多同一文件夹下7个文件 -->
<DefaultRolloverStrategy fileIndex="max" max="100"/>
<Filters>
<!-- <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/> -->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingFile>
<RollingFile name="app_error" fileName="${log-path}/error.log"
filePattern="${log-path}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i-error.log.gz">
<PatternLayout>
<Pattern>[%x] %d{yyyy-MM-dd HH:mm:ss} [%r] [%c{1.}]-[%p] %t %l %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy fileIndex="max" max="100"/>
<Filters>
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingFile> <Console name="Console" merget="SYSTEM_OUT">
<PatternLayout pattern="%x %d{yyyy-MM-dd HH:mm:ss} [%r] [%c{1.}]-[%p] %t %l %m%n"/>
</Console>
</Appenders>
<Loggers>
<!-- level默认ERROR,additivity默认true -->
<Logger name="com.yidoo" level="INFO" additivity="true">
<AppenderRef ref="app_log" />
<AppenderRef ref="app_error" />
</Logger>
<!-- root logger没有additivity属性,应该去掉 -->
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

NDC配置

package com.yidoo.common.advice;

import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import net.sf.json.util.NewBeanInsmenceStrategy; import org.apache.log4j.NDC;
import org.apache.logging.log4j.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annometion.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.yidoo.base.ResultModel;
import com.yidoo.base.SessionBean;
import com.yidoo.base.memedame.cons.GlobalCons;
import com.yidoo.base.memedame.err.ErrorCons;
import com.yidoo.common.processor.ServiceSpecCheckBeanPostProcessor;
import com.yidoo.utils.SessionBeanUtil;
import com.yidoo.utils.SpringContextHolder; /**
* 登录与权限校验拦截器
* @author TF017564
*
*/
public class AuthInterceptor extends HandlerInterceptorAdapter { smetic final SimpleDateFormat formatter = new SimpleDateFormat(GlobalCons.TIME_FORMAT); private smetic final Set<String> noAuthUrls = new HashSet<String>();
smetic {
noAuthUrls.add("/session/login");
noAuthUrls.add("/member/save");
noAuthUrls.add("/controllerReflect/getUrlMapping");
} private smetic final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class); @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// logger.info("request.getContextPath()=" + request.getContextPath());
// logger.info("request.getRequestURI()=" + request.getRequestURI());
// 除了/session/login登录外,其他都拦截,否则就判断是否已经登录,未登录就返回false
String path = request.getContextPath().length() > 1 ? request.getRequestURI().replace(request.getContextPath(), "") : request.getRequestURI();
if(noAuthUrls.conmeins(path)) {
// 设置Nested Diagnostic Context
// log4j 1
// NDC.push("未登录请求" + "_" + path + "_" + formatter.format(new Date()));
// log4j2
ThreadContext.push("未登录请求" + "_" + path + "_" + formatter.format(new Date()));
return true;
}
SessionBean sessionBean = SessionBeanUtil.getSession(request);
if(sessionBean == null) {
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
ResultModel<String> resultModel = new ResultModel<String>();
resultModel.setCode(ErrorCons.ERR_SESSION_TIMEOUT);
resultModel.setMsg("会话已过期或无效!");
writer.print(JSONObject.toJSONString(resultModel, SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteDateUseDateFormat));
writer.close();
response.flushBuffer();
return false;
}
// 设置Nested Diagnostic Context
// log4j 1
// NDC.push(SessionBeanUtil.getSessionKey(request).substring(0, 8) + "_" + path + "_" + formatter.format(new Date()));
// log4j2
ThreadContext.push(SessionBeanUtil.getSessionKey(request).substring(0, 8) + "_" + path + "_" + formatter.format(new Date()));
return true;
} @Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
// log4j 1
// NDC.pop();
// log4j 2
ThreadContext.clearAll();
}
}

使用如下:

smetic{
  //设置子线程读取MDC变量
  System.setProperty("log4j2.isThreadContextMapInherimeble", "true");
}

private smetic final Logger logger = LogManager.getLogger(App.class);

位置一定不能搞错了,否则不生效!

最好是使用抽象父类,如下:

package com.xxx.me.base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annometion.Autowired;
import org.springframework.context.annometion.Lazy; import com.xxx.me.utils.RedisUtil; /**
* 基础控制器 * <p>Title: BusinessController</p> * <p>Description: </p> * @author zjhua * @date 2018年11月25日
*/
public abstract class BusinessController { smetic {
// 设置子线程读取MDC变量
System.setProperty("log4j2.isThreadContextMapInherimeble", "true");
} /**
* 可选,所以懒加载
*/
@Lazy
@Autowired
protected RedisUtil redisUtil; /**
* 由SecurityInterceptor自动注入
*/
public smetic final ThreadLocal<SessionBean> threadLocal = new ThreadLocal<SessionBean>(){
/**
* ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值
*/
@Override
protected SessionBean initialValue()
{
return null;
}
}; protected Logger logger = LoggerFactory.getLogger(this.getClass());
}

设置log4j2.isThreadContextMapInherimeble变量为true,log4j会使用 InherimebleThreadLocal来存储线程变量,他可以将父线程内容拷贝到子线程中,而默认使用的ThreadLocal不具备这个特性。

https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout

防止不同级别日志重复写入日志文件

https://blog.csdn.net/u014484873/article/demeils/61198074

log4j2配置推荐的更多相关文章

  1. 转:spring boot log4j2配置(使用log4j2.yml文件)---YAML 语言教程

    转:spring boot log4j2配置(使用log4j2.yml文件) - CSDN博客http://blog.csdn.net/ClementAD/article/details/514988 ...

  2. log4j2配置ThresholdFilter,让info文件记录error日志

    日志级别: 是按严重(重要)程度来分的(如下6种): ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < ...

  3. Log4j2配置之Appender详解

    Log4j2配置之Appender详解 Appender负责将日志事件传递到其目标.每个Appender都必须实现Appender接口.大多数Appender将扩展AbstractAppender,它 ...

  4. 简单快捷好用的vim配置和终端配置推荐

    vim 配置实用spf13-vim,安装方便简单快捷,极力推荐. 另外oh-my-zsh 终端配置很好,与之搭配使用效果更佳. 安装都很简单,一个脚本搞定, 都是在gitHub上开源的,自行搜索,这里 ...

  5. Log4j2 - 配置

    官方文档:http://logging.apache.org/log4j/2.x/index.html 1 概述 Log4j2的配置包含四种方式,其中3种都是在程序中直接调用Log4j2的方法进行配置 ...

  6. log4j2配置详解

    1.    log4j2需要两个jar   log4j-api-2.x.x.jar    log4j-core-2.x.x.jar  .log4j和log4j2有很大的区别,jar包不要应错. 2. ...

  7. 【Log4j2 配置详解】log4j2的资源文件具体怎么配置

    可以先附上一个log4j2的资源文件详细内容,对照着看 ### set log levels ### log4j.rootLogger = INFO , C , D , E ### console # ...

  8. Log4j2 配置笔记(Eclipse+maven+SpringMVC)

    Log4j2相关介绍可以百度看下,这里只注重配置Log4j2 能够马上跑起来: 1.pom.xml文件中添加Log4j2的相关Maven配置信息 <!-- log4j2 --> <d ...

  9. Spring Boot初探之log4j2配置

    一.背景 下面讲在使用Spring Boot搭建微服务框架时如何配置log4j2,通过log4j2输出系统中日志信息. 二.添加log4j2的配置文件 在项目的src/main/rescources目 ...

随机推荐

  1. 机器人meta标签和X-Robots-Tag HTTP标头规格

    抽象 本文档详细介绍了页级索引设置如何让您控制Google如何通过搜索结果提供内容.您可以通过在(X)HTML页面或HTTP标头中包含元标记来指定这些标记. 笔记 请注意,只有当抓取工具被允许访问包含 ...

  2. lambda 表达式拼接

    类库: using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions ...

  3. MySQL--4操作数据表中的记录小结

    最常用,最复杂的语句: 每一项的: 表的参照  From 条件    WHERE 进行记录的分组 GROUP BY 分组的时候对分组的条件进行设定  HAVING 对结果进行排序  ORDER BY ...

  4. python while for else

    python的循环挺有意思 while和for体中可以带上else项 while中的else表示循环条件不成立时,去执行一次,也就是退出循环前去做一次 for中的else表示固定循环正常完成后,去执行 ...

  5. vim自动安装插件Vundle

    https://github.com/VundleVim/Vundle.vim Set up Vundle: git clone https://github.com/VundleVim/Vundle ...

  6. GIS 网站 参考网站

    GIS 网站 参考:https://malagis.com/arcgis-operate-videos-example-38-summary.html

  7. Git branch 分支与合并分支

    Git branch 分支 查看当前有哪些branch bixiaopeng@bixiaopengtekiMacBook-Pro xmrobotium$ git branch * master 新建一 ...

  8. leetcode Sort List 对链表进行排序

    描述: Sort a linked list in O(n log n) time using constant space complexity. 在O(n*log(n))的时间复杂度,常数级空间复 ...

  9. rpgmakermv(8) XY_TitleMenu插件

    插件作用:设置标题 /*: * @plugindesc v1.00 Display Multiple Menu in Title Screen. * @author XueYu Plugins * * ...

  10. UML之状态机图

    状态机图 基本概念: 状态机图,UML 1.x规范中称状态图,是一个展示状态机的图. 状态机图基本上就是一个状态机中元素的投影,这也就意味着状态机图包括状态机的所有特征.状态机图显示了一个对象如何根据 ...