首页 > 其他分享 >关于jfinal包slf4j包的学习

关于jfinal包slf4j包的学习

时间:2022-11-04 12:44:20浏览次数:81  
标签:log -- Db 学习 slf4j User jfinal 日志

关于jfinal包slf4j包的学习

1. jfinal包

1.1 jfinal简介

公司的就项目使用的是JFinal框架,那么为了读懂并维护公司的项目,则需要对此框架进行学习、了解。
JFinal项目开源代码地址:https://gitee.com/jfinal/jfinal/tree/master
JFinal官网地址:https://jfinal.com/project/1
一个基于 Java 语言的极速 WEB + ORM + AOP + Template Engine 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。

JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有 ruby、python 等动态语言的开发效率!为您节约更多时间,去陪恋人、家人和朋友 ;)
1.2 JFinal包的如下特点
  • MVC 架构,设计精巧,使用简单
  • 遵循 COC 原则,支持零配置,无 XML
  • 独创 Db + Record 模式,灵活便利
  • ActiveRecord 支持,使数据库开发极致快速
  • 极简、强大、高性能模板引擎 Enjoy,十分钟内掌握 90% 用法
  • 自动加载修改后的 Java 文件,开发过程中无需重启服务
  • AOP支持,拦截器配置灵活,功能强大
  • Plugin 体系结构,扩展性强
  • 多视图支持,支持 Enjoy、FreeMarker、JSP
  • 强大的 Validator 后端校验功能
  • 功能齐全,拥有传统 SSH 框架的绝大部分核心功能
  • 体积小仅 832 KB,并且无第三方依赖
1.3 Maven 坐标
<dependency>
    <groupId>com.jfinal</groupId>
    <artifactId>jfinal</artifactId>
    <version>5.0.6</version>
</dependency>
1.4 model类的简单使用

Model是ActiveRecord中最重要的组件之一,它充当MVC模式中的Model部分。以下是Model定义示例代码:

public class User extends Model<User> {
    public static final User dao = new User().dao();
}

以下为Model的一些常见用法:

// 创建name属性为James,age属性为25的User对象并添加到数据库
new User().set("name", "James").set("age", 25).save();
 
// 删除id值为25的User
User.dao.deleteById(25);
 
// 查询id值为25的User将其name属性改为James并更新到数据库
User.dao.findById(25).set("name", "James").update();
 
// 查询id值为25的user, 且仅仅取name与age两个字段的值
User user = User.dao.findByIdLoadColumns(25, "name, age");
 
// 获取user的name属性
String userName = user.getStr("name");
 
// 获取user的age属性
Integer userAge = user.getInt("age");
 
// 查询所有年龄大于18岁的user
List<User> users = User.dao.find("select * from user where age>18");
 
// 分页查询年龄大于18的user,当前页号为1,每页10个user
Page<User> userPage = User.dao.paginate(1, 10, "select *", "from user where age > ?", 18);
1.5. Db类的简单使用

Jfinal提供了两种操作数据库的组件,分别是Model类和DB类,可以极大地减少代码量,提高开发效率。

Db类提供了在Model类之外更丰富的的数据库操作能力,使用Db类以及嵌套的Record类时,无需对数据库表进行映射,Record类相当于一个通用的Model。

以下为Db+Record的常见用法:

  1. 没有创建 Model,不得不使用

  2. 由于Active Record 限制一个model对象对应一条记录,当需要批量操作表中的记录时需要使用Db + Record,例如,需要对 account 表中的 cash 字段统一加上 100 块钱:Db.update("update account set cash=cash+100"),这种情况下 Model 只能一条一条地处理数据,而 Db 可以利用 sql 去批量处理

  3. 在某些非常需要高度灵活性、通用性的系统之下使用 Db.find(...),例如做一个报表系统,其中绝大部分业务都是跨多表的联合查询的数据展现,用 Db.find(sql) 更加方便,以及拥有更大自由度。比如:

1 List<A> list = A.dao.find("select A.a,B.b from A  left join (select a,b from B) B on A.a = B.a")

这个时候如果需要对list中的数据进行处理,list.get(index).get("b")将会出错,因为list初始化是A类型的,而实体类A即数据库A中没有字段b。

这个时候采用Db类:

1 List<Record> list = Db.use(configname).find("select A.a,B.b from A  left join (select a,b from B) B on A.a = B.a")
  1. 在一些删除、更新语句使用的时候,比如:

 a. Model类在执行删除语句的时候可以使用deleteById()方法,该方法的使用需要数据库字段具有主键(当然,好的数据库设计每张表都具有一个主键)。如果没有主键,Model方法执行删除语句就无法进行了。当然我们可能会想到利用model.dao.find(sql)方法去执行delete操作,这样是不可以的。这个时候可以使用Db类的update方法:

1 Db.use("User").update("delete from tablename where para = ?", para);

 "User"是数据库配置configname:

public static final String CONFIG_NAME = "User";

b.批量插入、更新、删除时,可以使用Db类的batch方法:

public static int[] batch(java.lang.String sql,
          java.lang.String columns,
          java.util.List modelOrRecordList,
          int batchSize)
  • sql 参数是指 insert into 或者 update 语句,动态参数使用问号占位,例如:String sql = "insert into user(name, cash) values(?, ?)";上面这个 sql 其中要插入   name、cash 两个字段,而 values 中用了两个问号,这两个问号中的值从后续的 modelOrRecordList 中获取
  • columns 是指前面 sql 中问号占位的地方的参数名称,jfinal 在填充字段值的时候会根据这个名称去 modelOrRecordList 中去取数据
  • modelOrRecordList 是指 List < User > 或者 List < Record> 或者这种列表
  • batchSize 是指多少条数据写一次数据库
1 Db.use("User").batch("delete from tablename where para = ?",  new Object[][] {{para}}, 1);

2. slf4j包

2.1 什么是LSF4J(简介)

官网:https://www.slf4j.org/manual.html
(1)简单日记门面(simple logging Facade for Java)SLF4J是为各种loging APIs提供一个简单统一的接口。

(2)slf4j并不是一种具体的日志系统,而是一个用户日志系统的facade。

(3)在部署时,选择不同的日志系统包,即可自动转换到不同的日志系统上。
如:选择JDK自带的日志系统,则只需要将slf4j-api-XXX.jar和slf4j-jdkXXX.jar放置到classpath中即可,若想换成log4j的日志系统,仅需要用slf4j-log4jXXx.jar替换slf4j-jdkXXX.jar即可

(4)slf4j和log4j比较:
①log4j看成是一个完整的日志库;而slf4j是一个日志库的规范接口,可以根据不同的日志包使用不同的日志库。
②日志中需要传入参数时,log4j一般是使用字符串进行拼接的方式;
slf4j使用占位符,比字符串拼接更加高效。如logger.error("sql为 {} ",sql)。

(5)slf4j日志级别
Slf4j日志级别,级别由低到高,设置的级别约低,打印的日志越多
①trace: 一般不会使用,在日志里边也不会打印出来,最低的一个日志级别。
②debug: 一般放于程序的某个关键点的地方,用于打印一个变量值或者一个方法返回的信息之类的信息
③info 一般处理业务逻辑的时候使用,就跟 system.err打印一样,用于说明此处是干什么的。
④warn:警告,不会影响程序的运行,但是值得注意。
⑤error: 用户程序报错,必须解决的时候使用此级别打印日志。

2.2 使用教程
  1. 添加依赖
      <!--slf4j依赖-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.32</version>
            </dependency>
            <!-- logback 依赖 -->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
            </dependency>
    
  2. 在springBoot项目中添加一段controller代码

    package com.example.springb_web.controller;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class VisualController {
    
        private Logger logger = LoggerFactory.getLogger(VisualController.class);
    
        @RequestMapping(value="/test")
        @ResponseBody
        public String test(){
            String msg = "fucking good";
            logger.info("slf4j print info msg:{}",msg);
            logger.debug("slf4j print debug msg:{}",msg);
            return msg;
        }
    
    }
    
    

这里通过http://localhost:8080/test访问可以看到控制台输出如下,可以看到info的输出了,debug没有,因为springboot内部集成了slf4j,默认是info级别:

image-20221104113512078

  • 只在控制台打印,application.yml文件配置如下:

    # slf4j日志配置
    logging:
      # 配置级别
      level:
        root: info
        #分包配置级别,即不同的目录下可以使用不同的级别
        com.example.springb_web.controller: debug
    
  • 将日志打到文件中

    logging:
      file: D://log.log #输出到文件
      level:
        root: info
    
  • 当需要什么级别输出到什么地方时。要加上xml配置。

    #yml配置
    logging:
      config: classpath:log/logback-spring.xml
      path: D:/log
      level:
        root: info
    
  • xml配置,取名logback-spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
    <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
    <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
    <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
    <configuration  scan="true" scanPeriod="10 seconds">
     
        <!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
     
        <contextName>logback</contextName>
        <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
        <property name="logging.file.path" value="D:/log" />
        <property name="maxHistory" value="30" />
        <property name="maxFileSize" value="100MB" />
     
        <!-- 彩色日志(IDE下载插件才可以生效) -->
        <!-- 彩色日志依赖的渲染类 -->
        <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
        <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
        <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
        <!-- 彩色日志格式 -->
        <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
     
     
        <!--输出到控制台-->
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>info</level>
            </filter>
            <encoder>
                <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
                <!-- 设置字符集 -->
                <charset>UTF-8</charset>
            </encoder>
        </appender>
     
     
        <!--输出到文件-->
     
        <!-- 时间滚动输出 level为 DEBUG 日志 -->
        <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 正在记录的日志文件的路径及文件名 -->
    <!--        <file>${logging.file.path}/log_debug.log</file>-->
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset> <!-- 设置字符集 -->
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 日志归档 -->
                <fileNamePattern>${logging.file.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${maxFileSize}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>${maxHistory}</maxHistory>
            </rollingPolicy>
            <!-- 此日志文件只记录debug级别的 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>debug</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
     
        <!-- 时间滚动输出 level为 INFO 日志 -->
        <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 正在记录的日志文件的路径及文件名 -->
    <!--        <file>${logging.file.path}/log_info.log</file>-->
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset>
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 每天日志归档路径以及格式 -->
                <fileNamePattern>${logging.file.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${maxFileSize}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>${maxHistory}</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>${logging.file.path}/log_warn.log</file>-->
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset> <!-- 此处设置字符集 -->
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${logging.file.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${maxFileSize}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>${maxHistory}</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>${logging.file.path}/log_error.log</file>-->
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset> <!-- 此处设置字符集 -->
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${logging.file.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${maxFileSize}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>${maxHistory}</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,
                  还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
                  如果未设置此属性,那么当前logger将会继承上级的级别。
            addtivity:是否向上级logger传递打印信息。默认是true。
        -->
        <!--<logger name="org.springframework.web" level="info"/>-->
        <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
        <!--
            使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
            第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
            第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
         -->
     
     
        <!--
            root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
            level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
            不能设置为INHERITED或者同义词NULL。默认是DEBUG
            可以包含零个或多个元素,标识这个appender将会添加到这个logger。
        -->
     
        <!--开发环境:打印控制台
        <springProfile name="dev">
            <logger name="com.nmys.view" level="debug"/>
        </springProfile>-->
     
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
        </root>
     
        <!--生产环境:输出到文件-->
        <!--<springProfile name="pro">-->
        <!--<root level="info">-->
        <!--<appender-ref ref="CONSOLE" />-->
        <!--<appender-ref ref="DEBUG_FILE" />-->
        <!--<appender-ref ref="INFO_FILE" />-->
        <!--<appender-ref ref="ERROR_FILE" />-->
        <!--<appender-ref ref="WARN_FILE" />-->
        <!--</root>-->
        <!--</springProfile>-->
     
    </configuration>
    

标签:log,--,Db,学习,slf4j,User,jfinal,日志
From: https://www.cnblogs.com/atao-BigData/p/16857389.html

相关文章

  • 【学习心得】老男孩Linux课程学习分享,听听我的故事!
    我是老男孩教育Linux班的毕业学员,说一说我的学习感受。首先是费用方面,其实关于费用我没有什么想要说的,但很多小伙伴肯定都关注这点,所以简单分享一下。费用的话,其实......
  • 【单片机/嵌入式】【梁山派】学习日志04:寄存器点灯
    一、寄存器点亮LED1.1配置流程一般我们使用GPIO的端口,都需要有以下几个步骤。(1)开启GPIO的端口时钟(2)配置GPIO的模式(3)配置GPIO的输出从LED介绍那一章节我们了解到LED1......
  • Java学习——11.04
    因为昨天学的有点少,上不了台面,所以和今天的一起写,当然还可能是自己太懒了,昨天的没记住,于是又看了一遍。1.变量:局部变量(和C一样的)实例变量(加new引用文件名创建函数......
  • 深度学习识别路面裂缝记录
    https://github.com/yhlleo/DeepSegmentor程序↑1.condaenvcreate-fenvironment.yml执行ResolvePackageNotFound:pytorch=0.4.1_pip没有这个版本忽略了,哪个pytorc......
  • 第十周第十二章学习笔记
    第十二章学习笔记12.1块设备I/O缓冲区I/O缓冲的基本原理非常简单。文件系统使用一系列I/O缓冲区作为块设备的缓存内存。当进程试图读取(dev,blk)标识的磁盘块时。它首先在......
  • 如何正确学习vue3.0源码
    为什么要学源码技术是第一生产力学习API的设计目的、思路、取舍学习优秀的代码风格学习组织代码的方式学习实现方法的技巧学习ES67新API、TS高级用法不给自......
  • STM32 UART学习
    UART配置步骤:1、初始化串口所需要的GPIO2、初始化串口,USART_InitTypeDef3、中断配置(接收中断,中断优先级)4、使能串口5、编写接收和发送函数6、编写中断服务函数 ke......
  • JVM学习笔记——垃圾回收篇
    JVM学习笔记——垃圾回收篇在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的垃圾回收部分我们会分为以下几部分进行介绍:判断垃圾回收对象垃圾回收算法分......
  • localtime_r学习
    转自:https://blog.csdn.net/u010087712/article/details/507312221.localtime_r  用来获取系统时间,运行于linux平台下。 函数原型:structtm*localtime_r(constti......
  • Flask学习笔记(十八)-Flask 信号机制
    一、说明官方文档-信号参考Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为安装:pip3installblinker二、自定义信号自定义......