首页 > 编程知识 正文

mybatis拦截器不生效,idea代码生成器插件

时间:2023-05-05 12:18:25 阅读:16341 作者:2409

作者:溪~源

blog.csdn.net/Xuan _ Lu/article/details/109253213

首先熟悉Mybatis的运行过程,如下图所示。

首先,说明Mybatis可以监听的类型具体有以下4种。

执行程序:如何阻止执行机构。

参数处理程序:阻止参数的过程。

结果处理程序:阻止处理结果集。

语句处理程序:阻止处理SQL语法生成。

规则Intercepts注释需要Signature截取点参数数组。 在Signature中,指定要阻止哪个对象中的哪个方法。 @Intercepts注释定义如下:

@ documented @ retention (retention policy.runtime ) target ) elementtype.type ) public @ interface intercepts {/* * } 定义如下。

@ documented @ retention (retention policy.runtime ) target({} ) public@interfacesignature(/***拦截的类执行程序,PPP /**在定义拦截类的基础上,拦截的方法*/Stringmethod (); /**在定义拦截方法的基础上,定义拦截方法对应的参数。 *注意参数类型和顺序*/Class,因为*JAVA可能会重载方法? []args (; }标识拦截注释@Intercepts规则的使用。 以下是一个简单的例子。

@intercepts(//请注意这个大括号。 也就是说,您可以在此定义多个@Signature并监听到多个位置。 所有的都使用这个拦截器@ signature (type=resultset handler.class,method='Handdler ) args={Statement.class},@ signgind

@Signature :显示自定义拦截器需要拦截哪些类型、哪些方法;

类型:上述四种类型中的一种;

method (因为可能存在对应于接口的什么类型的方法()重载方法);

args :应对哪些方法的参与;

method如何支持四种类型:

介绍拦截器定制的实践部分,主要遵循以下三个步骤。

1 .实现org.Apache.ibatis.plugin.interceptor接口,然后重写以下方法:

publicinterfaceinterceptor { object intercept (invocation var1) throwsThrowable; 对象插件(objectvar 1; 语音属性(属性var 1; } 2.添加拦截器注释@Intercepts{.}。 具体值按照上述规则设定。

3 .向配置文件中添加阻止程序。

Invocation invocation (Intercept )或更高版本表明,有四种类型的对象可供interceptor拦截。 其中,加入invocation是指监听到的对象。

示例:如果阻止StatementHandler#query(Statement st,ResultHandler rh)方法,则Invocation适用于该方法。

plugin (对象目标)的方法的作用是使mybatis判断是否监听,并决定是否生成代理。

@ overridepublicobjectplugin ((object target )//确定是否侦听这种类型的对象) @由@Intercepts注释确定),然后返回代理对象或原始对象//,所以我们在实现plugin方法时,可以确定目标类型,如果是插件

拦截的对象时才执行Plugin.wrap方法,否则的话,直接返回目标本身。    if (target instanceof StatementHandler) {        return Plugin.wrap(target, this);    }    return target;}

注意:每经过一个拦截器对象都会调用插件的plugin方法,也就是说,该方法会调用4次。根据@Intercepts注解来决定是否进行拦截处理。

setProperties(Properties properties)

拦截器需要一些变量对象,而且这个对象是支持可配置的。(搜索公众号Java知音,回复“2021”,送你一份Java面试题宝典)

实战

自定义拦截器

@Intercepts(value = {@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})public class MyInterceptor implements Interceptor {    @Override    public Object intercept(Invocation invocation) throws Throwable {        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();        BoundSql boundSql = statementHandler.getBoundSql();        Object obj = boundSql.getParameterObject();        String sql = boundSql.getSql();        if (sql.trim().toUpperCase().startsWith("INSERT")) {            ReflectUtil.setFieldValue(obj, "rev", 0);            ReflectUtil.setFieldValue(obj, "createTime", new Date());            ReflectUtil.setFieldValue(obj, "operateTime", new Date());            ReflectUtil.setFieldValue(boundSql,"parameterObject", obj);        } else if (sql.trim().toUpperCase().startsWith("UPDATE")) {            sql = sql.replaceAll(" set ", " SET ")                    .replaceAll(" Set ", " SET ")                    .replaceAll(" SET ", " SET rev = rev+1, operate_time = NOW(), ");            ReflectUtil.setFieldValue(boundSql,"sql", sql);        }        return invocation.proceed();    }    @Override    public Object plugin(Object o) {        return Plugin.wrap(o, this);    }    @Override    public void setProperties(Properties properties) {    }}

主要看下核心代码方法intercept():

这段代码主要目的:拦截insert和update语句,利用反射机制,设置insert语句的参数rev(版本号,利用乐观锁),第一次查询,故创建时间和操作时间相同;update是将版本号+1,统一修改其操作时间。

mybatis-config

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>     <plugins>        <plugin interceptor="com.qxy.mybatis.interceptor.MyInterceptor"/>    </plugins></configuration>

application.yml

特别重要的一点,一定将mybatis-config中的对象注入到Sprint容器中,否则不会生效。

...//省略其他配置mybatis:  config-location: classpath:/mybatis-config.xml

ReflectUtil

public class ReflectUtil {    private ReflectUtil() {}    /**     * 利用反射获取指定对象的指定属性     * @param obj 目标对象     * @param fieldName 目标属性     * @return 目标字段     */    private static Field getField(Object obj, String fieldName) {        Field field = null;        for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {            try {                field = clazz.getDeclaredField(fieldName);                break;            } catch (NoSuchFieldException e) {                //这里不用做处理,子类没有该字段,可能父类有,都没有就返回null            }        }        return field;    }    /**     * 利用反射设置指定对象的指定属性为指定的值     * @param obj 目标对象     * @param fieldName 目标属性     * @param fieldValue 目标值     */    public static void setFieldValue(Object obj, String fieldName, Object fieldValue) throws IllegalAccessException {        Field field = getField(obj, fieldName);        if (field != null) {            field.setAccessible(true);            field.set(obj, fieldValue);        }    }}

debug

上图中能够看到BoundSql对象中主要存储的属性值,所以我们自定义拦截器时,主要针对BoundSql的属性值进行修改。

程序代码没有走到我们反射机制设置值的位置,测试createTime=null;

返回之前,看下BoundSql对象的值,创建时间已被赋值。

END 推荐好文 >>【练手项目】基于SpringBoot的ERP系统,自带进销存+财务+生产功能>>分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!>>能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。