使用ThreadLocal存储分页参数

目录

前言

一、代码实现

        1.工具类

        2.拦截器

         3.配置类

        4.使用

二、总结


前言

使用ThreadLocal对存储分页参数有以下好处:

  1. 避免多层级参数传递:在复杂的系统或框架中,分页参数可能需要跨越多个层级进行传递。使用ThreadLocal可以避免这种多层级传递,使代码更加简洁和易于维护。
  2. 提高性能:ThreadLocal避免了使用线程同步机制(如锁)来保护共享数据,从而提高程序的并发性能。由于每个线程都拥有自己的数据副本,因此不会出现线程间的竞争和冲突,从而避免了锁竞争带来的性能损耗。
  3. 便于管理线程特定的资源:在某些场景下,我们需要为每个线程分配一些特定的资源,并且在线程结束时进行清理工作。ThreadLocal可以通过在对象中存储和管理线程特定的资源,使得这些资源能够方便地与线程相关联,同时在线程结束时自动清理。
  4. 解决上下文切换问题:在一些需要维护上下文关系的场景中,例如数据库连接、会话管理等,使用ThreadLocal可以很好地解决上下文切换的问题。通过将上下文相关的信息存储在ThreadLocal中,可以在同一线程内共享这些信息,而无需通过参数传递或全局变量访问来维护。

一、代码实现

        1.工具类

                在工具类中,通过封装ThreadLocal,并提供将分页参数封装进ThreadLocal的几个方法。

package com.pzg.chat.utils;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

public class PageUtil {

	private static ThreadLocal> pageThreadLocal = new ThreadLocal<>();

	public static void setPage(Integer currentPage,Integer size){
		pageThreadLocal.set(new Page<>(currentPage,size));
	}

	public static long getCurrentPage(){
		long size = pageThreadLocal.get().getSize();
		return (pageThreadLocal.get().getCurrent()-1)*size;
	}

	public static long getLimitPage(){
		long size = pageThreadLocal.get().getSize();
		return (pageThreadLocal.get().getCurrent()-1)*size;
	}

	public static long getSize(){
		return pageThreadLocal.get().getSize();
	}

	public static void removeThreadLocal(){
		pageThreadLocal.remove();
	}
}

        2.拦截器

        在拦截器中,当请求进入方法前,获取request中分页的字段参数,然后通过调用PageUtil.setPage(page,size);方法,将分页参数存储到ThreadLocal当中

@Component
public class PageInterception implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String currentPage = request.getParameter("currentPage");
		String currentSize = request.getParameter("size");
		Integer page = Integer.valueOf(currentPage != null ? currentPage : "1");
		Integer size = Integer.valueOf(currentSize != null ? currentSize : "10");
		PageUtil.setPage(page,size);
		return true;
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
			PageUtil.removeThreadLocal();
	}
}

       注意:前端分页参数字段当前页currentPage,每页显示的字段为size,可自行修改。

         3.配置类

                通过配置类注册拦截器,让拦截器起到拦截的效果,若不配置,则拦截器不生效。

@Configuration
@SuppressWarnings("all")
public class WebMvcConfig implements WebMvcConfigurer {



	@Autowired
	private LimitInterception limitInterception;

	@Autowired
	private PageInterception pageInterception;

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(pageInterception);
	}

	/**
	 * 解决跨域
	 * @param registry
	 */
	@Override
	public void addCorsMappings(CorsRegistry registry) {

		registry
				//运行所有方式请求
				.addMapping("/**")
				//运行跨域请求的域名
				.allowedOrigins("*")
				//是否允许证书
				.allowCredentials(true)
				//运行任何头
				.allowedHeaders("*")
				//运行的方法
				.allowedMethods("*");
	}
}

        4.使用

                在Mybatis中通过PageUtil.getLimitPage(), PageUtil.getSize()来获取当前页和每页显示条数。

 Page page = new Page<>(PageUtil.getLimitPage(), PageUtil.getSize());

                在SQL语句中通过传入PageUtil.getCurrentPage(),PageUtil.getSize(),因为SQL当前页需要(当前页-1)*每页显示条数;

二、总结

        通过ThreadLocal加上拦截器,我们就不需要在Controller通过获取分页的参数来写许多重复的代码,而是通过自己封装的一个工具类,如果想要分页参数时调用工具类里边的方法即可,大大降低了代码的耦合度。

你可能感兴趣的:(springboot,spring,boot,java,spring)