<?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. 自动出借-python+selenium

    自动出借 import time from selenium import webdriver # import os #B username = " # 请替换成你的用户名 passwor ...

  2. 根据白名单过滤 HTML(防止 XSS 攻击)

    https://github.com/leizongmin/js-xss/blob/master/README.zh.md 根据白名单过滤 HTML(防止 XSS 攻击) xss是一个用于对用户输入的 ...

  3. rosetta mpi编译时出现 MPI has not been declared 错误

    安装openmpi2.1.0版本,编译mpi rosetta时出现 MPI has not been declared 错误,经过一系列的摸索发现安装openmpi-1.6.5就可以顺利编译,降低版本 ...

  4. ASP.Net Core 2.2 MVC入门到基本使用系列 (四)(转)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  5. xml--myeclipse用快捷键注释xml语句

    7.5以上版本才可以ctrl+shift+/ 撤销注释:CTRL + SHIFT + \ 参考:https://blog.csdn.net/tengdazhang770960436/article/d ...

  6. C++ new运算符

    new 分配的数据类型:内置数据类型.自定义数据类型. 如果不成功,则 new 将返回零或引发异常:编写自定义异常处理例程并调用 _set_new_handler运行库函数(以您的函数名称作为其参数) ...

  7. spring之继承配置

    我们有一下两个类,并且Gradate类继承了Student类 public class Student public class Gradate extends Student 在applicatio ...

  8. Swift 了解(3)

    类(Classes) 假设你是一个建筑师,你刚刚签了一个合同,要在一个新的小区修建20个相似的房子.在你派出建筑工队之前,你必须要画一个房子的设计图.这份设计图将会展现房子的外表和功能.把这份设计图当 ...

  9. MVC请求管道

    下面是请求管道中的19个事件. (1)BeginRequest: 开始处理请求 (2)AuthenticateRequest授权验证请求,获取用户授权信息 (3):PostAuthenticateRe ...

  10. XML系列之--创建电文格式的XML(一)

    关于XML,学校那会,老师在口中仅仅提及,自己也未曾深入接触过,仅是些将最基本XML文件内容显示在web定义的表格中之类的简单操作,如今项目中的收发电文涉及到复杂XML的操作.趁此契机好好回顾下XML ...