mybatis分页拦截器自动封装版讲解.docx
- 文档编号:4753570
- 上传时间:2022-12-08
- 格式:DOCX
- 页数:27
- 大小:25.88KB
mybatis分页拦截器自动封装版讲解.docx
《mybatis分页拦截器自动封装版讲解.docx》由会员分享,可在线阅读,更多相关《mybatis分页拦截器自动封装版讲解.docx(27页珍藏版)》请在冰豆网上搜索。
mybatis分页拦截器自动封装版讲解
近期由于工作需要,想要开发一版能够满足多数人员使用的mybatis分页拦截器,在网上查找了很多资料并结合自己的一些理解,开发出了以下一版简单的代码。
起初想要遵循江湖惯例,通过各个层级间传递分页参数来实现目标,但开发过程中发现这样针对已开发好的代码影响较大(需要修改前端到后端的所有代码),成本较高。
然后在此基础上提升了目标
1、降低业务代码侵入性。
2、减少原有代码的修改。
3、减少调用人员开发量。
虽然最终版本在初次配置使用时会有一些繁琐,但后续扩展非常有优势。
废话少说,上配置过程和代码。
使用方法
1、将java文件放置到某个文件夹下
2、添加maven依赖mybatis主要是拦截器部分,可自行在内部资源库中搜索或在网上搜索
3、配置springmybatis部分。
4、根据需要修改spring-mybatis文件。
5、Mapper文件中配置以”ForPage”结尾的查询,如
select
distinctt.*
fromtablet
groupbyt.id
5、jsp页面引入 importurl="/page/page.jsp"/> java代码 分页信息实体 /** *分页信息 */ publicclassPageBean{ privateintDEF_PAGE_VIEW_SIZE=15; /**当前页*/ privateintpageNo=1; /**当前页显示记录条数*/ privateintpageSize; /**取得查询总记录数*/ privateinttotalRecord; /***总页数**/ privateinttotalPage; privateStringactionUrl; privateMap publicStringgetActionUrl(){ returnactionUrl; } publicvoidsetActionUrl(StringactionUrl){ this.actionUrl=actionUrl; } publicMap returnparams; } publicvoidsetParams(Map this.params=params; } /** *(空) */ publicPageBean(){ this.pageNo=1; this.pageSize=DEF_PAGE_VIEW_SIZE; } /** *根据当前显示页与每页显示记录数设置查询信息初始对象 * *@parampageNo当前显示页号 *@parampageSize当前页显示记录条数 */ publicPageBean(intpageNo,intpageSize){ this.pageNo=(pageNo<=0)? 1: pageNo; this.pageSize=(pageSize<=0)? DEF_PAGE_VIEW_SIZE: pageSize; } /** *取得当前显示页号 * *@return当前显示页号 */ publicintgetPageNo(){ return(pageNo<=0)? 1: pageNo; } /** *设置当前页 * *@parampageNo当前页 */ publicvoidsetPageNo(intpageNo){ this.pageNo=pageNo; } /** *取得当前显示页号最多显示条数 * *@return当前显示页号最多显示条数 */ publicintgetPageSize(){ return(pageSize<=0)? DEF_PAGE_VIEW_SIZE: pageSize; } /** *设置当前页显示记录条数 * *@parampageSize当前页显示记录条数 */ publicvoidsetPageSize(intpageSize){ this.pageSize=pageSize; } publicintgetTotalRecord(){ returntotalRecord; } publicvoidsetTotalRecord(inttotalRecord){ this.totalRecord=totalRecord; //在设置总页数的时候计算出对应的总页数,在下面的三目运算中加法拥有更高的优先级,所以最后可以不加括号。 inttotalPage=totalRecord%pageSize==0? totalRecord/pageSize : totalRecord/pageSize+1; this.setTotalPage(totalPage); } publicintgetTotalPage(){ returnthis.totalPage; } publicvoidsetTotalPage(inttotalPage){ this.totalPage=totalPage; } } 分页信息操作帮助类,用于贯穿单次请求的各个层级 /** *PageBean操作帮助类 */ publicclassPageBeanUtils{ //定义一个当前线程对象,处于该主线程内的所有类均可调用该对象中的pagebean publicstaticThreadLocal publicstaticPageBeangetPageBean(){ PageBeanpageBean=local.get(); if(pageBean==null){ pageBean=newPageBean(); } returnpageBean; } publicstaticvoidsetPageBean(PageBeanpageBean){ local.set(pageBean); } } Controller拦截器,用于在执行前后封装或获取分页信息 importcom.xx.xx.util.StringUtils; importorg.springframework.web.servlet.ModelAndView; importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importjava.util.Enumeration; importjava.util.HashMap; importjava.util.Map; /** *分页自动封装拦截,在controller执行前后对PageBean进行读取和设置 */ publicclassPageSpringMVCInterceptorextendsHandlerInterceptorAdapter{ /** *preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在 *多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在 *Controller方法调用之前调用。 SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返 *回值为false,当preHandle的返回值为false的时候整个请求就结束了。 */ @Override publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse, Objecthandler){ PageBeanpageBean=newPageBean(); //进入Controller前封装page StringpageNo=request.getParameter("pageNo"); StringpageSize=request.getParameter("pageSize"); if(StringUtils.isNotEmpty(pageNo)){ pageBean.setPageNo(Integer.parseInt(pageNo)); } if(StringUtils.isNotEmpty(pageSize)){ pageBean.setPageSize(Integer.parseInt(pageSize)); } Stringurl=request.getRequestURI(); Enumerationenumeration=request.getParameterNames(); //绑定action地址 pageBean.setActionUrl(url); Map while(enumeration.hasMoreElements()){ Objectobj=enumeration.nextElement(); if(objinstanceofString){ Stringparaname=String.valueOf(obj); try{ //过滤掉页面标签 if(pageBean.getClass().getDeclaredField(paraname)! =null){ continue; } }catch(NoSuchFieldExceptione){ } StringparaValue=request.getParameter(paraname); params.put(paraname,paraValue); } } //绑定参数 pageBean.setParams(params); PageBeanUtils.setPageBean(pageBean); returntrue; } /** *这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。 postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之 *后,也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操 *作。 这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,这跟Struts2里面的拦截器的执行过程有点像, *只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法 *,Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor *或者是调用action,然后要在Interceptor之前调用的内容都写在调用invoke之前,要在Interceptor之后调用的内容都写在调用invoke方法之后。 */ @Override publicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler, ModelAndViewmodelAndView)throwsException{ /** *不支持AJAX请求 */ PageBeanpageBean=PageBeanUtils.getPageBean(); StringrequestType=request.getHeader("X-Requested-With"); if(requestType! =null&&requestType.length()>0 &&requestType.equals("XMLHttpRequest")){ }else{ request.setAttribute("_pageBean",pageBean); } } /** *该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行, *这个方法的主要作用是用于清理资源的,当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。 */ @Override publicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse, Objecthandler,Exceptionex)throwsException{} } Mybatis分页拦截器,用于在执行查询时的分页处理 importmon.ReflectionUtils; importorg.apache.ibatis.executor.parameter.ParameterHandler; importorg.apache.ibatis.executor.statement.RoutingStatementHandler; importorg.apache.ibatis.executor.statement.StatementHandler; importorg.apache.ibatis.mapping.BoundSql; importorg.apache.ibatis.mapping.MappedStatement; importorg.apache.ibatis.plugin.*; importorg.apache.ibatis.session.Configuration; importjava.sql.Connection; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.SQLException; importjava.util.Properties; @Intercepts({@Signature(type=StatementHandler.class,method="prepare", args={Connection.class})}) /** *mybatis分页拦截器所有以ForPage结尾的查询方法,获取分页条件并动态添加分页 */ publicclassPageStatementHandlerInterceptorimplementsInterceptor{ /** *分页拦截器。 * *功能主要是用来取总记录数和对SQL分页拦截。 * *@paraminvocation *@return *@throwsThrowable */ publicObjectintercept(Invocationinvocation)throwsThrowable{ RoutingStatementHandlerhandler=(RoutingStatementHandler)invocation.getTarget(); //通过反射获取到当前RoutingStatementHandler对象的delegate属性 StatementHandlerdelegate= (StatementHandler)ReflectionUtils.getFieldValue(handler,"delegate"); //通过反射获取delegate父类BaseStatementHandler的mappedStatement属性 MappedStatementmappedStatement=(MappedStatement)ReflectionUtils.getFieldValue(delegate, "mappedStatement"); if(mappedStatement! =null){ //获取方法名,如果方法是以PAGE结尾的,则加工sql语句,添加分页 Stringid=mappedStatement.getId(); if(id.toUpperCase().endsWith("FORPAGE")){ //获取sql绑定对象 BoundSqlboundSql=delegate.getBoundSql(); //拿到当前绑定Sql的参数对象,就是我们在调用对应的Mapper映射语句时所传入的参数对象parameterType PageBeanpageBean=PageBeanUtils.getPageBean(); //获取当前要执行的Sql语句,也就是我们直接在Mapper映射语句中写的Sql语句 Stringsql=boundSql.getSql(); //给当前的page参数对象设置总记录数 this.setTotalRecord(mappedStatement,boundSql,pageBean, (Connection)invocation.getArgs()[0]); //获取分页Sql语句 StringpageSql=this.getPageSql(pageBean,sql); //利用反射设置当前BoundSql对应的sql属性为我们建立好的分页Sql语句 ReflectionUtils.setFieldValue(boundSql,"sql",pageSql); } } returninvocation.proceed(); } /** *拦截器对应的封装原始对象的方法 */ publicObjectplugin(Objecttarget){ if(targetinstanceofStatementHandler){ returnPlugin.wrap(target,this); }else{ returntarget; } } /** *设置注册拦截器时设定的属性 * *@paramproperties */ publicvoidsetProperties(Propertiesproperties){} /** *根据page对象获取对应的分页查询Sql语句,这里只做了两种数据库类型,Mysql和Oracle其它的数据库都没有进行分页 * *@parampage分页对象 *@paramsql原sql语句 *@return */ privateStringgetPageSql(PageBeanpage,Stringsql){ StringBuffersqlBuffer=newStringBuffer(sql); returngetMysqlPageSql(page,sqlBuffer); } /** *获取Mysql数据库的分页查询语句 * *@parampage分页对象 *@paramsqlBuffer包含原sql语句的StringBuffer对象 *@returnMysql数据库分页语句 */ privateStringgetMysqlPageSql(PageBeanpage,StringBuffersqlBuffer){ //计算第一条记录的位置,Mysql中记录的位置是从0开始的。 intoffset=(page.getPageNo()-1)*page.getPageSize(); sqlBuffer.append("limit").append(offset).append(",").append(page.getPageSize()); returnsqlBuffer.toString(); } /** *给当前的参数对象page设置总记录数 */ privatevoidsetTotalRecord(MappedStatementmappedStatement,BoundSqlboundSql, PageBeanpageBean,Connectionconnection){ Stringsql=boundSql.getSql(); StringcountSql=getCountSql(sql.trim()); PreparedStatementcountStmt=null; ResultSetrs=null; try{ countStmt=connection.prepareStatement(countSql); //向countStmt中传递参数 Configurationconfiguration=mappedStatement.getConfiguration(); ParameterHandlerhandler=configuration.newParam
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- mybatis 分页 拦截 自动 封装 讲解
![提示](https://static.bdocx.com/images/bang_tan.gif)