当前位置: 首页 > news >正文

天津网站建设是什么双11销量数据

天津网站建设是什么,双11销量数据,wordpress怎么建一个文章链接页面,做思维导图的网站目录 分页插件 Mybatis插件典型适用场景 实现思考 第一个问题 第二个问题 自定义分页插件 分页插件使用 添加pom依赖 插件注册 调用 代理和拦截是怎么实现的 PageHelper 原理 分页插件 MyBatis 通过提供插件机制,让我们可以根据自己的需要去增强MyBati…

目录

分页插件

Mybatis插件典型适用场景

实现思考

第一个问题

第二个问题

自定义分页插件

分页插件使用

添加pom依赖

插件注册

调用

代理和拦截是怎么实现的

PageHelper 原理


分页插件

MyBatis 通过提供插件机制,让我们可以根据自己的需要去增强MyBatis 的功能。需要注意的是,如果没有完全理解MyBatis 的运行原理和插件的工作方式,最好不要使用插件,因为它会改变系底层的工作逻辑,给系统带来很大的影响。

MyBatis 的插件可以在不修改原来的代码的情况下,通过拦截的方式,改变四大核心对象的行为,比如处理参数,处理SQL,处理结果。

Mybatis插件典型适用场景

分页功能

mybatis的分页默认是基于内存分页的(查出所有,再截取),数据量大的情况下效率较低,不过使用mybatis插件可以改变该行为,只需要拦截StatementHandler类的prepare方法,改变要执行的SQL语句为分页语句即可;

公共字段统一赋值

一般业务系统都会有创建者,创建时间,修改者,修改时间四个字段,对于这四个字段的赋值,实际上可以在DAO层统一拦截处理,可以用mybatis插件拦截Executor类的update方法,对相关参数进行统一赋值即可;

性能监控

对于SQL语句执行的性能监控,可以通过拦截Executor类的update, query等方法,用日志记录每个方法执行的时间;

其它

其实mybatis扩展性还是很强的,基于插件机制,基本上可以控制SQL执行的各个阶段,如执行阶段,参数处理阶段,语法构建阶段,结果集处理阶段,具体可以根据项目业务来实现对应业务逻辑。

实现思考

第一个问题

 不修改对象的代码,怎么对对象的行为进行修改,比如说在原来的方法前面做一点事情,在原来的方法后面做一点事情?

  答案:大家很容易能想到用代理模式,这个也确实是MyBatis 插件的原理。

第二个问题

我们可以定义很多的插件,那么这种所有的插件会形成一个链路,比如我们提交一个休假申请,先是项目经理审批,然后是部门经理审批,再是HR 审批,再到总经理审批,怎么实现层层的拦截?

  答案:插件是层层拦截的,我们又需要用到另一种设计模式——责任链模式。

在之前的源码中我们也发现了,mybatis内部对于插件的处理确实使用的代理模式,既然是代理模式,我们应该了解MyBatis 允许哪些对象的哪些方法允许被拦截,并不是每一个运行的节点都是可以被修改的。只有清楚了这些对象的方法的作用,当我们自己编写插件的时候才知道从哪里去拦截。在MyBatis 官网有答案,我们来看一下:

mybatis – MyBatis 3 | 配置

Executor 会拦截到CachingExcecutor 或者BaseExecutor。因为创建Executor 时是先创建CachingExcecutor,再包装拦截。从代码顺序上能看到。我们可以通过mybatis的分页插件来看看整个插件从包装拦截器链到执行拦截器链的过程。

  在查看插件原理的前提上,我们需要来看看官网对于自定义插件是怎么来做的,官网上有介绍:通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。这里本人踩了一个坑,在Springboot中集成,同时引入了pagehelper-spring-boot-starter 导致RowBounds参数的值被刷掉了,也就是走到了我的拦截其中没有被设置值,这里需要注意,拦截器出了问题,可以Debug看一下Configuration配置类中拦截器链的包装情况。

自定义分页插件

@Intercepts({@Signature(type = Executor.class,method = "query" ,args ={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} ), // 需要代理的对象和方法@Signature(type = Executor.class,method = "query" ,args ={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class} ) // 需要代理的对象和方法
})
public class MyPageInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {System.out.println("简易版的分页插件:逻辑分页改成物理分页");// 修改sql 拼接Limit 0,10Object[] args = invocation.getArgs();// MappedStatement 对mapper映射文件里面元素的封装MappedStatement ms= (MappedStatement) args[0];// BoundSql 对sql和参数的封装Object parameterObject=args[1];BoundSql boundSql = ms.getBoundSql(parameterObject);// RowBounds 封装了逻辑分页的参数 :当前页offset,一页数limitRowBounds rowBounds= (RowBounds) args[2];// 拿到原来的sql语句String sql = boundSql.getSql();String limitSql=sql+ " limit "+rowBounds.getOffset()+","+ rowBounds.getLimit();//将分页sql重新封装一个BoundSql 进行后续执行BoundSql pageBoundSql = new BoundSql(ms.getConfiguration(), limitSql, boundSql.getParameterMappings(), parameterObject);// 被代理的对象Executor executor= (Executor) invocation.getTarget();CacheKey cacheKey = executor.createCacheKey(ms, parameterObject, rowBounds, pageBoundSql);// 调用修改过后的sql继续执行查询return  executor.query(ms,parameterObject,rowBounds, (ResultHandler) args[3],cacheKey,pageBoundSql);}
}

拦截签名跟参数的顺序有严格要求,如果按照顺序找不到对应方法会抛出异常:

org.apache.ibatis.exceptions.PersistenceException: ### Error opening session. Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface org.apache.ibatis.executor.Executor named query

MyBatis 启动时扫描 标签, 注册到Configuration 对象的 InterceptorChain 中。property 里面的参数,会调用setProperties()方法处理。

分页插件使用

添加pom依赖

<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>1.2.15</version>
</dependency>

插件注册

在mybatis-config.xml 中注册插件

<configuration><plugins><!-- com.github.pagehelper为PageHelper类所在包名 --><plugin interceptor="com.github.pagehelper.PageHelper"><property name="helperDialect" value="mysql" /><!-- 该参数默认为false --><!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 --><!-- 和startPage中的pageNum效果一样 --><property name="offsetAsPageNum" value="true" /><!-- 该参数默认为false --><!-- 设置为true时,使用RowBounds分页会进行count查询 --><property name="rowBoundsWithCount" value="true" /><!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 --><!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型) --><property name="pageSizeZero" value="true" /><!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 --><!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 --><!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 --><property name="reasonable" value="true" /><!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 --><!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 --><!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 --><!-- 不理解该含义的前提下,不要随便复制该配置 --><property name="params" value="pageNum=start;pageSize=limit;" /></plugin></plugins>
</configuration>

调用

// 获取配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis/mybatis-config.xml");
// 通过加载配置文件获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {// Mybatis在getMapper就会给我们创建jdk动态代理EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);PageHelper.startPage(1, 5);List<Emp> list=mapper.selectAll(); PageInfo<ServiceStation> info = new PageInfo<ServiceStation>(list, 3);                   System.out.println("当前页码:"+info.getPageNum());System.out.println("每页的记录数:"+info.getPageSize());System.out.println("总记录数:"+info.getTotal());System.out.println("总页码:"+info.getPages());System.out.println("是否第一页:"+info.isIsFirstPage());System.out.println("连续显示的页码:");int[] nums = info.getNavigatepageNums();for (int i = 0; i < nums.length; i++) {System.out.println(nums[i]);}     
}  

代理和拦截是怎么实现的

上面提到的可以被代理的四大对象都是什么时候被代理的呢?Executor 是openSession() 的时候创建的; StatementHandler 是SimpleExecutor.doQuery()创建的;里面包含了处理参数的ParameterHandler 和处理结果集的ResultSetHandler 的创建,创建之后即调用InterceptorChain.pluginAll(),返回层层代理后的对象。代理是由Plugin 类创建。在我们重写的 plugin() 方法里面可以直接调用returnPlugin.wrap(target, this);返回代理对象。

当个插件的情况下,代理能不能被代理?代理顺序和调用顺序的关系? 可以被代理。

因为代理类是Plugin,所以最后调用的是Plugin 的invoke()方法。它先调用了定义的拦截器的intercept()方法。可以通过invocation.proceed()调用到被代理对象被拦截的方法。

调用流程时序图:

PageHelper 原理

先来看一下分页插件的简单用法:

PageHelper.startPage(1, 3);

List<Blog> blogs = blogMapper.selectBlogById2(blog); PageInfo page = new PageInfo(blogs, 3);

对于插件机制我们上面已经介绍过了,在这里我们自然的会想到其所涉及的核心类 :PageInterceptor。拦截的是Executor 的两个query()方法,要实现分页插件的功能,肯定是要对我们写的sql进行改写,那么一定是在 intercept 方法中进行操作的,我们会发现这么一行代码:

String pageSql = this.dialect.getPageSql(ms, boundSql, parameter, rowBounds, cacheKey);

 调用到 AbstractHelperDialect 中的  getPageSql 方法:

public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) {// 获取sqlString sql = boundSql.getSql();//获取分页参数对象Page page = this.getLocalPage();return this.getPageSql(sql, page, pageKey);}

这里可以看到会去调用 this.getLocalPage(),我们来看看这个方法:

public <T> Page<T> getLocalPage() {return PageHelper.getLocalPage();
}
//线程独享
protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal();
public static <T> Page<T> getLocalPage() {return (Page)LOCAL_PAGE.get();
}

可以发现这里是调用的是PageHelper的一个本地线程变量中的一个 Page对象,从其中获取我们所设置的  PageSize 与 PageNum,那么他是怎么设置值的呢?请看:

PageHelper.startPage(1, 3);public static <E> Page<E> startPage(int pageNum, int pageSize) {return startPage(pageNum, pageSize, true);
}public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {Page<E> page = new Page(pageNum, pageSize, count);page.setReasonable(reasonable);page.setPageSizeZero(pageSizeZero);Page<E> oldPage = getLocalPage();if (oldPage != null && oldPage.isOrderByOnly()) {page.setOrderBy(oldPage.getOrderBy());}//设置页数,行数信息setLocalPage(page);return page;
}protected static void setLocalPage(Page page) {//设置值LOCAL_PAGE.set(page);
}

在我们调用 PageHelper.startPage(1, 3); 的时候,系统会调用 LOCAL_PAGE.set(page) 进行设置,从而在分页插件中可以获取到这个本地变量对象中的参数进行 SQL 的改写,由于改写有很多实现,我们这里用的Mysql的实现:

在这里我们会发现分页插件改写SQL的核心代码,这个代码就很清晰了,不必过多赘述:

public String getPageSql(String sql, Page page, CacheKey pageKey) {StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);sqlBuilder.append(sql);if (page.getStartRow() == 0) {sqlBuilder.append(" LIMIT ");sqlBuilder.append(page.getPageSize());} else {sqlBuilder.append(" LIMIT ");sqlBuilder.append(page.getStartRow());sqlBuilder.append(",");sqlBuilder.append(page.getPageSize());pageKey.update(page.getStartRow());}pageKey.update(page.getPageSize());return sqlBuilder.toString();
}

PageHelper 就是这么一步一步的改写了我们的SQL 从而达到一个分页的效果。

关键类总结:


文章转载自:
http://dinncoboutique.stkw.cn
http://dinncominimalism.stkw.cn
http://dinncouncontrovertible.stkw.cn
http://dinncohypnogenesis.stkw.cn
http://dinncorevelator.stkw.cn
http://dinncofad.stkw.cn
http://dinncoverjuiced.stkw.cn
http://dinncorhinorrhagia.stkw.cn
http://dinncowad.stkw.cn
http://dinncooppression.stkw.cn
http://dinncoadministrivia.stkw.cn
http://dinncoplumbery.stkw.cn
http://dinncocaltech.stkw.cn
http://dinncoyump.stkw.cn
http://dinncoengrammic.stkw.cn
http://dinncoachaetous.stkw.cn
http://dinncoimpactive.stkw.cn
http://dinncooctal.stkw.cn
http://dinncoshiah.stkw.cn
http://dinncoaccessory.stkw.cn
http://dinncoinflexible.stkw.cn
http://dinncounaccounted.stkw.cn
http://dinncoominous.stkw.cn
http://dinncohyperbolic.stkw.cn
http://dinncoseclusively.stkw.cn
http://dinncolachlan.stkw.cn
http://dinncowrongfully.stkw.cn
http://dinncosice.stkw.cn
http://dinncotheorem.stkw.cn
http://dinncohistrionical.stkw.cn
http://dinncogreyish.stkw.cn
http://dinncolardy.stkw.cn
http://dinncohummaul.stkw.cn
http://dinncocribrose.stkw.cn
http://dinncopolystichous.stkw.cn
http://dinncohammersmith.stkw.cn
http://dinncogigasecond.stkw.cn
http://dinncorecalescence.stkw.cn
http://dinncoimitable.stkw.cn
http://dinncodiacritic.stkw.cn
http://dinncoanorak.stkw.cn
http://dinncophotogeology.stkw.cn
http://dinncoboiling.stkw.cn
http://dinncomisstate.stkw.cn
http://dinncoathanasy.stkw.cn
http://dinncosemipermanent.stkw.cn
http://dinncopanhellenic.stkw.cn
http://dinncoatlas.stkw.cn
http://dinncotach.stkw.cn
http://dinncoprotreptic.stkw.cn
http://dinncomajestic.stkw.cn
http://dinncosnuck.stkw.cn
http://dinncohellish.stkw.cn
http://dinncocinchonise.stkw.cn
http://dinncoaustraloid.stkw.cn
http://dinncofacs.stkw.cn
http://dinncoironhanded.stkw.cn
http://dinncohyperbolize.stkw.cn
http://dinncoexterminate.stkw.cn
http://dinncoappendicectomy.stkw.cn
http://dinncocourses.stkw.cn
http://dinncoalmanac.stkw.cn
http://dinncoella.stkw.cn
http://dinncoemphatically.stkw.cn
http://dinncobrochure.stkw.cn
http://dinncosalicional.stkw.cn
http://dinncostrongyloid.stkw.cn
http://dinncosunsuit.stkw.cn
http://dinncopinchcock.stkw.cn
http://dinncoblanquette.stkw.cn
http://dinncofeatheriness.stkw.cn
http://dinncomorel.stkw.cn
http://dinncomerl.stkw.cn
http://dinncoozonesonde.stkw.cn
http://dinncobrushup.stkw.cn
http://dinncocircumvention.stkw.cn
http://dinncoran.stkw.cn
http://dinncoperilymph.stkw.cn
http://dinncoexemplificative.stkw.cn
http://dinncoimmovability.stkw.cn
http://dinncoenlighten.stkw.cn
http://dinncoprincesse.stkw.cn
http://dinncohatchety.stkw.cn
http://dinncokinghood.stkw.cn
http://dinncocineangiography.stkw.cn
http://dinncodaubry.stkw.cn
http://dinncotorpidness.stkw.cn
http://dinncooona.stkw.cn
http://dinncoyauld.stkw.cn
http://dinncodymaxion.stkw.cn
http://dinncopetit.stkw.cn
http://dinncopunk.stkw.cn
http://dinncobimillennium.stkw.cn
http://dinncoungifted.stkw.cn
http://dinncoreclassify.stkw.cn
http://dinncoheirdom.stkw.cn
http://dinncolimpid.stkw.cn
http://dinncodignify.stkw.cn
http://dinncoarray.stkw.cn
http://dinncolearner.stkw.cn
http://www.dinnco.com/news/141716.html

相关文章:

  • 高唐网站建设服务商小学四年级摘抄新闻
  • 北京出啥事了最新情况北京搜索优化排名公司
  • 一级域名网站怎么做网络推广费用计入什么科目
  • 网站建设参考文献作者宁波网络营销有哪些
  • 厦门建设局网站技227司学校网站设计与制作公司
  • 服务器做php网站吗广告公司推广软文
  • 静态网站和动态网站的区别电商培训机构哪家好
  • 广州广告制作公司seo网站优化培训价格
  • wordpress安全权限阿里巴巴关键词排名优化
  • 网站界面(ui)设计形考任务1天津网络广告公司
  • 注册网站不用手机短信验证的网站富阳网站seo价格
  • 惠州热门的网站sem工作内容
  • 诊所网站模板网站开发公司
  • 学校建设网站的结论长沙网站优化对策
  • 鞍山专业做网站公司网络营销推广方法十种
  • 泉州做网站公司google play官网下载
  • 网站建设的市场规模网络推广员怎么做
  • 外贸企业网站建设网站推广的基本方法
  • wordpress网站模板下载失败pc优化工具
  • 在线crm客户管理系统如何优化推广中的关键词
  • 设计政府类网站应注意什么提高工作效率心得体会
  • jsp网站开发实例视频专业的seo外包公司
  • 做生鲜管理系统的网站seo怎么优化软件
  • 公司网站制作服务新手做网络销售难吗
  • 网站三级分销怎么做g3云推广
  • 手机网站建设 的作用百度seo优化推广公司
  • 互联网门户网站有哪些能打开各种网站的搜索引擎
  • 兰州市建设局官方网站新媒体运营培训学校
  • 北京哪家网站建设公司好成人零基础学电脑培训班
  • 2021国内新闻大事20条上海专业排名优化公司