Spring IOC 工厂【一】引言、第一个Spring程序、使用日志框架Logback

引言

1、EJB存在的问题

在这里插入图片描述

2、什么是Spring?

Spring是一个轻量级的JavaEE解决方案,整合众多优秀的设计模式

  • 轻量级
1. 对于运行环境没有额外要求
	开源 tomcat resion jetty
	收费  welogic websphere
2. 代码移植性高
	不需要实现额外的接口
  • JavaEE的解决方案
    在这里插入图片描述
  • 整合了设计模式
1. 工厂
2. 代理
3. 模板
4. 策略

3、设计模式

1. 广义概念
	面向对象设计中,解决特定问题的经典代码
2. 狭义概念
	GOF4人帮定义的23中设计模式:工厂、适配器、装饰器、门面、代理、模板...

4、工厂设计模式

4.1什么是工厂设计模式

1. 概念:通过工厂类,创建对象
		User user = new User();
		UserDao userDao = new UserDaoImpl();
2. 好处:
    	解耦合
   耦合:
   		指定是代码间的强关联关系,一方的改变会影响另一方  
   问题:
   		不利于代码的维护
   简单理解:
   		把接口的实现类,硬编码在程序中:
 			UserService userService = new UserSerivce();

4.2简单工厂模式

#----------------applicationContext.properties--------------------
# Properties  集合 存储 Properties文件内容
# 特殊Map key=String value = String
# Properties.getProperties("userService");
userService = com.rick.serviceImpl.UserServiceImpl
userDao = com.rick.daoImpl.UserDaoImple

----------------------------------BeanFactory.java-------------------------------------
package com.rick.factory;

import com.rick.dao.UserDao;
import com.rick.daoImpl.UserDaoImpl;
import com.rick.service.UserService;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import static java.lang.Class.*;

/**
 * @author Rick
 */
public class BeanFactory {
    private static Properties env = new Properties();
    static{
        try {
            //获得IO输入流
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            //文件内容分装
            env.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /*
        对象的创建方式:
            1、直接通过调用构造方法 UserService userService = new UserService();
            2、通过反射的形式,创建对象,解耦合
     */
    public static UserService getUserService(){
        //return new UserServiceImpl();
        UserService userService = null;
        try {
            Class clazz = Class.forName(env.getProperty("userService"));
            userService = (UserService) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return userService;
    }

    public static UserDaoImpl getUserDao(){
        UserDaoImpl userDaoImpl = null;
        try {
            Class clazz  = Class.forName(env.getProperty("userDao"));
            userDaoImpl = (UserDaoImpl)clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return userDaoImpl;
    }

}
-------------------------------UserService.java--------------------------
package com.rick.service;

import com.rick.domain.User;

/**
 * @author Rick
 */
public interface UserService {
    public void saveUser(User user);
    public void querryUserByNameAndPassword(User user);
}
------------------------------UserServiceImpl.java--------------------------------------
package com.rick.serviceImpl;

import com.rick.dao.UserDao;
import com.rick.factory.BeanFactory;
import com.rick.service.UserService;
import com.rick.domain.User;

/**
 * @author Rick
 */
public class UserServiceImpl implements UserService {

//    UserDao userDao = new UserDaoImpl();
    UserDao userDao = BeanFactory.getUserDao();

    @Override
    public void saveUser(User user) {
        userDao.saveUser(user);
    }

    @Override
    public void querryUserByNameAndPassword(User user) {
        userDao.querryUserByNameAndPassword(user);
    }
}
------------------------------------------------UserDao.java-------------------------------
package com.rick.dao;

import com.rick.domain.User;

/**
 * @author Rick
 */
public interface UserDao {
    public void saveUser(User user);
    public void querryUserByNameAndPassword(User user);
}
-----------------------------------------UserDaoImpl.java------------------------------
package com.rick.daoImpl;

import com.rick.dao.UserDao;
import com.rick.domain.User;

/**
 * @author Rick
 */
public class UserDaoImpl implements UserDao {

    @Override
    public void saveUser(User user) {
        System.out.println("saving" + user.toString());
    }

    @Override
    public void querryUserByNameAndPassword(User user) {
        System.out.println(user.toString());
    }
}
---------------------------------AppTest.java------------------------------------------
package com.ric

import static org.junit.Assert.assertTrue;

import com.rick.service.UserService;
import com.rick.factory.BeanFactory;
import org.junit.Test;

public class AppTest 
{
    @Test
    public void test1() throws Exception{
        //UserServiceImplNew
        //UserService userService = new UserServiceImplNew();
        //UserService userService = new UserServiceImpl();
        UserService userService = BeanFactory.getUserService();
        User user = new User();
        userService.querryUserByNameAndPassword(user);
    }
    
}

4.3通用工厂模式

  • 问题

简单工厂存在大量代码冗余

  • 通用工厂代码
package com.rick.factory;

import com.rick.dao.UserDao;
import com.rick.daoImpl.UserDaoImpl;
import com.rick.service.UserService;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import static java.lang.Class.*;

/**
 * @author Rick
 */
public class BeanFactory {
    private static Properties env = new Properties();
    static{
        try {
            //获得IO输入流
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            //文件内容分装
            env.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /*
        对象的创建方式:
            1、直接通过调用构造方法 UserService userService = new UserService();
        key 小配置文件中的key
     */
    public static Object getBean(String key){
        Object obj = null;
        Class clazz = null;
        try {
            clazz = Class.forName(env.getProperty("key"));
            obj = clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return obj;
    }
}
  • 通用工厂的使用方式
1. 定义类型(类)
2. 通过配置文件配置告知工厂(applicationContext.properties)
		key = value
3. 通过工厂获得类的对象
		Object obj = BeanFactory.getBean("key");

5 总结

Spring本质:工厂 		
	ApplicationContext(applicationContext.xml)

第一个Spring程序

1、软件版本

	JDK: 8
	Maven: 3.6.3
	IDEA: 2020.1.1
	SpringFranework: 5.1.15.RELEASE	
	官方网站:www.spring.io

2、环境搭建

  • 设置Spring的pom依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
    <version>5.1.15.RELEASE</version>
</dependency>
  • Spring的配置文件

    1. 配置文件的放置位置:任意位置 没有硬性要求
    2. 配置文件命名:没有硬性要求 建议:applicationContext.xml
    

思考:

日后应用Spring框架时,需要进行配置文件路径的设置。

3、Spring的核心API

  • ApplicationContext

    1. 作用:
    Spring提供的ApplicationContext工厂,用于对象的创建
    2. 好处:
    解耦合
    
    • ApplicationContext为接口类型

      接口:
      	屏蔽实现的差异
      非web环境:
      	ClassPathXmlApplicationContext
      web环境:
      	XmlWebApplicationContext
      
    • ApplicationContext为重量级资源

      1. ApplicationContext工厂的对象占用大量内存
      2. 不会频繁的创建对象:
      		一个应用只会创建一个工厂对象
      3. ApplicationContext工厂:
      		一定是线程安全的(多线程并发访问)
      

4、程序开发

1. 创建类型
2. 配置文件的配置:qpplicationContext.xml
3. 通过工厂类,获得对象
	ApplicationContext
		|ClassPathXmlApplication|
<!--applicationContext.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="com.rick.domain.Person"/>

</beans>
//-----------------------------------Person.java
package com.rick.domain;
/**
 * @author Rick
 * 通过工厂创建
 */
public class Person {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", dog=" + dog +
                '}';
    }
}
//--------------------------------Test.java
package com.rick;

import com.rick.domain.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Unit test for simple App.
 */
public class AppTest 
    @Test
    public void test1(){
        //获得Spring的工厂
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");	
    	/**
		 *需要强制转换类型
         *Person user = (Person) ctx.getBean("person");
    	 *不需要强制转换类型
    	 *Person person = ctx.getBean(Person.class);
 		 */
    	//当前的Spring的配置文件中,只能有一个bean标签的class为Person类型
    	Person user = ctx.getBean("person",Person.class);
        System.out.println(person.toString());
    }
}

5、细节分析

  • 名词解释
Spring工厂创建的对象,叫做bean或者组件
  • Spring工厂的的相关方法
ApplicationContext tcx = new ClassPathXmlApplicationContext("/applicationContext.xml");
//获取Spring工厂配置文件中所有bean标签的id的值,但不能判断name值
String[] beanDefinitionNames = ctx.getBeanDefinitionNames(Person.class);
//根据类型获得Spring配置文件中对应的id值,也能判断name值
String[] beanNamesForType = ctx.getBeanNamesFOrType(Person.class);
//判断是否存在指定的id值的bean
boolean isExist = ctx.containBeanDefinition("a");
//判断是否存在指定的id值的bean
boolean isExist = ctx.containBean("a");
  • 配置文件中需要注意的细节
1. 只配置class属性
<bean class=""/>
  a)上述这三种配置,有无id值
	com.rick.domain.Person#0
  b)应用场景
  	如果这个bean只用一次则可以省略id值,反之若需要多次使用则必须设置id值
2. name属性
  作用:用于在Spring的配置文件中,weibean对象定义别名(小名)
  区别:
  	别名可以定义多个,但id属性只能有有一个值
  	XML的id属性值有命名要求:必须以字母开头,由字母、数字、连字符、下划线组成,不能以特殊字符,如:/person
  	XML的name属性值无命名要求,name属性一般应用在特殊的场景下
  今日:
  	XML发展到今天,id属性的限制已不存在

6、对Spring工厂底层实现原理的简单分析

1. 通过ClassPathXmlApplicationContext()或XmlWebApplicationContext()工厂读取配置文件applicationContext.xml
2. 获得bean标签的相关信息(id的值,class的值),通过反射创建对于的对象
		Classs<?> clazz = Class.forName(Person.class);
		Person person = clazz.newInstance();
3. 反射创建对象,底层也是会调用对象自己的构造方法
	    Classs<?> clazz = Class.forName(Person.class);
		Person person = clazz.newInstance();
	等效于
		Person person = new Person();

7、思考

1. 问题a:未来在开发过程中,是不是所有的对象,都会交给Spring工厂来创建? 
	理论上,是的,但也有特例:实体对象(entity)是不会交给Spring创建,实体对象是由持久层框架进行创建的

使用Spring5.x自带的logback框架

1、logback简介

logback是由log4j创始人设计的又一个开源日志组件

logback当前分成三个模块:

  • logback-core:是其它两个模块的基础模块。
  • logback- classic:是log4j的一个 改良版本,且完整实现Sl4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging
  • logback-access:与Servlet容器集成提供通过Http来访问日志的功能

logback-corelogback-classic此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。

2、与log4j区别

1. 更快的实现 Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。

2. 非常充分的测试 Logback经过了几年,数不清小时的测试。Logback的测试完全不同级别的。这是简单重要的原因选择logback而不是log4j。

3. Logback-classic非常自然实现了SLF4j Logback-classic实现了 SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了SLF4J, 所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。

4. 非常充分的文档 官方网站有两百多页的文档。

5. 自动重新加载配置文件 当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在JEE环境里面。

6. Lilith Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。

7. 谨慎的模式和非常友好的恢复 在谨慎模式下,多个FileAppender实例跑在多个JVM下,能 够安全地写道同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。

8. 配置文件可以处理不同的情况 开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,和来实现,这样一个配置文件就可以适应多个环境。

9. Filters(过滤器) 有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续 保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需 加4行XML配置。可以参考MDCFIlter 。

10. SiftingAppender(一个非常多功能的Appender) 它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。

11. 自动压缩已经打出来的log RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。

12. 堆栈树带有包版本 Logback在打出堆栈树日志时,会带上包的数据。

13. 自动去除旧的日志文件 通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置maxHistory 12,那那些log文件超过12个月的都会被自动移除。

总结:logback比log4j优秀,可以取代之。

3、使用

1. 添加pom依赖
2. 编写logback.xml配置文件
<!--  logback start  -->
<dependency>
	<groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.3</version>
 </dependency>
 <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
<dependency>
     <groupId>ch.qos.logback</groupId>
     <artifactId>logback-access</artifactId>
     <version>1.2.3</version>
</dependency>
<!--   logback end   -->
<?xml version="1.0" encoding="UTF-8"?>
<!--
	说明:【logback.xml】
	1、日志级别及文件
		日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中
		例如:error级别记录到log.error.xxx.log或log.error.log(该文件为当前记录的日志文件),而log.error.xxx.log为归档日志,
		日志文件按日期记录,同一天内,若日志文件大小等于或大于10M,则按0、1、2...顺序分别命名
		例如log-level-2013-12-21.0.log
		其它级别的日志也是如此。

	2、文件路径
		若开发、测试用,在Eclipse中运行项目,则到Eclipse的安装路径查找logs文件夹.
		若部署到Tomcat下,则在Tomcat下的logs文件中.
		${catalina.base}能够取到项目部署时候的tomcat目录。

	3、Appender
		FILE-ERROR对应error级别,文件名以log.error.xxx.log形式命名
		FILE-WARN对应warn级别,文件名以log.warn.xxx.log形式命名
		FILE-INFO对应info级别,文件名以log.info.xxx.log形式命名
		FILE-DEBUG对应debug级别,文件名以log.debug.xxx.log形式命名
		STDOUT将日志信息输出到控制台上,为方便开发测试使用
 -->

<!--
    scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true.
    scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒.当scan为true时,此属性生效。默认的时间间隔为1分钟.
    debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 在Eclipse中运行,请到Eclipse的安装目录中找log文件,Tomcat下,请到Tomcat目录下找 -->
    <property name="LOG_PATH" value="${catalina.base}/logs"/>
    <!-- 项目名称 -->
    <property name="PROJECT_NAME" value="spring-starter"/>

    <!-- 控制台打印日志的配置 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${PROJECT_NAME} [%thread] [%logger{50}:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
    </appender>

    <!-- 配置DEBUG, INFO, WARN, ERROR 日志的Appender -->
    <appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${PROJECT_NAME}/${PROJECT_NAME}.log.error.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,
                 可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
                 而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${PROJECT_NAME}/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
                 命名日志文件,例如log-error-2013-12-21.0.log -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 日志文件保留天数 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志打印的格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${PROJECT_NAME} [%thread] [%logger{50}:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录error级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${PROJECT_NAME}/${PROJECT_NAME}.log.warn.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,
                 可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
                 而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${PROJECT_NAME}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
                 命名日志文件,例如log-warn-2013-12-21.0.log -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 日志文件保留天数 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志打印的格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${PROJECT_NAME} [%thread] [%logger{50}:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录warn级别,不记录大于warn级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${PROJECT_NAME}/${PROJECT_NAME}.log.info.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,
                 可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
                 而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${PROJECT_NAME}/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
                 命名日志文件,例如log-info-2013-12-21.0.log -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 日志文件保留天数 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志打印的格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${PROJECT_NAME} [%thread] [%logger{50}:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别,不记录大于info级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE-DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${PROJECT_NAME}/${PROJECT_NAME}.log.debug.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,
                 可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
                 而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${PROJECT_NAME}/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
                 命名日志文件,例如log-debug-2013-12-21.0.log -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 日志文件保留天数 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志打印的格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${PROJECT_NAME} [%thread] [%logger{50}:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录debug级别,不记录大于debug级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- SPRING等框架类代码日志打印, 输出到OTHER文件中, 出厂默认WARN以上 -->
    <appender name="OTHER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 此日志文件只记录warn级别及其以上的 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
        <!-- 正在记录的日志文件的路径及文件名 -->
        <File>${LOG_PATH}/${PROJECT_NAME}/${PROJECT_NAME}.log.other.log</File>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,
                 可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
                 而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${PROJECT_NAME}/log-other-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
                 命名日志文件,例如log-debug-2013-12-21.0.log -->
            <maxFileSize>35MB</maxFileSize>
            <!-- 日志文件保留天数 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志打印的格式 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${PROJECT_NAME} [%thread] [%logger{50}:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
    </appender>

    <!--
        出厂默认输出level级别INFO, 排查问题时, 可以通过工具切换为TRACE.
        自定义模块日志打印 添加在后面.
        name需要修改为自己项目中的合适的package
     -->
    <logger name="com.tao" level="INFO" additivity="false">
        <appender-ref ref="FILE-ERROR" />
        <appender-ref ref="FILE-WARN" />
        <appender-ref ref="FILE-INFO" />
        <appender-ref ref="FILE-DEBUG" />
        <!-- 生产环境请将STDOUT去掉!!! -->
        <appender-ref ref="STDOUT" />
    </logger>

    <!-- 其他的warn级别及其以上的日志,通过OTHER来记录 -->
    <root level="WARN">
        <appender-ref ref="OTHER" />
    </root>
</configuration>
展开阅读全文
©️2020 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值