1.背景

在我们项目开发中,很多时候需要记录访问ip地址,方便跟踪操作日志定位是哪个机器访问了我们的服务(逮住证据),或者根据ip做一些分析统计。

那么使用springboot自带的logback如何记录客户端访问ip呢?下面详细说明。

2.重写日志规则方法记录ip

创建IPLogConfig类实现ClassicConverter类重写convert方法获取请求上下文返回ip,如下:

package com.bylz.api.config;import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.bylz.api.utils.IpUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;/*** Author: lizhi* Date: 2021-10-11* Describe: 日志输出ip配置*/
public class IPLogConfig extends ClassicConverter {@Overridepublic String convert(ILoggingEvent event) {RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();if (requestAttributes == null) {return "127.0.0.1";}HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();return IpUtils.getIpAddr(request);}
}

IpUtils工具类:

package com.bylz.api.utils;import com.google.common.base.Strings;import javax.servlet.http.HttpServletRequest;/*** @author lizhi* @version 1.0* @date 2021/8/31 11:33*/
public class IpUtils {private IpUtils(){}public static String getIpAddr(HttpServletRequest request) {String xIp = request.getHeader("X-Real-IP");String xFor = request.getHeader("X-Forwarded-For");if (!Strings.isNullOrEmpty(xFor) && !"unKnown".equalsIgnoreCase(xFor)) {//多次反向代理后会有多个ip值,第一个ip才是真实ipint index = xFor.indexOf(",");if (index != -1) {return xFor.substring(0, index);} else {return xFor;}}xFor = xIp;if (!Strings.isNullOrEmpty(xFor) && !"unKnown".equalsIgnoreCase(xFor)) {return xFor;}if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {xFor = request.getHeader("Proxy-Client-IP");}if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {xFor = request.getHeader("WL-Proxy-Client-IP");}if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {xFor = request.getHeader("HTTP_CLIENT_IP");}if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {xFor = request.getHeader("HTTP_X_FORWARDED_FOR");}if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {xFor = request.getRemoteAddr();}return "0:0:0:0:0:0:0:1".equals(xFor) ? "127.0.0.1" : xFor;}
}

3.配置logback-spring.xml打印ip

在日志配置xml文件中增加convert规则:

<!--配置规则类的位置-->
<conversionRule conversionWord="ip" converterClass="com.bylz.api.config.IPLogConfig" />

在日志打印模板中获取ip打印:

<property name="CONSOLE_LOG_PATTERN"value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%magenta(%ip) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>

完整日志打印配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="10 seconds"><!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 --><!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true --><!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 --><!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><contextName>logback</contextName><!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --><property name="log.path" value="/data/apps/qcloud-api/log" /><!--配置规则类的位置--><conversionRule conversionWord="ip" converterClass="com.bylz.api.config.IPLogConfig" /><!-- 彩色日志 --><!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 --><!-- magenta:洋红 --><!-- boldMagenta:粗红--><!-- cyan:青色 --><!-- white:白色 --><!-- magenta:洋红 --><property name="CONSOLE_LOG_PATTERN"value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%magenta(%ip) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/><!--输出到控制台--><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>DEBUG</level></filter><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!--输出到文件--><!-- 时间滚动输出 level为 INFO 日志 --><appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_info.log</file><!--日志文件输出格式--><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>UTF-8</charset></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志归档路径以及格式 --><fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录info级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 WARN 日志 --><appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_warn.log</file><!--日志文件输出格式--><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录warn级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>warn</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 ERROR 日志 --><appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_error.log</file><!--日志文件输出格式--><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录ERROR级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。name:用来指定受此logger约束的某一个包或者具体的某一个类。level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,如果未设置此属性,那么当前logger将会继承上级的级别。--><!--使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:--><!--开发环境:打印控制台--><springProfile name="dev"><!--可以输出项目中的debug日志,包括mybatis的sql日志--><!--<logger name="com.bylz.api.dao" level="DEBUG" />--><!--<logger name="com.bylz.api.controller.feign" level="DEBUG" />--><!--root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG可以包含零个或多个appender元素。--><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="ERROR_FILE" /></root></springProfile><!--测试环境:输出到文件--><springProfile name="test"><!--可以输出项目中的debug日志,包括mybatis的sql日志--><!--<logger name="com.bylz.api.dao" level="DEBUG" />--><!--<logger name="com.bylz.api.controller.feign" level="DEBUG" />--><root level="INFO"><appender-ref ref="CONSOLE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="ERROR_FILE" /></root></springProfile><!--生产环境:输出到文件--><springProfile name="prod"><!--可以输出项目中的debug日志,包括mybatis的sql日志--><!--<logger name="com.bylz.api.dao" level="DEBUG" />--><!--<logger name="com.bylz.api.controller.feign" level="DEBUG" />--><root level="INFO"><appender-ref ref="ERROR_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="INFO_FILE" /></root></springProfile></configuration>

4.日志输出如下

springboot项目日志记录访问客户端ip地址相关推荐

  1. springboot项目引用QQWry.Dat解析IP地址

    引入ipseek 代码包 /*** * 封装ip相关信息,目前只有两个字段,ip所在的国家和地区*/ public class IPLocation {private String country = ...

  2. Filebeat 输出日志时添加客户端 IP 地址(引用变量)

    推荐阅读 Helm3(K8S 资源对象管理工具)视频教程:https://edu.csdn.net/course/detail/32506 Helm3(K8S 资源对象管理工具)博客专栏:https: ...

  3. 在ASP.NET Core中获取客户端IP地址

    随着ASP.NET的发展,有不同的方式从请求中访问客户端IP地址.WebForms和MVC Web应用程序只是访问当前HTTP上下文的请求. var ip = HttpContext.Current. ...

  4. apache关于记录真实客户端ip和不记录健康检查日志

    由于负载均衡会转发客户端的请求到web服务器,所以web服务往往记录的是负载均衡的IP,现在可以通过下面的配置,让apache记录真实客户端IP 语法 #LogFormat  "\" ...

  5. springboot 获取客户端ip_JAVA如何获取客户端IP地址和MAC地址

    本文介绍了JAVA如何获取客户端IP地址和MAC地址 ,分享给大家,具体如下: 1.获取客户端IP地址 public String getIp(HttpServletRequest request) ...

  6. 网站配置了Cloudflare代理后,如何配置Nginx获取的真实客户端IP地址?

    网站配置了Cloudflare代理后,如何配置Nginx获取的真实客户端IP地址? 这是一个很简单的问题,如何在后台获取真实的访问者IP地址? 网站为了避免有些不怀好意的访问者,不得不自动分析一下客户 ...

  7. HAProxy客户端IP地址的透传

    HAProxy客户端IP地址的透传 环境准备 server IP client 172.20.27.10 haproxy 172.20.27.20,192.168.27.10 nginx 192.16 ...

  8. Nginx在多层代理下获取真实客户端IP地址

    最近在研究nginx中如何获取真实客户端IP的方法.众所周知,在编译Nginx时,可通过添加http_realip_module模块来获取真实客户端IP地址.何为真实IP地址呢?请看下图,既获取到的真 ...

  9. 学习笔记 - Nginx在多层代理下获取真实客户端IP地址

    最近在研究nginx中如何获取真实客户端IP的方法.众所周知,在编译Nginx时,可通过添加http_realip_module模块来获取真实客户端IP地址.何为真实IP地址呢?请看下图,既获取到的真 ...

最新文章

  1. 【VS开发】【DSP开发】WinDriver简介(或介绍)
  2. python矩阵分解
  3. react+express+mongodb搭建个人博客
  4. 搜狗浏览器智慧版_奥维互动地图浏览器下载_奥维互动地图浏览器64位版v7.1.2
  5. 智能音箱 之 麦克风参数介绍
  6. python调用c++深度学习模型生成的dll(传入图片,返回多个结果)
  7. Rust: codewars的DNA to RNA Conversion
  8. 面试技巧——程序员简历模板
  9. 大泥王怎么调时区_卡西欧大泥王功能教学及怎么调时间
  10. autocad2007二维图画法_AutoCAD 2007矩形绘制方法教程
  11. html svg 线条动画,HTML5 SVG简单的动态绘制轮廓线条动画插件
  12. android 渐变蒙版_css3 渐变、蒙版
  13. 研究生师兄谈SCI论文写作心得
  14. 让你彻悟人生的555句金玉良言
  15. 被黑的SNES是一款多合一的复古游戏机
  16. 7.1 RAID(独立冗余磁盘阵列)
  17. iOS12 系统 webView加载H5页面,反复点击网页中视频播放 退出视频全屏 闪退解决方式。
  18. 这届618:掀起直播盛世
  19. File.separator 详解
  20. Java经典入门教程!java工程师的进阶之路

热门文章

  1. 【通刷】_晶晨S905L3A、S905L3AB芯片_安卓9.0_AI语音_完美线刷固件包
  2. 树莓派3B+安装Android 系统
  3. vscode 用户设置与工作区设置
  4. 连上WiFi就能打电话?“手机营业厅”中的神奇功能火了
  5. PHP 常用英语精简1
  6. 用户登录功能以及登录拦截
  7. 项目3-分数类中的运算符重载
  8. 语句摘抄——第16周
  9. java中有测试方法主方法不运行_java – 我的Eclipse无法再运行(或调试)我的JUnit测试...
  10. C#/音乐播放器/带进度条/歌词滚动、颜色变化/桌面应用程序设计