整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Spring Boot:实现MyBatis分页

Spring Boot:实现MyBatis分页

合概述

想必大家都有过这样的体验,在使用Mybatis时,最头痛的就是写分页了,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 select,幸好我们有 pagehelper 分页插件,pagehelper 是一个强大实用的 MyBatis 分页插件,可以帮助我们快速的实现MyBatis分页功能,而且pagehelper有个优点是,分页和Mapper.xml完全解耦,并以插件的形式实现,对Mybatis执行的流程进行了强化,这有效的避免了我们需要直接写分页SQL语句来实现分页功能。那么,接下来我们就来一起体验下吧。

实现案例

接下来,我们就通过实际案例来讲解如何使用pagehelper来实现MyBatis分页,为了避免重复篇幅,此篇教程的源码基于《Spring Boot:整合MyBatis框架》一篇的源码实现,读者请先参考并根据教程链接先行获取基础源码和数据库内容。

添加相关依赖

首先,我们需要在 pom.xml 文件中添加分页插件依赖包。

pom.xml

<!-- pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>

添加相关配置

然后在 application.yml 配置文件中添加分页插件有关的配置。

application.yml

# pagehelper   
pagehelper:
    helperDialect: mysql
    reasonable: true
    supportMethodsArguments: true
    params: count=countSql

编写分页代码

首先,在 DAO 层添加一个分页查找方法。这个查询方法跟查询全部数据的方法除了名称几乎一样。

SysUserMapper.java

package com.louis.springboot.demo.dao;

import java.util.List;
import com.louis.springboot.demo.model.SysUser;

public interface SysUserMapper {
    int deleteByPrimaryKey(Long id);

    int insert(SysUser record);

    int insertSelective(SysUser record);

    SysUser selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(SysUser record);

    int updateByPrimaryKey(SysUser record);
    
    /**
     * 查询全部用户
     * @return
     */
    List<SysUser> selectAll();
    
    /**
     * 分页查询用户
     * @return
     */
    List<SysUser> selectPage();
}

然后在 SysUserMapper.xml 中加入selectPage的实现,当然你也可以直接用@Select注解将查询语句直接写在DAO代码,但我们这里选择写在XML映射文件,这是一个普通的查找全部记录的查询语句,并不需要写分页SQL,分页插件会拦截查询请求,并读取前台传来的分页查询参数重新生成分页查询语句。

SysUserMapper.xml

<select id="selectPage"  resultMap="BaseResultMap">
  select 
  <include refid="Base_Column_List" />
  from sys_user
</select>

服务层通过调用DAO层代码完成分页查询,这里统一封装分页查询的请求和结果类,从而避免因为替换ORM框架而导致服务层、控制层的分页接口也需要变动的情况,替换ORM框架也不会影响服务层以上的分页接口,起到了解耦的作用。

SysUserService.java

package com.louis.springboot.demo.service;
import java.util.List;
import com.louis.springboot.demo.model.SysUser;
import com.louis.springboot.demo.util.PageRequest;
import com.louis.springboot.demo.util.PageResult;

public interface SysUserService {

    /**
     * 根据用户ID查找用户
     * @param userId
     * @return
     */
    SysUser findByUserId(Long userId);

    /**
     * 查找所有用户
     * @return
     */
    List<SysUser> findAll();

    /**
     * 分页查询接口
     * 这里统一封装了分页请求和结果,避免直接引入具体框架的分页对象, 如MyBatis或JPA的分页对象
     * 从而避免因为替换ORM框架而导致服务层、控制层的分页接口也需要变动的情况,替换ORM框架也不会
     * 影响服务层以上的分页接口,起到了解耦的作用
     * @param pageRequest 自定义,统一分页查询请求
     * @return PageResult 自定义,统一分页查询结果
     */
    PageResult findPage(PageRequest pageRequest);
}

服务实现类通过调用分页插件完成最终的分页查询,关键代码是 PageHelper.startPage(pageNum, pageSize),将前台分页查询参数传入并拦截MyBtis执行实现分页效果。

SysUserServiceImpl.java

package com.louis.springboot.demo.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.louis.springboot.demo.dao.SysUserMapper;
import com.louis.springboot.demo.model.SysUser;
import com.louis.springboot.demo.service.SysUserService;
import com.louis.springboot.demo.util.PageRequest;
import com.louis.springboot.demo.util.PageResult;
import com.louis.springboot.demo.util.PageUtils;

@Service
public class SysUserServiceImpl implements SysUserService {
    
    @Autowired
    private SysUserMapper sysUserMapper;
    
    @Override
    public SysUser findByUserId(Long userId) {
        return sysUserMapper.selectByPrimaryKey(userId);
    }

    @Override
    public List<SysUser> findAll() {
        return sysUserMapper.selectAll();
    }
    
    @Override
    public PageResult findPage(PageRequest pageRequest) {
        return PageUtils.getPageResult(pageRequest, getPageInfo(pageRequest));
    }
    
    /**
     * 调用分页插件完成分页
     * @param pageQuery
     * @return
     */
    private PageInfo<SysUser> getPageInfo(PageRequest pageRequest) {
        int pageNum=pageRequest.getPageNum();
        int pageSize=pageRequest.getPageSize();
        PageHelper.startPage(pageNum, pageSize);
        List<SysUser> sysMenus=sysUserMapper.selectPage();
        return new PageInfo<SysUser>(sysMenus);
    }
}

在控制器SysUserController中添加分页查询方法,并调用服务层的分页查询方法。

SysUserController.java

package com.louis.springboot.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.louis.springboot.demo.service.SysUserService;
import com.louis.springboot.demo.util.PageRequest;

@RestController
@RequestMapping("user")
public class SysUserController {

    @Autowired
    private SysUserService sysUserService;
    
    @GetMapping(value="/findByUserId")
    public Object findByUserId(@RequestParam Long userId) {
        return sysUserService.findByUserId(userId);
    }
    
    @GetMapping(value="/findAll")
    public Object findAll() {
        return sysUserService.findAll();
    }
    
    @PostMapping(value="/findPage")
    public Object findPage(@RequestBody PageRequest pageQuery) {
        return sysUserService.findPage(pageQuery);
    }
}

分页查询请求封装类。

PageRequest.java

package com.louis.springboot.demo.util;
/**
 * 分页请求
 */
public class PageRequest {
    /**
     * 当前页码
     */
    private int pageNum;
    /**
     * 每页数量
     */
    private int pageSize;
    
    public int getPageNum() {
        return pageNum;
    }
    public void setPageNum(int pageNum) {
        this.pageNum=pageNum;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        this.pageSize=pageSize;
    }
}

分页查询结果封装类。

PageResult.java

package com.louis.springboot.demo.util;
import java.util.List;
/**
 * 分页返回结果
 */
public class PageResult {
    /**
     * 当前页码
     */
    private int pageNum;
    /**
     * 每页数量
     */
    private int pageSize;
    /**
     * 记录总数
     */
    private long totalSize;
    /**
     * 页码总数
     */
    private int totalPages;
    /**
     * 数据模型
     */
    private List<?> content;
    public int getPageNum() {
        return pageNum;
    }
    public void setPageNum(int pageNum) {
        this.pageNum=pageNum;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        this.pageSize=pageSize;
    }
    public long getTotalSize() {
        return totalSize;
    }
    public void setTotalSize(long totalSize) {
        this.totalSize=totalSize;
    }
    public int getTotalPages() {
        return totalPages;
    }
    public void setTotalPages(int totalPages) {
        this.totalPages=totalPages;
    }
    public List<?> getContent() {
        return content;
    }
    public void setContent(List<?> content) {
        this.content=content;
    }
}

分页查询相关工具类。

PageUtils.java

package com.louis.springboot.demo.util;
import com.github.pagehelper.PageInfo;

public class PageUtils {

    /**
     * 将分页信息封装到统一的接口
     * @param pageRequest 
     * @param page
     * @return
     */
    public static PageResult getPageResult(PageRequest pageRequest, PageInfo<?> pageInfo) {
        PageResult pageResult=new PageResult();
        pageResult.setPageNum(pageInfo.getPageNum());
        pageResult.setPageSize(pageInfo.getPageSize());
        pageResult.setTotalSize(pageInfo.getTotal());
        pageResult.setTotalPages(pageInfo.getPages());
        pageResult.setContent(pageInfo.getList());
        return pageResult;
    }
}

编译测试运行

启动应用,访问:localhost:8088/swagger-ui.html,找到对应接口,模拟测试,结果如下。

参数:pageNum: 1, pageSize: 5

参数:pageNum: 2, pageSize: 4

学习更多JAVA知识与技巧,关注与私信博主(学习)

yBatis开发Dao有两种方式:原始Dao的开发方式,Mapper动态代理的方式。

两种开发方式在企业开发中均有运用。都要掌握。

使用myBatis时,需要对其进行一个全局的管理配置。

sqlMappingConfig.xml

[html] view plain copy

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <!-- 加载属性文件-->
  7. <properties resource="db.properties"></properties>
  8. <!-- 全局参数配置,在需要时候进行配置 -->
  9. <!-- <settings></settings> -->
  10. <!-- 别名设置 -->
  11. <!-- 单个配置
  12. type:类型路径
  13. alias:别名-->
  14. <!-- <typeAliases>
  15. <typeAlias type="cn.edu.hpu.ssm.po.User" alias="user"/>
  16. </typeAliases> -->
  17. <!-- 批量设置(推荐使用)
  18. 指定包名,mybatis自动扫描扫描po类,自动定义别名。默认为类名(首字母大写或小写) -->
  19. <typeAliases>
  20. <package name="cn.edu.hpu.ssm.po"/>
  21. </typeAliases>
  22. <!-- 和spring整合后 environments配置将废除-->
  23. <environments default="development">
  24. <environment id="development">
  25. <!-- 使用jdbc事务管理,事物控制有mybatis控制-->
  26. <transactionManager type="JDBC" />
  27. <!-- 数据库连接池,由mybatis管理-->
  28. <dataSource type="POOLED">
  29. <property name="driver" value="${jdbc.driver}" />
  30. <property name="url" value="${jdbc.url}" />
  31. <property name="username" value="${jdbc.username}" />
  32. <property name="password" value="${jdbc.password}" />
  33. </dataSource>
  34. </environment>
  35. </environments>
  36. <!-- 配置mpper,加载映射文件 -->
  37. <!-- <mappers>
  38. <mapper resource="sqlmap/User.xml"/>
  39. <mapper resource="mapper/UserMapper.xml"/>
  40. </mappers> -->
  41. <!-- 通过mapper接口,加载映射文件
  42. 规范:mapper接口名必须与mapper。xml文件名相同,且放在同一包下
  43. 前提是使用mapper代理的方式 -->
  44. <mappers>
  45. <mapper class="cn.edu.hpu.ssm.mapper.UserMapper"/>
  46. <mapper class="cn.edu.hpu.ssm.mapper.OrdersMapperCustom"/>
  47. </mappers>
  48. </configuration>

其中关于数据库的一些配置,抽取出来了,这样可以减少硬编码:

db.properties:

[plain] view plain copy

  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/mybatis
  3. jdbc.username=root
  4. jdbc.password=123456

1.原始Dao的开发方式

原始Dao的开发,需要程序员自己编写Dao的接口和Dao接口的实现类。(一下以一个按照id查询为例说明)

1.映射文件:

[html] view plain copy

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!-- namespace:命名空间,作用就是对sql进行分类化管理,sql隔离
  6. 注意:在使用mapper的代理方法开发时,有重要作用 -->
  7. <mapper namespace="test">
  8. <!-- 在映射文件中配置多个,sql语句 -->
  9. <!-- 按照id查询 -->
  10. <!-- 将sql语句封装到MapperStatement中,所以也将id 成为statement的Id -->
  11. <!-- paramerType:指定输入参数的类型。
  12. #{ } :代表占位符。
  13. #{id }:表示接受输入参数id的值,如果输入参数是简单类型,#{ }中的参数名可以任意
  14. ,可以是value或是其他值
  15. resultType:表示sql输出结果的所映射的Javabean的对象类型,resultType指定将单条记录映射成Java对像-->
  16. <select id="findUserById" parameterType="int" resultType="cn.edu.hpu.ssm.po.User">
  17. SELECT * FROM USER WHERE id=#{value}
  18. </select>
  19. </mapper>

2.Dao接口:

[java] view plain copy

  1. Public interface UserDao {
  2. public User getUserById(int id) throws Exception;
  3. }

3.Dao接口的实现

[java] view plain copy

  1. Public class UserDaoImpl implements UserDao {
  2. //通过构造函数注入SqlSessionFactory
  3. public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
  4. this.setSqlSessionFactory(sqlSessionFactory);
  5. }
  6. private SqlSessionFactory sqlSessionFactory;
  7. @Override
  8. public User getUserById(int id) throws Exception {
  9. SqlSession session=sqlSessionFactory.openSession();
  10. User user=null;
  11. try {
  12. //通过sqlsession调用selectOne方法获取一条结果集
  13. //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
  14. user=session.selectOne("test.findUserById", 1);
  15. System.out.println(user);
  16. } finally{
  17. session.close();
  18. }
  19. return user;
  20. }
  21. }

通过上面的例子,我们可以总结:

原始Dao开发存在以下问题:

Dao的方法存在重复代码,:通过sqlSessionFactory创建SqlSession,调用sqlSession数据库的操作方法。

调用sqlSession操作数据库的方法(第一个参数)时,硬编码,不利于系统的维护。

SqlSessionFactory的使用范围:

通过SQLSessionFactoryBuilder创建会话工厂SQLSessionFactory。将SQLSessionFactoryBuilder当做一个工具类来使用即可,不需要使用单例模式去管理。

通过SQLSessionFactory创建sqlSession,使用单例模式管理SQLSessionFactory,(工厂一旦被创建,使用一个实例)。将来mybatis与spring整合后,使用单例模式来管理sqlSessionFactory。

sqlSession是线程不安全的,在sqlsession中不但存在操作数据库的方法,还有数据域属性。sqlSession最佳应用场合,是在方法体内,定义成局部变量使用。

2.Mapper代理的方式:

mapper动态代理实现的原理:

mapper接口开发方式,只需要程序员编写mapper接口(相当于Dao接口),有mybatis框架根据接口定义创建接口的动态代理对象,代理的方法体与上面Dao实现类中的方法体相类似

Mapper接口开发要符合一下规范:

1.Mapper.xml中namespace路径与mapper接口路径相同

2.mapper接口中的方法名,与Mapper.xml中对应statement的id相同

3.mapper接口中方法的输入参数类型和mapper.xml中定义的对应sql的ParameterType的类型相同

4.mapper接口中方法的返回值类型和mapper.xml中定义的对应sql的ResultType的类型相同

1.Mapper.xml写法:(与上面User.xml不同的是namespace做了定义)

[html] view plain copy

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!-- namespace:命名空间,作用就是对sql进行分类化管理,sql隔离
  6. 注意:在使用mapper的代理方法开发时,有重要作用
  7. namespace命名必须与Mapper接口的路径相同 -->
  8. <mapper namespace="cn.edu.hpu.ssm.mapper.UserMapper">
  9. <!-- 按照id查询 -->
  10. <!-- 将sql语句封装到MapperStatement中,所以也将id 成为statement的Id -->
  11. <!-- paramerType:指定输入参数的类型。
  12. #{ } :代表占位符。
  13. #{id }:表示接受输入参数id的值,如果输入参数是简单类型,#{ }中的参数名可以任意
  14. ,可以是value或是其他值
  15. resultType:表示sql输出结果的所映射的Javabean的对象类型,resultType指定将单条记录映射成Java对像-->
  16. <select id="findUserById" parameterType="int" resultType="User">
  17. SELECT * FROM USER WHERE id=#{value}
  18. </select>
  19. </mapper>

2.mapper.java(接口文件)

[java] view plain copy

  1. package cn.edu.hpu.ssm.mapper;
  2. import java.util.List;
  3. import java.util.Map;
  4. import cn.edu.hpu.ssm.po.User;
  5. import cn.edu.hpu.ssm.po.UserCustom;
  6. import cn.edu.hpu.ssm.po.UserQueryVo;
  7. public interface UserMapper {
  8. //返回值类型必须与mapper.xml中resultType类型相同
  9. //形参必须与mapper.xml中的parameterType类型相同
  10. //mapper.java接口中的方法名和mapper.xml中statement的id一致
  11. public User findUserById(int id) throws Exception;
  12. }

3.测试文件:(通过junit)

[java] view plain copy

  1. public class MapperTest {

[java] view plain copy

  1. private SqlSessionFactory sqlSessionFactory;
  2. @Before
  3. public void setUp() throws Exception {
  4. String resource="SqlMapConfig.xml";
  5. InputStream input=Resources.getResourceAsStream(resource);
  6. sqlSessionFactory=new SqlSessionFactoryBuilder().build(input);
  7. }

[java] view plain copy

  1. /**
  2. * 通过id查询
  3. * @throws Exception
  4. */
  5. @Test
  6. public void testFindUserById() throws Exception {
  7. SqlSession session=sqlSessionFactory.openSession();
  8. //通过session自动创建mapper代理对象
  9. UserMapper userMap=session.getMapper(UserMapper.class);
  10. User user=userMap.findUserById(1);
  11. System.out.println(user);
  12. }

[java] view plain copy

  1. }

4.对Mapper动态代理的一个小结:

1.使用mapper代理时,输入参数类型可以使用pojo的包装对象,或是mapper对象,保证dao的同性。

2.selectOne和selectList

动态代理对象通过sqlsession.selectOne和sqlsession.selectList,是通过对返回值类型进行判断而选择调用哪一个方法。如果返回单个对象则调用selectOne,返回集合对象则调用selectList

积月累,方成大器。

各大网站:

Mybatis官方技术文档 https://mybatis.org/mybatis-3/zh/index.html
Mybatis源码包下载:https://github.com/mybatis/mybatis-3/releases
所有代码及笔记gitee路径:https://gitee.com/simple-coding/all-demo-code.git

一、关于Mybatis开发

要使用Mybatis开发只需引入mybatis-x.x.x.jar即可,想其它的日志等,如果需要可以另外引入包进行扩展。

本案例使用最新版本:mybatis-3.5.9.jar

二、日志配置

如果我们不引入第三方的日志包,那mybatis就不能对日志进行输出了吗?

首先,要知道Mybatis不引入第三方日志包,也能进行日志输出(默认日志功能禁用),只不过只能进行控制台输出,不能进行文件输出;另外,对于第三方日志,mybatis有特定的加载顺序,如果引入了多个日志实现也可以在主配置中通过settings进行配置,告诉mybatis我要用哪个进行输出

最新版本,第三方加载顺序如下、源码如下图(不同的mybatis版本可能不一样):

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j (deprecated since 3.5.9)
  • JDK logging

MyBatis 内置日志工厂基于运行时自省机制选择合适的日志工具。它会使用第一个查找得到的工具(按上文列举的顺序查找)。如果一个都未找到,日志功能就会被禁用。

Mybatis日志加载顺序

三、Mybatis支持哪些日志

Mybatis支持哪些日志的配置,那就要看我们的主配置文件中settings配置了,配置如下


日志实现指定

说白了就是支持常用实现JUL(java util logging)、logback、log4j、log4j2,而SLF4J和COMMONS_LOGGING其实就是日志门面技术,也就是接口。关于日志框架我们后续,会单独讲一下。

四、日志演示

1.STDOUT_LOGGING

STDOUT_LOGGING :是Mybatis内置实现,只做控制台输出。配置只需一步,也不需要引入第三方依赖:

  • 指定settings配置
<setting name="logImpl" value="STDOUT_LOGGING"/>
  • 效果图

运行结果

2.SLF4J

首先声明SLF4J是日志门面技术,通过一系列中间转换操作,可以适配现有的任何日志技术。本节只做简单的配置实现logback。

  • 引入第三方包
<!--这个依赖直接包含了 logback-core实现 以及 slf4j-api日志门面的依赖-->
<dependency>
		<groupId>ch.qos.logback</groupId>
		<artifactId>logback-classic</artifactId>
		<version>1.2.11</version>
</dependency>
  • 指定settings配置

不配置也行,第三方日志只有一个日志实现的情况下,有默认加载顺序,详见:第二部分、日志配置

<!--使用logback-->
<setting name="logImpl" value="SLF4J"/>
  • 引入logback配置文件:logback.xml

开启debug级别,用于输出SQL语句。

<?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] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/smifc.log.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>20</maxHistory>
            <totalSizeCap>100GB</totalSizeCap>
        </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>
    </appender>
    <!-- 日志输出级别 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
    </root>
    <root level="DEBUG">
        <appender-ref ref="FILE"/>
    </root>
</configuration>
  • 效果图

logback

3.JDK_LOGGING

JDK_LOGGING是个啥?其实它就是JDK自带的日志。也不需要我们引入第三方包。

jdk自带的日志,配置文件加载有三种方法:1.默认路径【JRE_HOME/lib/logging.properties】;2.自定义加载配置文件路径【java.util.logging.config.file】;3.自定义加载配置类【java.util.logging.config.class】需要通过readConfiguration(InputStream) 实现

看下JDK源码LogManager加载配置实现:

JDK源码LogManager加载配置实现

  • 自定义加载配置文件路径【java.util.logging.config.file】实现

自定义加载路径

  • 引入logging.properties
handlers=java.util.logging.ConsoleHandler
.level=ALL

#mapper的命名空间
test=ALL

java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tT.%1$tL %4$s %3$s - %5$s%6$s%n
  • 主配置文件指定日志实现
<setting name="logImpl" value="JDK_LOGGING"/>
  • 效果图

运行结果

4.LOG4J、LOG4J2

LOG4J(log4j.properties)、LOG4J2(log4j2.xml)这两个实现和logback实现大同小异,直接引入实现jar包,变更主配置实现即可。

  • jar包引入

引入jar包

  • 主配置配置

指定日志实现

  • 配置文件

配置文件

  • 运行结果

运行结果

5.COMMONS_LOGGING

COMMONS_LOGGING (commons-logging.properties)是一个日志门面技术,也就是接口,其自身自带简单实现org.apache.commons.logging.impl.SimpleLog也支持jdk的日志实现。这里我们引入commons-logging包使用其的简单日志实现。

另外,支持的实现如下:

 //LogFactoryImpl.java
 private static final String[] classesToDiscover=new String[]{"org.apache.commons.logging.impl.Log4JLogger", "org.apache.commons.logging.impl.Jdk14Logger", "org.apache.commons.logging.impl.Jdk13LumberjackLogger", "org.apache.commons.logging.impl.SimpleLog"};
  • 只引入commons-logging包
<!--commons-logging-->
<dependency>
 <groupId>commons-logging</groupId>
 <artifactId>commons-logging</artifactId>
 <version>1.2</version>
</dependency>
  • 定义commons-logging.properties指明使用的日志实现
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
  • 定义simplelog.properties配置日志信息
org.apache.commons.logging.simplelog.defaultlog=all
org.apache.commons.logging.simplelog.log.test=all
org.apache.commons.logging.simplelog.showlogname=true
org.apache.commons.logging.simplelog.showShortLogname=true
org.apache.commons.logging.simplelog.showdatetime=true
org.apache.commons.logging.simplelog.dateTimeFormat=yyyy-MM-dd hh:mm:ss
  • 主配置指定实现
<!--使用COMMONS_LOGGING简单日志-->
<setting name="logImpl" value="COMMONS_LOGGING"/>
  • 效果

运行结果

五、总结

在以上的日志配置中,我引入了所有的日志实现,通过控制主配置文件中配置

 <setting name="logImpl" value="XXX"/>

达到,具体要使用哪个的目的。如果整合Mybatis时有多个日志实现,可通过此配置控制。