SpringBoot使用Mybatis分页插件(10)

一、配置分页插件

(1)先导入依赖。

        <!-- 分页工具pageHelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.10</version>
        </dependency>

(2)在yml中加入分页配置。这里指明是mysql数据库。配置部分搭建完毕。

spring:
  pagehelper:
    #指明数据库
    helperDialect: mysql
    # when pageNum<=0 ,query first page
    # when pageNum > max count , query last page
    reasonable: true
    supportMethodsArguments: true
    params: count=countSql 

二、编写拦截器

分页插件提供的主要类叫做: PageRowBounds。

一般分页传递的参数是 start  、page 、 limit。

编写如下的拦截器,拦截住前端的分页相关参数。根据这些分页参数,构造出分页插件需要的PageRowBounds对象。 然后再把这个PageRowBounds对象存放到当前线程中,这里使用到了ThreadLocal技术。ThreadLocal技术的原理就是,把要被存放的数据作为"线程局部变量"存放到线程中。以后不管这个线程执行到哪里,都能够取到 "线程局部变量"。最后当请求执行完毕后,再用拦截器的后处理PostHandler,清除掉"线程局部变量"。

(1)编写分页拦截器。

package com.hanzhenya.learnspringboot.interceptor;
 
 
import com.github.pagehelper.PageRowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@Component
public class PageHelperInterceptor extends HandlerInterceptorAdapter {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(PageHelperInterceptor.class);
 
    private static final String PAGE = "page";
    private static final String LIMIT = "limit";
    private static final int DEFAULT_PAGE_INDEX = 0;
    private static final int DEFAULT_PAGE_SIZE = 10;
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 
        //原生的int类型可能会有空指针异常,无法将null赋值给基本数据类型
        Integer page = ServletRequestUtils.getIntParameter(request, PAGE);
        Integer limit = ServletRequestUtils.getIntParameter(request, LIMIT);
        if (null == page || page < 1) {
            page = DEFAULT_PAGE_INDEX;
        } else {
            page = page - 1;
        }
        if (null == limit || limit < 0) {
            limit = DEFAULT_PAGE_SIZE;
        }
        int start = page * limit;
 
        LOGGER.info("分页资源预处理");
        LOGGER.info("从第{}条记录开始查询,共查询{}条记录", start + 1, limit);
 
        //generate an page object and put it into threadLocal
        PageRowBounds pageRowBounds = new PageRowBounds(start, limit);
        PageHelperThreadLocal.setPageInfo(pageRowBounds);
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        //when the business process has been completed,
        //removing page object which is in the threadLocal
        PageHelperThreadLocal.clean();
    }
 
}

(2)编写ThreadLocal,用于存放线程局部变量

package com.hanzhenya.learnspringboot.interceptor;
 
 
import com.github.pagehelper.PageRowBounds;
 
public final class PageHelperThreadLocal {
 
    private static final ThreadLocal<PageRowBounds> PAGE_INFO = new ThreadLocal<>();
 
    /**
     * 为调用的线程存储 线程局部变量 PageRowBounds(分页信息封装在此对象里)
     */
    public static void setPageInfo(PageRowBounds rowBounds) {
        PAGE_INFO.set(rowBounds);
    }
 
    /**
     * 获取调用此方法的线程的 线程局部变量 PageRowBounds
     */
    public static PageRowBounds getPageInfo() {
        return PAGE_INFO.get();
    }
 
    /**
     * 清除掉当前线程中的线程局部变量
     */
    public static void clean() {
        PAGE_INFO.remove();
    }
}

(3)将拦截器配置到项目中。

package com.hanzhenya.learnspringboot.config;
 
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.zhoutianyu.learnspringboot.interceptor.MyInterceptor;
import com.zhoutianyu.learnspringboot.interceptor.PageHelperInterceptor;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
import javax.annotation.Resource;
 
@Configuration
public class CustomWebConfigure implements WebMvcConfigurer {
 
    @Resource
    private PageHelperInterceptor pageHelperInterceptor;
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(pageHelperInterceptor).addPathPatterns("/**").excludePathPatterns("/static/**");
    }
}  

三、调用分页工具
         编写Controller、Mapper、mapper.xml进行测试。

         重点需要关注的是如何使用分页插件。

         在Dao层查询的方法上,一定要将分页对象PageRowBounds作为方法的参数,才能使用我们的分页插件。

package com.hanzhenya.learnspringboot.mybatis;
 
import com.zhoutianyu.learnspringboot.interceptor.PageHelperThreadLocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.List;
 
@RestController
public class UserController {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
 
    @Autowired
    private UserMapper mapper;
 
    @GetMapping(value = "mybatis/getUsers")
    public List<User> getUsers() {
        return mapper.getUsers(PageHelperThreadLocal.getPageInfo());
    }
}

 mapper层

package com.hanzhenya.learnspringboot.mybatis;
 
import com.github.pagehelper.PageRowBounds;
import org.apache.ibatis.annotations.Mapper;
 
import java.util.List;
 
@Mapper
public interface UserMapper {
 
    List<User> getUsers(PageRowBounds pageRowBounds);
}

 xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hanzhenya.learnspringboot.mybatis.UserMapper">
    <resultMap id="BaseResultMap" type="com.hanzhenya.learnspringboot.mybatis.User">
 
        <id column="id" jdbcType="BIGINT" property="id"/>
        <result column="username" jdbcType="VARCHAR" property="username"/>
        <result column="age" jdbcType="INTEGER" property="age"/>
    </resultMap>
    <sql id="Base_Column_List">
    id, username, age
  </sql>
 
    <select id="getUsers" resultType="com.hanzhenya.learnspringboot.mybatis.User">
        select
        <include refid="Base_Column_List"/>
        from t_user
    </select>
</mapper>

  注意:在实际使用过程中还需要考虑数据库的数据量。如果某张表的数据量很大,动辄三四十万条记录,手动分页还是有必要的。因此,分表在数据库设计过程也是十分重要的。对于分页插件来说,分页插件也不是万能的,它还是把查到的数据存储到内存中,可能会导致内存溢出风险

posted @ 2021-03-31 16:39  hzy_叶子  阅读(145)  评论(0编辑  收藏  举报