Kevin's Zone

  • Home
  • Project
  • ContactMe
  • Login
  • Register
Kevin
受苦即了苦, 享福即消福, 福尽而死
  1. 首页
  2. 学习笔记
  3. 正文

在SpringBoot使用PageHelper5插件来MyBatis分页查询

2017年12月5日 4359点热度 3人点赞 0条评论

[title]引入Jar包[/title]

<!-- MyBatis分页插件 -->
<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>5.1.2</version>
</dependency>

 

[title]SqlSessionFactory加入此插件[/title]

使用Boot代码的方式管理Bean

PageHelper在5以前版本需要用PageHelper, 5以后的版本改为PageInterceptor

PageHelper可以自动识别方言, 而且手动指定方言会报错不知道为什么, 所以先不指定方言了.

@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
	SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
	PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
	sqlSessionFactory.setDataSource(dataSource());
	sqlSessionFactory.setConfigLocation(resolver.getResource(mabatisConf));
	sqlSessionFactory.setMapperLocations(resolver.getResources(mapperLocations));

	/* PageHelper分页配置开始 */
	PageInterceptor pageInterceptor = new PageInterceptor();
	Properties properties = new Properties();
	properties.setProperty("offsetAsPageNum", "true");
	properties.setProperty("rowBoundsWithCount", "true");
	properties.setProperty("reasonable", "true");
	pageInterceptor.setProperties(properties);
	/* PageHelper分页配置结束 */

	sqlSessionFactory.setPlugins(new Interceptor[] { pageInterceptor });

	return sqlSessionFactory.getObject();
}

 

[title]定义PageBean[/title]

根据项目情况来定义一个PageBean, 用来获取分页之后的结果, 这里直接采用作者提供的例子, 有不需要的属性可以删掉.

/**
 * 保存分页之后的结果
 * 
 * @author Kevin
 *
 * @param <T>
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class PageBean<T> implements Serializable {
	private static final long serialVersionUID = 1L;
	/** 当前页 */
	private int pageNum;
	/** 每页的数量 */
	private int pageSize;
	/** 当前页的数量 */
	private int size;
	/** 当前页面第一个元素在数据库中的行号 */
	private int startRow;	// 由于startRow和endRow不常用, 这里说个具体的用法, 可以在页面中"显示startRow到endRow 共size条数据"
	/** 当前页面最后一个元素在数据库中的行号 */
	private int endRow;
	/** 总记录数 */
	private long total;
	/** 总页数 */
	private int pages;
	/** 结果集 */
	private List<T> list;
	/** 第一页 */
	private int firstPage;
	/** 前一页 */
	private int prePage;
	/** 下一页 */
	private int nextPage;
	/** 最后一页 */
	private int lastPage;
	/** 是否为第一页 */
	private boolean isFirstPage = false;
	/** 是否为最后一页 */
	private boolean isLastPage = false;
	/** 是否有前一页 */
	private boolean hasPreviousPage = false;
	/** 是否有下一页 */
	private boolean hasNextPage = false;
	/** 导航页码数 */
	private int navigatePages;
	/** 所有导航页号 */
	private int[] navigatepageNums;

	/**
	 * 包装Page对象
	 *
	 * @param list
	 */
	public PageBean(List<T> list) {
		this(list, 8);
	}

	/**
	 * 包装Page对象, 因为直接返回Page对象, 在JSON处理以及其他情况下会被当成List来处理而出现一些问题.
	 *
	 * @param list page结果
	 * @param navigatePages 页码数量
	 */
	public PageBean(List<T> list, int navigatePages) {
		if (list instanceof Page) {
			Page page = (Page) list;
			this.pageNum = page.getPageNum();
			this.pageSize = page.getPageSize();

			this.total = page.getTotal();
			this.pages = page.getPages();
			this.list = page;
			this.size = page.size();
			// 由于结果是>startRow的,所以实际的需要+1
			if (this.size == 0) {
				this.startRow = 0;
				this.endRow = 0;
			} else {
				this.startRow = page.getStartRow() + 1;
				// 计算实际的endRow(最后一页的时候特殊)
				this.endRow = this.startRow - 1 + this.size;
			}
			this.navigatePages = navigatePages;
			// 计算导航页
			calcNavigatepageNums();
			// 计算前后页,第一页,最后一页
			calcPage();
			// 判断页面边界
			judgePageBoudary();
		}
	}

	/**
	 * 计算导航页
	 */
	private void calcNavigatepageNums() {
		// 当总页数小于或等于导航页码数时
		if (pages <= navigatePages) {
			navigatepageNums = new int[pages];
			for (int i = 0; i < pages; i++) {
				navigatepageNums[i] = i + 1;
			}
		} else { // 当总页数大于导航页码数时
			navigatepageNums = new int[navigatePages];
			int startNum = pageNum - navigatePages / 2;
			int endNum = pageNum + navigatePages / 2;

			if (startNum < 1) {
				startNum = 1;
				// (最前navigatePages页
				for (int i = 0; i < navigatePages; i++) {
					navigatepageNums[i] = startNum++;
				}
			} else if (endNum > pages) {
				endNum = pages;
				// 最后navigatePages页
				for (int i = navigatePages - 1; i >= 0; i--) {
					navigatepageNums[i] = endNum--;
				}
			} else {
				// 所有中间页
				for (int i = 0; i < navigatePages; i++) {
					navigatepageNums[i] = startNum++;
				}
			}
		}
	}

	/**
	 * 计算前后页, 第一页, 最后一页
	 */
	private void calcPage() {
		if (navigatepageNums != null && navigatepageNums.length > 0) {
			firstPage = navigatepageNums[0];
			lastPage = navigatepageNums[navigatepageNums.length - 1];
			if (pageNum > 1) {
				prePage = pageNum - 1;
			}
			if (pageNum < pages) {
				nextPage = pageNum + 1;
			}
		}
	}

	/**
	 * 判定页面边界
	 */
	private void judgePageBoudary() {
		isFirstPage = pageNum == 1;
		isLastPage = pageNum == pages;
		hasPreviousPage = pageNum > 1;
		hasNextPage = pageNum < pages;
	}

	public void setPageNum(int pageNum) {
		this.pageNum = pageNum;
	}

	public int getPageNum() {
		return pageNum;
	}

	public int getPageSize() {
		return pageSize;
	}

	public int getSize() {
		return size;
	}

	public int getStartRow() {
		return startRow;
	}

	public int getEndRow() {
		return endRow;
	}

	public long getTotal() {
		return total;
	}

	public int getPages() {
		return pages;
	}

	public List<T> getList() {
		return list;
	}

	public int getFirstPage() {
		return firstPage;
	}

	public int getPrePage() {
		return prePage;
	}

	public int getNextPage() {
		return nextPage;
	}

	public int getLastPage() {
		return lastPage;
	}

	public boolean isIsFirstPage() {
		return isFirstPage;
	}

	public boolean isIsLastPage() {
		return isLastPage;
	}

	public boolean isHasPreviousPage() {
		return hasPreviousPage;
	}

	public boolean isHasNextPage() {
		return hasNextPage;
	}

	public int getNavigatePages() {
		return navigatePages;
	}

	public int[] getNavigatepageNums() {
		return navigatepageNums;
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer("PageInfo{");
		sb.append("pageNum=").append(pageNum);
		sb.append(", pageSize=").append(pageSize);
		sb.append(", size=").append(size);
		sb.append(", startRow=").append(startRow);
		sb.append(", endRow=").append(endRow);
		sb.append(", total=").append(total);
		sb.append(", pages=").append(pages);
		sb.append(", list=").append(list);
		sb.append(", firstPage=").append(firstPage);
		sb.append(", prePage=").append(prePage);
		sb.append(", nextPage=").append(nextPage);
		sb.append(", lastPage=").append(lastPage);
		sb.append(", isFirstPage=").append(isFirstPage);
		sb.append(", isLastPage=").append(isLastPage);
		sb.append(", hasPreviousPage=").append(hasPreviousPage);
		sb.append(", hasNextPage=").append(hasNextPage);
		sb.append(", navigatePages=").append(navigatePages);
		sb.append(", navigatepageNums=");
		if (navigatepageNums == null)
			sb.append("null");
		else {
			sb.append('[');
			for (int i = 0; i < navigatepageNums.length; ++i)
				sb.append(i == 0 ? "" : ", ").append(navigatepageNums[i]);
			sb.append(']');
		}
		sb.append('}');
		return sb.toString();
	}
}

 

[title]定义PaginationContext传递分页参数[/title]

方便传递/获取分页参数, 定义一个工具类, 后面再配合Filter拦截

/**
 * 基于 ThreadLocal 来传递分页参数的一个工具类
 * 
 * @author Kevin
 *
 */
public class PaginationContext {
	private static ThreadLocal<Integer> pageNum = new ThreadLocal<Integer>();	// 保存第几页
	private static ThreadLocal<Integer> pageSize = new ThreadLocal<Integer>();	// 保存每页记录条数

	public static int getPageNum() {
		Integer pn = pageNum.get();
		if (pn == null) {
			return 0;
		}
		return pn;
	}

	public static void setPageNum(int pageNumValue) {
		pageNum.set(pageNumValue);
	}

	public static void removePageNum() {
		pageNum.remove();
	}

	public static int getPageSize() {
		Integer ps = pageSize.get();
		if (ps == null) {
			return 0;
		}
		return ps;
	}

	public static void setPageSize(int pageSizeValue) {
		pageSize.set(pageSizeValue);
	}

	public static void removePageSize() {
		pageSize.remove();
	}
}

ThreadLocal解决多线程并发处理同一变量.

[title]定义Filter拦截分页参数[/title]

/**
 * 分页拦截过滤器, pageNum, pageSize</br>
 * Order注解表示执行过滤顺序,值越小,越先执行
 * 
 * @author Kevin
 *
 */
@Order(1)
@WebFilter(filterName = "PageFilter", urlPatterns = "/*")
public class PageFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

		HttpServletRequest httpRequest = (HttpServletRequest) request;

		PaginationContext.setPageNum(getPageNum(httpRequest));
		PaginationContext.setPageSize(getPageSize(httpRequest));

		try {
			chain.doFilter(request, response);
		} finally {
			// 使用完Threadlocal, 将其删除
			PaginationContext.removePageNum();
			PaginationContext.removePageSize();
		}
	}

	/**
	 * 设置页码
	 * 
	 * @param request
	 * @return
	 */
	protected int getPageNum(HttpServletRequest request) {
		int pageNum = 1;
		try {
			String pageNums = request.getParameter("pageNum");
			if (pageNums != null && StringUtils.isNumeric(pageNums)) {
				pageNum = Integer.parseInt(pageNums);
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		return pageNum;
	}

	/**
	 * 设置默认每页大小
	 * 
	 * @return
	 */
	protected int getPageSize(HttpServletRequest request) {
		int pageSize = 10; // 默认每页10条记录
		try {
			String pageSizes = request.getParameter("pageSize");
			if (pageSizes != null && StringUtils.isNumeric(pageSizes)) {
				pageSize = Integer.parseInt(pageSizes);
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		return pageSize;
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub

	}

}

 

[title]实现[/title]

public Object getUserList() {
	PageHelper.startPage(PaginationContext.getPageNum(), PaginationContext.getPageSize());
	List<User> list = userDao.getUserList();
	return new PageBean<User>(list);
}

 

标签: 暂无
最后更新:2017年12月5日

Kevin

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2021 Kevin's Zone. ALL RIGHTS RESERVED.

京ICP备16064400号-1