MySQL优化
一、SQL语句优化 (1)使用limit对查询结果的记录进行限定 (2)避免select *,将需要查找的字段列出来 (3)使用连接(join)来代替子查询 (4)拆分大的delete或insert语句 二、选择合适的数据类型 (1)使用可存下数据的最小的数据类型,整型 < date,time < char,varchar < blob (2)使用简单的数据类型,整型比字符处理开销更小,因为字符串的比较更复杂。如,int类型存储时间类型,bigint类型转ip函数 (3)使用合理的字段属性长度,固定长度的表会更快。使用enum、char而不是varchar (4)尽可能使用not null定义字段 (5)尽量少用text,非用不可最好分表 三、选择合适的索引列 (1)查询频繁的列,在where,group by,order by,on从句中出现的列 (2)where条件中<,<=,=,>,>=,between,in,以及like 字符串+通配符(%)出现的列 (3)长度小的列,索引字段越小越好,因为数据库的存储单位是页,一页中能存下的数据越多越好 (4)离散度大(不同的值多)的列,放在联合索引前面。查看离散度,通过统计不同的列值来实现,count越大,离散程度越高:
1 |
mysql> SELECT COUNT(DISTINCT column_name) FROM table_name; |
四、使用命令分析 (1)SHOW查看状态 1.显示状态信息
1 |
mysql> SHOW [SESSION|GLOBAL] STATUS LIKE '%Status_name%'; |
session(默认):取出当前窗口的执行 global:从mysql启动到现在 (a)查看查询次数(插入次数com_insert、修改次数com_insert、删除次数com_delete)
1 |
mysql> SHOW STATUS LIKE 'com_select'; |
(b)查看连接数(登录次数)
1 |
mysql> SHOW STATUS LIKE 'connections'; |
(c)数据库运行时间
1 |
mysql> SHOW STATUS LIKE 'uptime'; |
(d)查看慢查询次数
1 |
mysql> SHOW STATUS LIKE 'slow_queries'; |
(e)查看索引使用的情况:
1 |
mysql> SHOW STATUS LIKE 'handler_read%'; |
handler_read_key:这个值越高越好,越高表示使用索引查询到的次数。 handler_read_rnd_next:这个值越高,说明查询低效。 2.显示系统变量
1 |
mysql> SHOW VARIABLES LIKE '%Variables_name%'; |
3.显示InnoDB存储引擎的状态
1 |
mysql> SHOW ENGINE INNODB STATUS; |
(2)EXPLAIN分析查询
1 |
mysql> EXPLAIN SELECT column_name FROM table_name; |
explain查询sql执行计划,各列含义: table:表名; type:连接的类型 -const:主键、索引; -eq_reg:主键、索引的范围查找; -ref:连接的查找(join) -range:索引的范围查找; -index:索引的扫描; -all:全表扫描; possible_keys:可能用到的索引; key:实际使用的索引; key_len:索引的长度,越短越好; ref:索引的哪一列被使用了,常数较好; rows:mysql认为必须检查的用来返回请求数据的行数; extra:using filesort、using temporary(常出现在使用order by时)时需要优化。 -Using filesort 额外排序。看到这个的时候,查询就需要优化了 -Using temporary 使用了临时表。看到这个的时候,也需要优化 (3)PROFILING分析SQL语句 1.开启profile。查看当前SQL执行时间
1 2 |
mysql> SET PROFILING=ON; mysql> SHOW profiles; |
2.查看所有用户的当前连接。包括执行状态、是否锁表等
1 |
mysql> SHOW processlist; |
(4)PROCEDURE ANALYSE()取得建议 通过分析select查询结果对现有的表的每一列给出优化的建议
1 |
mysql> SELECT column_name FROM table_name PROCEDURE ANALYSE(); |
(5)OPTIMIZE TABLE回收闲置的数据库空间
1 |
mysql> OPTIMIZE TABLE table_name; |
[…]
View DetailsMySQL索引类型
一、简介 MySQL目前主要有以下几种索引类型: 1.普通索引 2.唯一索引 3.主键索引 4.组合索引 5.全文索引 二、语句
1 2 |
CREATE TABLE table_name[col_name data type] [unique|fulltext][index|key][index_name](col_name[length])[asc|desc] |
1.unique|fulltext为可选参数,分别表示唯一索引、全文索引 2.index和key为同义词,两者作用相同,用来指定创建索引 3.col_name为需要创建索引的字段列,该列必须从数据表中该定义的多个列中选择 4.index_name指定索引的名称,为可选参数,如果不指定,默认col_name为索引值 5.length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度 6.asc或desc指定升序或降序的索引值存储 三、索引类型 1.普通索引 是最基本的索引,它没有任何限制。它有以下几种创建方式: (1)直接创建索引
1 |
CREATE INDEX index_name ON table(column(length)) |
(2)修改表结构的方式添加索引
1 |
ALTER TABLE table_name ADD INDEX index_name ON (column(length)) |
(3)创建表的时候同时创建索引
1 2 3 4 5 6 7 8 |
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER NOT NULL , `content` text CHARACTER NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), INDEX index_name (title(length)) ) |
(4)删除索引
1 |
DROP INDEX index_name ON table |
2.唯一索引 与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式: (1)创建唯一索引
1 |
CREATE UNIQUE INDEX indexName ON table(column(length)) |
(2)修改表结构
1 |
ALTER TABLE table_name ADD UNIQUE indexName ON (column(length)) |
(3)创建表的时候直接指定
1 2 3 4 5 6 7 |
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER NOT NULL , `content` text CHARACTER NULL , `time` int(10) NULL DEFAULT NULL , UNIQUE indexName (title(length)) ); |
3.主键索引 是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引:
1 2 3 4 5 |
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) NOT NULL , PRIMARY KEY (`id`) ); |
4.组合索引 指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合
1 |
ALTER TABLE `table` ADD INDEX name_city_age (name,city,age); |
5.全文索引 主要用来查找文本中的关键字,而不是直接与索引中的值相比较。fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的where语句的参数匹配。fulltext索引配合match against操作使用,而不是一般的where语句加like。它可以在create table,alter table ,create index使用,不过目前只有char、varchar,text 列上可以创建全文索引。值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE index创建fulltext索引,要比先为一张表建立fulltext然后再将数据写入的速度快很多。 (1)创建表的适合添加全文索引
1 2 3 4 5 6 7 8 |
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER NOT NULL , `content` text CHARACTER NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), FULLTEXT (content) ); |
(2)修改表结构添加全文索引
1 |
ALTER TABLE article ADD FULLTEXT index_content(content) |
(3)直接创建索引
1 |
CREATE FULLTEXT INDEX index_content ON article(content) |
四、缺点 1.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行insert、update和delete。因为更新表时,不仅要保存数据,还要保存一下索引文件。 2.建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会增长很快。 索引只是提高效率的一个因素,如果有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。 五、注意事项 使用索引时,有以下一些技巧和注意事项: 1.索引不会包含有null值的列 只要列中包含有null值都将不会被包含在索引中,复合索引中只要有一列含有null值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为null。 2.使用短索引 对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。 3.索引列排序 查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。 4.like语句操作 一般情况下不推荐使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。 5.不要在列上进行运算 这将导致索引失效而进行全表扫描,例如
1 |
SELECT * FROM table_name WHERE YEAR(column_name)<2017; |
6.不使用not in和<>操作 from:https://www.cnblogs.com/luyucheng/p/6289714.html
View Details使用URLScan隐藏IIS服务器Server头信息
百度搜索 URLScan V3.1,进行软件下载,根据操作系统版本,有32和64位的区分,如下图所示: 以管理员身份运行对应版本的软件,然后勾选“I accept the terms in the License Agreement”,然后点击“Install”,如下图所示: 直至安装完成,点击“Finish”,如下图所示: 我们在浏览器中打开Server服务器上部署的Web应用,然后通过fiddler软件进行查看Header头信息,可以看到Server:Microsoft-IIS/7.5,如下图所示: 此时我们打开URLScan默认安装路径C:\Windows\System32\inetsrv\urlscan,找到UrlScan.ini文件,如下图所示: 使用记事本工具打开UrlScan.ini文件,找到RemoveServerHeader=0配置节然后修改为RemoveServerHeader=1,最后保存文件,如下图所示: 此时重新启动下服务器上的IIS服务,打开命令提示符,输入iisreset即可,如下图所示: 此时我们刷新Web应用地址,重新使用fiddler进行Header信息观察,现在就看不到Server这个Header头配置信息了,如下图所示: from:https://jingyan.baidu.com/article/6d704a1379629a28db51ca37.html urscanV3.1下载
View Details解决 spring boot devtool 热部署后出现访问404问题
DevTools的检测时间和idea的编译所需时间存在差异。在idea还没完成编译工作前,DevTools就开始进行重启和加载,导致@RequestMapping没有被全部正常处理。其他方法没试,就直接用了看起来最简单的方法:牺牲一点时间,去加长devtools的轮询时间,增大等待时间。 解决方案如下: spring.devtools.restart.poll-interval=3000ms spring.devtools.restart.quiet-period=2999ms from:https://www.cnblogs.com/yxfcnbg/p/11510426.html
View Details把object转成JSONObject JSON.toJSON
把object转成JSONObject JSON.toJSON public void onNext(Object o) { LogUtil.i("getFavorites", "json=" + o.toString()); JSONObject json = JSON.parseObject(o.toString()); // JSONObject json = JSON.parseObject("{\"code\":1001,\"timestamp\":\"2018-11-05 03:40:54\"}"); LogUtil 的可以打印o.toString() 出来,直接传字符串解析json可以获得属性值,为什么JSONObject json = JSON.parseObject(o.toString()); 就报错了?强制转换也报错,把object转成JSONObject 这种要怎么用的? 或者怎么把Object o 这个对象里面的属性值读出来的? 怎么变成字符串的? public interface ObserverResponseListener<T> { void onNext(T t); 传进来的Object是个泛型的 JSONObject json = (JSONObject) JSON.toJSON(o); 用这样可以了 from:https://www.cnblogs.com/zdz8207/p/java-object-JSONObject.html
View Detailsjava 遍历数组常见的3种方式
1.for循环,最常见 2.利用foreach 3.利用jdk自带的方法 --> java.util.Arrays.toString() from:https://www.cnblogs.com/baiaixing/p/11369514.html
View DetailsX-Frame-Options响应头配置详解
X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 <frame>, </iframe> 或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌套到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。 X-Frame-Options三个参数: 1、DENY 表示该页面不允许在frame中展示,即便是在相同域名的页面中嵌套也不允许。 2、SAMEORIGIN 表示该页面可以在相同域名页面的frame中展示。 3、ALLOW-FROM uri 表示该页面可以在指定来源的frame中展示。 换一句话说,如果设置为DENY,不光在别人的网站frame嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为SAMEORIGIN,那么页面就可以在同域名页面的frame中嵌套。正常情况下我们通常使用SAMEORIGIN参数。 Apache配置 需要把下面这行添加到 'site' 的配置中
1 |
Header always append X-Frame-Options SAMEORIGIN |
nginx配置 需要添加到 ‘http’, ‘server’ 或者 ‘location’ 的配置项中,个人来讲喜欢配置在‘server’ 中 正常情况下都是使用SAMEORIGIN参数,允许同域嵌套
1 |
add_header X-Frame-Options SAMEORIGIN; |
允许单个域名iframe嵌套
1 |
add_header X-Frame-Options ALLOW-FROM http://whsir.com/; |
允许多个域名iframe嵌套,注意这里是用逗号分隔
1 |
add_header X-Frame-Options "ALLOW-FROM http://whsir.com/,https://cacti.org.cn/"; |
IIS配置 添加下面的配置到 ‘Web.config’文件中
1 2 3 4 5 6 7 8 9 |
<system.webServer> ... <httpProtocol> <customHeaders> <add name="X-Frame-Options" value="SAMEORIGIN" /> </customHeaders> </httpProtocol> ... </system.webServer> |
HAProxy配置 添加下面这行到 ‘front-end, listen, or backend’配置中
1 |
rspadd X-Frame-Options:\ SAMEORIGIN |
Tomcat配置 在 ‘conf/web.xml’填加以下配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<filter> <filter-name>httpHeaderSecurity</filter-name> <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class> <init-param> <param-name>antiClickJackingOption</param-name> <param-value>SAMEORIGIN</param-value> </init-param> <async-supported>true</async-supported> </filter> <filter-mapping> <filter-name>httpHeaderSecurity</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> |
配置后如何确定X-Frame-Options是否已生效呢?我这里以Google浏览器为例,打开网站按F12键,选择Network,找到对应的Headers,如下图所示 from:https://blog.whsir.com/post-3919.html
View Detailsidea中配置Lombok + Logback + Slf4j打印日志(附所有踩坑记录)
本文介绍非spring项目中利用Lombok + Logback + Slf4j记录日志,并附上所有的踩坑记录 本文环境 macos Idea2019.2 配置过程 首先在idea中下载lombok插件 在pom.xml文件中引入Lombok,Logback,Slf4j依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> |
在项目中的resources文件夹中添加logback.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> <property name="LOG_HOME" value="/logs" /> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %boldMagenta(%-5level %logger{50}) : %msg%n</pattern>--> <pattern>%d{yyyy-MM-dd HH:mm:ss:SS} %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{50}) - %cyan(%msg%n)</pattern> </encoder> </appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/provider.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名--> <FileNamePattern>${LOG_HOME}/provider.log.%d{yyyy-MM-dd}.log</FileNamePattern> <!--日志文件保留天数--> <MaxHistory>30</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> <!--日志文件最大的大小--> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- 日志输出级别 --> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration> |
编写代码测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import lombok.extern.slf4j.Slf4j; @Slf4j public class ProviderStart { public static void main(String[] args) { log.debug("输出DEBUG级别日志"); log.info("输出INFO级别日志"); log.warn("输出WARN级别日志"); log.error("输出ERROR级别日志"); } } |
输出为 踩过的坑 看上去简简单单几步就完成了,然后并不是,接下来附上踩过的坑以及解决方法 idea中plugins的marketplace直接打不开 在idea中使用lombok需要在plugins中的marketplace中下载插件,然而我下载时marketplace迟迟无法连接上 我们需要在设置中的Appearance & Behavior --> System Settings --> Http Proxy中选择Auto-detect proxy settings勾选Automatic proxy configuration URL选项并填写url为http://127.0.0.1:1080,重启idea 代码运行成功,但是不显示日志信息 也是很邪门的一种情况,代码没错,但是不显示log打印的信息。 解决方案为,在Build,Execution,Deployment–>compiler–>Annotation Processors中勾选Enable annotation processing,重启idea 多个Slf4j冲突 报错信息如下
1 2 |
SLF4J Warning: Class Path Contains Multiple SLF4J Bindings ..... |
说明是jar包冲突了,maven仓库中可能同时包含了log4j,logback,然后slf4j在程序运行时,不知道binding哪一个jar包。 解决方案为:在maven仓库中删除其中一个jar包,只保留一个即可。 from:https://blog.csdn.net/jerseywwwwei/article/details/105871320
View Details基于 spring boot 下logback 的 logback-spring.xml 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" debug="false"> <springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/> <!--日志存放路径--> <property name="PATH" value="logs"/> <property name="FILE_NAME" value="${spring.application.name}"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <withJansi>true</withJansi> <encoder> <charset>UTF-8</charset> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %magenta([PID:${PID:-}]) %green([%15.15thread]) %cyan(%40.40logger:%-5.5L):%msg%n</pattern> </encoder> </appender> <!--trace--> <appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${PATH}/${FILE_NAME}_trace.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${PATH}/${FILE_NAME}_trace.%d{yyyy-MM-dd}.log</FileNamePattern> <maxHistory>60</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %highlight([%-5level]) %green([%15.15thread]) %cyan([%logger:%line])--%mdc{client} %msg%n</pattern> </encoder> </appender> <!--error--> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${PATH}/${FILE_NAME}_error.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${PATH}/${FILE_NAME}_error.%d{yyyy-MM-dd}.log</FileNamePattern> <maxHistory>60</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %highlight([%-5level]) %green([%15.15thread]) %cyan([%logger:%line])--%mdc{client} %msg%n</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> </filter> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> <appender-ref ref="TRACE_FILE" /> <appender-ref ref="ERROR_FILE" /> </root> </configuration> |
from:https://my.oschina.net/haopeng/blog/3065616
View Details日志配置logback-spring.xml
参考官方网址: https://logging.apache.org/log4j/2.x 一、log4j日志级别配置说明
1 2 3 4 5 6 7 8 9 10 11 12 13 |
log4j提供了4种日志级别和2个日志开关。 DEBUG:输出调试信息;指出细粒度信息事件对调试应用程序是非常有帮助的。 INFO: 输出提示信息;消息在粗粒度级别上突出强调应用程序的运行过程。 WARN: 输出警告信息;表明会出现潜在错误的情形。 ERROR:输出错误信息;指出虽然发生错误事件,但仍然不影响系统的继续运行。 FATAL: 输出致命错误;指出每个严重的错误事件将会导致应用程序的退出。 ALL level:打开所有日志记录开关;是最低等级的,用于打开所有日志记录。 OFF level:关闭所有日志记录开关;是最高等级的,用于关闭所有日志记录。 按照范围从小到大排序:OFF level > FATAL > ERROR > WARN > INFO > DEBUG > ALL level;范围大的会包含范围小的,例如日志设置为INFO级别的话则FATAL、ERROR、WARN、INFO的日志开关都是打开的,而DEBUG的日志开关将是关闭的。 Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG。 |
二、logback-spring.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
<?xml version="1.0" encoding="UTF-8"?> <!-- 说明: 1、日志级别及文件 日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中。 2、日志级别可以根据开发环境进行配置,为方便统一管理查看日志,日志文件路径统一由LOG_PATH:-.配置在/home/项目名称/logs --> <configuration> <!-- 引入默认设置 --> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <!-- 编码格式设置 --> <property name="ENCODING" value="UTF-8" /> <!-- 日志文件的存储地址,由application.yml中的logging.path配置,根路径默认同项目路径 --> <property name="LOG_HOME" value="${LOG_PATH:-.}" /> <!-- 常规输出格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <property name="NORMAL_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}.%method@%line - %msg%n"/> <!-- 彩色输出格式:magenta:洋红,boldMagenta:粗红,yan:青色,·#══> --> <property name="CONSOLE_LOG_PATTERN" value="%boldMagenta([%d{yyyy-MM-dd HH:mm:ss.SSS}]) %red([%thread]) %boldMagenta(%-5level) %blue(%logger{20}.%method@%line) %magenta(·#═>) %cyan(%msg%n)"/> <!-- ==========================控制台输出设置========================== --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>${ENCODING}</charset> </encoder> </appender> <!-- ==========================按天输出日志设置========================== --> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/system-info.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滚 daily --> <FileNamePattern>${LOG_HOME}/system-info.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- 日志文件保留天数 --> <MaxHistory>30</MaxHistory> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <!-- 设置拦截的对象为INFO级别日志 --> <onMatch>ACCEPT</onMatch> <!-- 当遇到了INFO级别时,启用该段配置 --> <onMismatch>DENY</onMismatch> <!-- 没有遇到INFO级别日志时,屏蔽该段配置 --> </filter> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${NORMAL_LOG_PATTERN}</pattern> <charset>${ENCODING}</charset> </encoder> <!-- 日志文件最大的大小 --> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- ==========================按天输出ERROR级别日志设置========================== --> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/system-error.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滚 daily --> <FileNamePattern>${LOG_HOME}/system-error.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- 日志文件保留天数 --> <MaxHistory>30</MaxHistory> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <!-- 设置拦截的对象为ERROR级别日志 --> <onMatch>ACCEPT</onMatch> <!-- 当遇到了ERROR级别时,启用该段配置 --> <onMismatch>DENY</onMismatch> <!-- 没有遇到ERROR级别日志时,屏蔽该段配置 --> </filter> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${NORMAL_LOG_PATTERN}</pattern> <charset>${ENCODING}</charset> </encoder> <!-- 日志文件最大的大小 --> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- ==========================用户登录日志设置========================== --> <appender name="USER_LOGIN" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/user-login.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滚 daily --> <fileNamePattern>${LOG_HOME}/auth-user.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 30天 --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>${NORMAL_LOG_PATTERN}</pattern> <charset>${ENCODING}</charset> </encoder> </appender> <!-- ===日志输出级别,OFF level > FATAL > ERROR > WARN > INFO > DEBUG > ALL level=== --> <logger name="com.sand" level="INFO"/> <logger name="com.apache.ibatis" level="INFO"/> <logger name="java.sql.Statement" level="INFO"/> <logger name="java.sql.Connection" level="INFO"/> <logger name="java.sql.PreparedStatement" level="INFO"/> <logger name="org.springframework" level="WARN"/> <logger name="com.baomidou.mybatisplus" level="WARN"/> <!-- 用户登录日志 --> <logger name="user-login" level="INFO"> <appender-ref ref="USER_LOGIN"/> </logger> <!-- ======开发环境:打印控制台和输出到文件====== --> <springProfile name="dev"><!-- 由application.yml中的spring.profiles.active配置 --> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="INFO_FILE"/> <appender-ref ref="ERROR_FILE"/> </root> </springProfile> <!-- ======测试环境:打印控制台和输出到文件====== --> <springProfile name="test"><!-- 由application.yml中的spring.profiles.active配置 --> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="INFO_FILE"/> <appender-ref ref="ERROR_FILE"/> </root> </springProfile> <!-- ======生产环境:打印控制台和输出到文件====== --> <springProfile name="prod"><!-- 由application.yml中的spring.profiles.active配置 --> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="INFO_FILE"/> <appender-ref ref="ERROR_FILE"/> </root> </springProfile> </configuration> |
注意:登录日志的记录还需进行以下配置,用lombok的话直接使用注解即可 @Slf4j(topic = "user-login") 配置效果如下: from:https://www.cnblogs.com/54hsh/p/12684241.html
View Details