3 Log
3.1 简介
技术选型
- 日志门面 (抽象层)
JCL 2014年最后更新- SLF4j (Simple Logging Facade for Java)
jboss-logging 天生不适合普通程序员用
- 日志实现
JUL (java.util.logging) 生来只是怕垄断Log4j- Log4j2 不同作者, 但太先进市场稍微小了点
- Logback 与4j同一作者, 升级版
Spring框架默认是JCL, SpringBoot选用SLF4j + logback
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0hCXb3z3-1588083234244)(SpringBoot2.assets/image-20200426211024111.png)]
用logback还可以少一层
使用原则
- 不直接调用实现类, 而是调用抽象层;
- 配置文件还是按照"日志实现"来配置
HelloWorld
-
导入slf4j的jar和logback实现的jar
-
官方helloworld
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HelloWorld { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.info("Hello World"); } }
历史遗留日志的替换 (legacy)
-
Spring(commons-logging) + Hibernate(jboss-logging) + MyBatis(xxx)
-
老系统不同组件可能不同日志工具
-
要统一日志, 即使别的框架也要统一使用slf4j
-
官方提供了replace的方案, 如下图. 用jcl-over-slf4j.jar来对commons logging API偷天换日
-
“中间包"偷天换日的"先锋队”: jcl-over-slf4j.jar | log4j-over-slf4j.jar | jul-to-slf4j.jar
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZhEp8wX-1588083234247)(SpringBoot2.assets/image-20200426225343662.png)]
具体如何统一到slf4j?
- 将系统中所有其它日志框架先排除出去
- 用 “中间包” 来替换原来的日志工具
- 导入slf4j的其他实现
3.2 Spring Boot 日志关系
SpringBoot能自动适配所有日志工具 (通过各种"中间包"), 自己底层用的是slf4j + logback的日志组合. 如果引入别的组件或者开发框架, 只需要把这个框架底层依赖的日志排除掉即可!
SpringBoot 的日志
SpringBoot日志依赖关系图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G4UG1wwv-1588083234248)(SpringBoot2.assets/image-20200426231806424.png)]
总结:
- Spring Boot底层也是使用slf4j+logback的方式进行日志记录
- Spring Boot也把其他日志替换成slf4j (还依赖三个"中间包")
spring boot底层如何替换其他框架?
利用"中间包", “偷梁换柱”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVzHds3m-1588083234251)(SpringBoot2.assets/image-20200426232753893.png)]
为什么称之为中间包, 偷梁换柱包? 代码片段演示
@SuppressWarnings("rawtypes")
public abstract class LogFactory {
static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";
// 它们底层有这一类的操作...把明明是slf4j的偷偷交给你用
static LogFactory logFactory = new SLF4JLogFactory();
//.....
如果引入其他软件开发框架
一定要把这个框架底层默认集成的日志依赖排除掉, Spring会自动也是借鉴了SpringBoot底层的操作:
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
...
-
<exclusions>
- 排除 -
注: commons logging是Spring默认的日志工具
3.4 日志使用
默认配置
- 级别
- 输出位置
- 输出文件名
SpringBoot默认已经配置好了日志, 并且有一个默认日志级别, 称之为 root
package org.zhangcl.springboot;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; // 注意这个包容易导错
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringBoot03LoggingApplicationTests {
// 日志"记录器"
Logger logger = LoggerFactory.getLogger(this.getClass());
@Test
void contextLoads() {
/*
日志的"级别", 由低到高!
可以调整需要输出的日志级别, 可以按级别选择性输出"某个级别以及更高级别"
配置文件可以设置级别
*/
logger.trace("这是trace日志");
logger.debug("这是debug日志");
logger.info("这是info日志");
logger.warn("这是warn日志");
logger.error("这是error日志");
/**
* 但是我这边更改配置没有用...
*/
}
}
也可以手动配置, 不过我这边按照视频讲解配置没有效果
# 日志级别
logging.level.org.zhangcl=error
# 如果不指定路径, 则在当前项目根目录下
logging.file=springboot.log
# 如果指定完整路径+文件名, 则按照执行 (我的只有重新运行项目主启动类才能)
logging.file=D:/springboot.log
#在当前磁盘的根路径下创建spirng文件夹和默认spring.log文件, linux就是绝对路径, win是c盘根目录
logging.path=/spring/log
# 控制台输出的格式
logging.pattern.console=
# 指定文件中日志输出格式
logging.pattern.file=
file 和 path的配合
logging.file | logging.path | Example | description |
---|---|---|---|
n | n | 只在控制台输出 | |
指定 | n | my.log | 项目根目录输出my.log |
n | 指定 | /var/log | 指定位置: spring.log |
指定配置
给类路径下放上每个日志框架各自的规定的配置文件即可
规则
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
-
logback.xml 日志框架可以直接识别
-
logback-spring.xml 日志框架不直接识别, 而是由SpringBoot识别
- 就可以使用高级特性: 某段配置只能在某个环境下生效
<springProfile name="dev">...</springProfile>
3.5 切换框架
切换到log4j
- 在diagram图上剔除不要的: logback + log4j中间包
- 根据官网推荐再引入log4j-12, 底层自动也加入了log4j
- 再引入相关配置文件
切换到log4j2
根据boot官网, 需要和默认的starter-logging
做二选一, 直接替换掉logging, 转而用starter-log4j2
4 Web
之前学的项目都是打jar包, 怎样web呢?
要解决的问题: (这一块内容可以删掉)
- 如何导入静态资源
- “首页”
- 代替jsp: 模板引擎
- 装配拓展SpringMVC
- CRUD
- 拦截器
- 国际化: 中英文切换
4.1 静态资源映射规则
SpringMVC的相关配置都在WebMvcAutoconfiguration类中
ResourceProperties类
-
可以设置与静态资源有关的属性, 比如缓存时间
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false) public class ResourceProperties implements ResourceLoaderAware { // 这个类可以设置与静态资源有关的参数 // ... }
规则1: /webjars/**
webjars是什么
-
Web Libraries in Jars
-
是一种把主流静态资源封装成jar形式的技术, 比如jQuery.js文件一般是以静态资源导入, 但这里以依赖jar的方式封装一下给我们用,的一种技术
-
官网给出最流行的几个例子:
源码分析
- idea中搜索WebMvcAutoconfiguration类找到其中的这个方法, 截取如下:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Integer cachePeriod = this.resourceProperties.getCachePeriod();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(
this.resourceProperties.getStaticLocations())
.setCachePeriod(cachePeriod));
}
}
- 符合/webjars/**的, 会去这个位置找资源
addResourceLocations("classpath:/META-INF/resources/webjars/"
例子
-
我们以jQuery为例, 在webjars官网选择版本, maven方式, 通过maven引入后, 在依赖列表:
意味着: 我们的classpath:/webjars下有东西了
![image-20200427123600281](SpringBoot2.assets/image-20200427123600281.png)
- 发现了代码中描述的路径
- 测试: 请求
localhost:8080/webjars/jquery/3.3.1/jquery.js
, 可以打开.
规则2: 静态资源的文件夹
注: 正常情况下静态资源是不允许外部直接访问的!
-
classpath:/META-INF/resources/
-
classpath:/resources/
-
classpath:/static/
-
classpath:/public/
-
当前项目根路径(个人自己测试不行, 反正也是优先级最低, 不管了)
localhost:8080/
规则3: 欢迎页
-
默认指定文件名:
index.html
-
默认位置: (如规则2)
-
默认url:
localhost:8080/
, 第层已经映射好了, 记住这个就行
规则4: 网页图标
所有的: **/favicon.ico 都在静态资源文件下找
(个人不重视 不熟练)
自定义: 静态资源路径
原则
如果自定义, 则默认的会失效
如何定义?
操作application.properties中设置:
spring.resources.static-locations=classpath:/mylocation1/,classpath:/mylocation2/deep1/
- 优先级: 按照以上写入顺序
/mylocation2/deep1
中, 个人测试了mylocation2目录, 无效
4.2 模板引擎
-
市面上: JSP | Velocity | Freemarker | Thymeleaf
-
重点讲SB推荐的Thymeleaf
- 语法简单\功能强大
-
如果要识别在template目录下静态资源, 除了Controller, 额外还需要模板引擎支持, 比如Thymeleaf
使用 - 基本规则
依赖 (引用为准)
<properties></