返回顶部
首页 > 资讯 > 后端开发 > Python >MyBatis拦截器的原理与使用
  • 373
分享到

MyBatis拦截器的原理与使用

2024-04-02 19:04:59 373人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录一、拦截对象和接口实现示例二、拦截器注册的三种方式        1.XML注册  &n

一、拦截对象和接口实现示例

        mybatis拦截器的作用是在于Dao到DB中间进行额外的处理。大部分情况下通过mybatis的xml配置sql都可以达到想要的DB操作效果,然而存在一些类似或者相同的查询条件或者查询要求,这些可以通过拦截器的实现可以提升开发效率,比如:分页、插入和更新时间/人、数据权限、SQL监控日志等。

  • Mybatis支持四种对象拦截Executor、StatementHandler、PameterHandler和ResultSetHandler
  1. Executor:拦截执行器的方法。
  2. StatementHandler:拦截Sql语法构建的处理。
  3. ParameterHandler:拦截参数的处理。
  4. ResultHandler:拦截结果集的处理。

public interface Executor {
    ResultHandler NO_RESULT_HANDLER = null;
    int update(MappedStatement var1, Object var2) throws SQLException;
    <E> List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, CacheKey var5, BoundSql var6) throws SQLException;
    <E> List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4) throws SQLException;
    <E> Cursor<E> queryCursor(MappedStatement var1, Object var2, RowBounds var3) throws SQLException;
    List<BatchResult> flushStatements() throws SQLException;
    void commit(boolean var1) throws SQLException;
    void rollback(boolean var1) throws SQLException;
    CacheKey createCacheKey(MappedStatement var1, Object var2, RowBounds var3, BoundSql var4);
    boolean isCached(MappedStatement var1, CacheKey var2);
    void clearLocalCache();
    void deferLoad(MappedStatement var1, MetaObject var2, String var3, CacheKey var4, Class<?> var5);
    Transaction getTransaction();
    void close(boolean var1);
    boolean isClosed();
    void setExecutorWrapper(Executor var1);
}
public interface StatementHandler {
    Statement prepare(Connection var1, Integer var2) throws SQLException;
    void parameterize(Statement var1) throws SQLException;
    void batch(Statement var1) throws SQLException;
    int update(Statement var1) throws SQLException;
    <E> List<E> query(Statement var1, ResultHandler var2) throws SQLException;
    <E> Cursor<E> queryCursor(Statement var1) throws SQLException;
    BoundSql getBoundSql();
    ParameterHandler getParameterHandler();
}
public interface ParameterHandler {
    Object getParameterObject();
    void setParameters(PreparedStatement var1) throws SQLException;
}
public interface ResultHandler<T> {
    void handleResult(ResultContext<? extends T> var1);
}

     拦截的执行顺序是Executor->StatementHandler->ParameterHandler->ResultHandler

  • MyBatis提供的拦截器接口:

public interface Interceptor {
    Object intercept(Invocation var1) throws Throwable;
    default Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    default void setProperties(Properties properties) {}
}

Object intercept方法用于拦截器的实现;

  Object plugin方法用于判断执行拦截器的类型;

  void setProperties方法用于获取配置项的属性。

  • 拦截对象和拦截器接口的结合,自定义的拦截器类需要实现拦截器接口,并通过注解@Intercepts和参数@Signature来声明要拦截的对象。

        @Signature参数type是拦截对象,method是拦截的方法,即上面的四个类对应的方法,args是拦截方法对应的参数(方法存在重载因此需要指明参数个数和类型)

         @Intercepts可以有多个@Signature,即一个拦截器实现类可以同时拦截多个对象及方法,示例如下:

  1. Executor->intercept
  2. StatementHandler->intercept
  3. ParameterHandler->intercept
  4. ResultHandler->intercept

@Intercepts({
        @Signature(
                type = Executor.class,
                method = "query",
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
        )
})
public class SelectPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof Executor) {
            System.out.println("SelectPlugin");
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }
    @Override
    public void setProperties(Properties properties) {}
}
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class StatementPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof StatementHandler) {
            System.out.println("StatementPlugin");
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }
    @Override
    public void setProperties(Properties properties) {}
}
@Intercepts({@Signature(type = ParameterHandler.class,method = "setParameters",args = {PreparedStatement.class})})
public class ParameterPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof ParameterHandler) {
            System.out.println("ParameterPlugin");
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        if (target instanceof ParameterHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }
    @Override
    public void setProperties(Properties properties) {}
}
@Intercepts({@Signature(type = ResultHandler.class,method = "handleResult",args = {ResultContext.class})})
public class ResultPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof ResultHandler) {
            System.out.println("ResultPlugin");
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        if (target instanceof ResultHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }
    @Override
    public void setProperties(Properties properties) {}
}

二、拦截器注册的三种方式

        前面介绍了Mybatis的拦截对象及其接口的实现方式,那么在项目中如何注册拦截器呢?本文中给出三种注册方式。

        1.XML注册

        xml注册是最基本的方式,是通过在Mybatis配置文件中plugins元素来进行注册的。一个plugin对应着一个拦截器,在plugin元素可以指定property子元素,在注册定义拦截器时把对应拦截器的所有property通过Interceptor的setProperties方法注入给拦截器。因此拦截器注册xml方式如下:


<?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.tiantian.mybatis.interceptor.MyInterceptor">
           <property name="prop1" value="prop1"/>
           <property name="prop2" value="prop2"/>
       </plugin>
    </plugins>
    <!-- ...... -->
</configuration>

        2.配置类注册

       配置类注册是指通过Mybatis的配置类中声明注册拦截器,配置类注册也可以通过Properties类给Interceptor的setProperties方法注入参数。具体参考如下:


@Configuration
public class MyBatisConfig {
    @Bean
    public String MyBatisInterceptor(SqlSessionFactory sqlSessionFactory) {
        UpdatePlugin executorInterceptor = new UpdatePlugin();
        Properties properties = new Properties();
        properties.setProperty("prop1", "value1");
        // 给拦截器添加自定义参数
        executorInterceptor.setProperties(properties);
        sqlSessionFactory.getConfiguration().addInterceptor(executorInterceptor);
        sqlSessionFactory.getConfiguration().addInterceptor(new StatementPlugin());
        sqlSessionFactory.getConfiguration().addInterceptor(new ResultPlugin());
        sqlSessionFactory.getConfiguration().addInterceptor(new ParameterPlugin());
        // sqlSessionFactory.getConfiguration().addInterceptor(new SelectPlugin());
        return "interceptor";
    }

    // 与sqlSessionFactory.getConfiguration().addInterceptor(new SelectPlugin());效果一致
    @Bean
    public SelectPlugin SelectInterceptor() {
        SelectPlugin interceptor = new SelectPlugin();
        Properties properties = new Properties();
        // 调用properties.setProperty方法给拦截器设置自定义参数
        interceptor.setProperties(properties);
        return interceptor;
    }
}

        3.注解方式

          通过@Component注解方式是最简单的方式,在不需要转递自定义参数时可以使用,方便快捷。


@Component
@Intercepts({
        @Signature(
                type = Executor.class,
                method = "query",
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
        )
})
public class SelectPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof Executor) {
            System.out.println("SelectPlugin");
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

三、ParameterHandler参数改写-修改时间和修改人统一插入

        针对具体的拦截器实现进行描述。日常编码需求中会碰到修改时需要插入修改的时间和人员,如果要用xml的方式去写非常麻烦,而通过拦截器的方式可以快速实现全局的插入修改时间和人员。先看代码:


@Component
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}),
})
public class MyBatisInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 参数代理
        if (invocation.getTarget() instanceof ParameterHandler) {
            System.out.println("ParameterHandler");
            // 自动添加操作员信息
            autoAddOperatorInfo(invocation);
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

    
    private void autoAddOperatorInfo(Invocation invocation) throws Throwable {
        System.out.println("autoInsertCreatorInfo");
        // 获取代理的参数对象ParameterHandler
        ParameterHandler ph = (ParameterHandler) invocation.getTarget();
        // 通过MetaObject获取ParameterHandler的反射内容
        MetaObject metaObject = MetaObject.forObject(ph,
                SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
                new DefaultReflectorFactory());
        // 通过MetaObject反射的内容获取MappedStatement
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("mappedStatement");
        // 当sql类型为INSERT或UPDATE时,自动插入操作员信息
        if (mappedStatement.getSqlCommandType() == SqlCommandType.INSERT ||
                mappedStatement.getSqlCommandType() == SqlCommandType.UPDATE) {
            // 获取参数对象
            Object obj = ph.getParameterObject();
            if (null != obj) {
                // 通过反射获取参数对象的属性
                Field[] fields = obj.getClass().getDeclaredFields();
                // 遍历参数对象的属性
                for (Field f : fields) {
                    // 如果sql是INSERT,且存在createdAt属性
                    if ("createdAt".equals(f.getName()) && mappedStatement.getSqlCommandType() == SqlCommandType.INSERT) {
                        // 设置允许访问反射属性
                        f.setAccessible(true);
                        // 如果没有设置createdAt属性,则自动为createdAt属性添加当前的时间
                        if (null == f.get(obj)) {
                            // 设置createdAt属性为当前时间
                            f.set(obj, LocalDateTime.now());
                        }
                    }
                    // 如果sql是INSERT,且存在createdBy属性
                    if ("createdBy".equals(f.getName()) && mappedStatement.getSqlCommandType() == SqlCommandType.INSERT) {
                        // 设置允许访问反射属性
                        f.setAccessible(true);
                        // 如果没有设置createdBy属性,则自动为createdBy属性添加当前登录的人员
                        if (null == f.get(obj)) {
                            // 设置createdBy属性为当前登录的人员
                            f.set(obj, 0);
                        }
                    }
                    // sql为INSERT或UPDATE时均需要设置updatedAt属性
                    if ("updatedAt".equals(f.getName())) {
                        f.setAccessible(true);
                        if (null == f.get(obj)) {
                            f.set(obj, LocalDateTime.now());
                        }
                    }
                    // sql为INSERT或UPDATE时均需要设置updatedBy属性
                    if ("updatedBy".equals(f.getName())) {
                        f.setAccessible(true);
                        if (null == f.get(obj)) {
                            f.set(obj, 0);
                        }
                    }
                }

                // 通过反射获取ParameterHandler的parameterObject属性
                Field parameterObject = ph.getClass().getDeclaredField("parameterObject");
                // 设置允许访问parameterObject属性
                parameterObject.setAccessible(true);
                // 将上面设置的新参数对象设置到ParameterHandler的parameterObject属性
                parameterObject.set(ph, obj);
            }
        }
    }
}

        拦截器的接口实现参考前文,这里着重介绍autoAddOperatorInfo方法里的相关类。

        1.ParameterHandler

        接口源码


 public interface ParameterHandler {
     Object getParameterObject();
     void setParameters(PreparedStatement var1) throws SQLException;
 }

        提供两个方法:

        getParameterObject是获取参数对象,可能存在null,需要注意null指针。

        setParameters是控制如何设置SQL参数,即sql语句中配置的java对象和jdbc类型对应的关系,例如#{id,jdbcType=INTEGER},id默认类型是javaType=class java.lang.Integer。

        该接口有一个默认的实现类,源码如下:


public class DefaultParameterHandler implements ParameterHandler {
    private final TypeHandlerReGIStry typeHandlerRegistry;
    private final MappedStatement mappedStatement;
    private final Object parameterObject;
    private final BoundSql boundSql;
    private final Configuration configuration;

    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        this.mappedStatement = mappedStatement;
        this.configuration = mappedStatement.getConfiguration();
        this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
        this.parameterObject = parameterObject;
        this.boundSql = boundSql;
    }

    public Object getParameterObject() {
        return this.parameterObject;
    }

    public void setParameters(PreparedStatement ps) {
        ErrorContext.instance().activity("setting parameters").object(this.mappedStatement.getParameterMap().getId());
        List<ParameterMapping> parameterMappings = this.boundSql.getParameterMappings();
        if (parameterMappings != null) {
            for(int i = 0; i < parameterMappings.size(); ++i) {
                ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    String propertyName = parameterMapping.getProperty();
                    Object value;
                    if (this.boundSql.hasAdditionalParameter(propertyName)) {
                        value = this.boundSql.getAdditionalParameter(propertyName);
                    } else if (this.parameterObject == null) {
                        value = null;
                    } else if (this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) {
                        value = this.parameterObject;
                    } else {
                        MetaObject metaObject = this.configuration.newMetaObject(this.parameterObject);
                        value = metaObject.getValue(propertyName);
                    }

                    TypeHandler typeHandler = parameterMapping.getTypeHandler();
                    JdbcType jdbcType = parameterMapping.getJdbcType();
                    if (value == null && jdbcType == null) {
                        jdbcType = this.configuration.getJdbcTypeForNull();
                    }

                    try {
                        typeHandler.setParameter(ps, i + 1, value, jdbcType);
                    } catch (SQLException | TypeException var10) {
                        throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var10, var10);
                    }
                }
            }
        }

    }
}

        通过DefaultParameterHandler实现类我们知道通过ParameterHandler可以获取到哪些属性和方法,其中包括我们下面一个重要的类MappedStatement。

        2.MappedStatement

        MyBatis的mapper文件中的每个select/update/insert/delete标签会被解析器解析成一个对应的MappedStatement对象,也就是一个MappedStatement对象描述一条SQL语句。MappedStatement对象属性如下:


// mapper配置文件名
    private String resource;
    // mybatis的全局信息,如jdbc
    private Configuration configuration;
    // 节点的id属性加命名空间,如:com.example.mybatis.dao.UserMapper.selectByExample
    private String id;
    private Integer fetchSize;
    private Integer timeout;
    private StatementType statementType;
    private ResultSetType resultSetType;
    private SqlSource sqlSource;
    private Cache cache;
    private ParameterMap parameterMap;
    private List<ResultMap> resultMaps;
    private boolean flushCacheRequired;
    private boolean useCache;
    private boolean resultOrdered;
    // sql语句的类型:select、update、delete、insert
    private SqlCommandType sqlCommandType;
    private KeyGenerator keyGenerator;
    private String[] keyProperties;
    private String[] keyColumns;
    private boolean hasNestedResultMaps;
    private String databaseId;
    private Log statementLog;
    private LanguageDriver lang;
    private String[] resultSets;

        在本例中通过MappedStatement对象的sqlCommandType来判断当前的sql类型是insert、update来进行下一步的操作。

四、通过StatementHandler改写SQL

        StatementHandler是用于封装JDBC Statement操作,负责对JDBC Statement的操作,如设置参数,并将Statement结果集转换成List集合

        实现代码如下:

        删除注解标记


@Target({ElementType.METHOD})  //表示注解的使用范围
@Retention(RetentionPolicy.RUNTIME) //注解的保存时间
@Documented    //文档显示
public @interface DeletedAt {
    boolean has() default true;
}

        Dao层添加删除注解,为false时不添加删除标志


 @Mapper
 public interface AdminProjectDao {
     @DeletedAt(has = false)
     List<AdminProjectPo> selectProjects(AdminProjectPo po);
 }

        拦截器通过删除注解标记判断是否添加删除标志


@Component
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
})
public class MyBatisInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof StatementHandler) {
            System.out.println("StatementHandler");
            checkHasDeletedAtField(invocation);
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

    
    private void checkHasDeletedAtField(Invocation invocation) throws Throwable {
        System.out.println("checkHasDeletedAtField");
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        // 通过MetaObject访问对象的属性
        MetaObject metaObject = MetaObject.forObject(
                statementHandler,
                SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
                new DefaultReflectorFactory());
        // 获取成员变量mappedStatement
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        // 如果sql类型是查询
        if (mappedStatement.getSqlCommandType() == SqlCommandType.SELECT) {
            // 获取删除注解标志
            DeletedAt annotation = null;
            String id = mappedStatement.getId();
            String className = id.substring(0, id.lastIndexOf("."));
            String methodName = id.substring(id.lastIndexOf(".") + 1);
            Class<?> aClass = Class.forName(className);
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                declaredMethod.setAccessible(true);
                //方法名相同,并且注解是DeletedAt
                if (methodName.equals(declaredMethod.getName()) && declaredMethod.isAnnotationPresent(DeletedAt.class)) {
                    annotation = declaredMethod.getAnnotation(DeletedAt.class);
                }
            }
            // 如果注解不存在或者注解为true(默认为true) 则为Mysql语句增加删除标志
            if (annotation == null || annotation.has()) {
                BoundSql boundSql = statementHandler.getBoundSql();
                //获取到原始sql语句
                String sql = boundSql.getSql();
                //通过反射修改sql语句
                Field field = boundSql.getClass().getDeclaredField("sql");
                field.setAccessible(true);
                String newSql = sql.replaceAll("9=9", "9=9 and deleted_at is null ");
                field.set(boundSql, newSql);
            }
        }
    }
}

        在SQL语句替换上需要能识别到要被替换的内容,因此在xml的sql语句中加入特殊标志"9=9",该标志不影响原来SQL的执行结果,不同的过滤条件可以设置不同的标志,是一个比较巧妙的替换方式。

以上就是MyBatis拦截器的原理与使用的详细内容,更多关于MyBatis拦截器的资料请关注编程网其它相关文章!

--结束END--

本文标题: MyBatis拦截器的原理与使用

本文链接: https://lsjlt.com/news/128379.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MyBatis拦截器的原理与使用
    目录一、拦截对象和接口实现示例二、拦截器注册的三种方式        1.XML注册  &n...
    99+
    2024-04-02
  • MyBatis拦截器的实现原理
    目录前言 1.使用方法2.MyBatis对象的创建3.代理对象的创建3.1 拦截器的获取3.2 代理对象的创建4. 拦截器的执行过程5. 拦截器的执行顺序前言 Mybati...
    99+
    2024-04-02
  • Spring中拦截器的原理与使用方法
    这篇文章主要讲解了“Spring中拦截器的原理与使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring中拦截器的原理与使用方法”吧!1.Spring中的拦截器在web开发中,拦截...
    99+
    2023-07-02
  • 【mybatis】mybatis 拦截器工作原理源码解析
    mybatis 拦截器工作原理(JDK动态代理) 1. mybatis 拦截器案例 场景:分页查询,类似成熟产品:pagehelper, 这里只做简单原理演示 1.0 mybatis全局配置 SqlMapConfig.xml ...
    99+
    2015-01-18
    【mybatis】mybatis 拦截器工作原理源码解析
  • mybatis拦截器怎么使用
    今天小编给大家分享一下mybatis拦截器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。mybatis实战之拦截器在...
    99+
    2023-07-05
  • 一文了解Spring中拦截器的原理与使用
    目录1.Spring中的拦截器1.1HandlerInterceptor拦截器1.2 MethodInterceptor拦截器2.二者的区别1.Spring中的拦截器 在web开发中...
    99+
    2024-04-02
  • 使用mybatis拦截器处理敏感字段
    目录mybatis拦截器处理敏感字段前言思路解析代码趟过的坑(敲黑板重点)mybatis Excutor 拦截器的使用这里假设一个场景实现过程的关键步骤和代码重点mybatis拦截器...
    99+
    2024-04-02
  • MyBatis Excutor 拦截器的巧妙用法
    这里要讲的巧妙用法是用来实现在拦截器中执行额外 MyBatis 现有方法的用法。并且会提供一个解决拦截Executor时想要修改MappedStatement时解决并发的问题。这里假设一个场景:实现一个拦截器,记录 MyBatis 所有的 ...
    99+
    2023-05-31
    mybatis excutor 拦截器
  • Struts2拦截器Interceptor原理与配置的示例分析
    这篇文章将为大家详细讲解有关Struts2拦截器Interceptor原理与配置的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Struts2拦截器原理:Struts2拦截器的实现原理相对简单...
    99+
    2023-05-30
    struts2
  • SpringBoot拦截器的使用
    目录一、拦截器简介二、拦截器配置使用方式1、过滤器拦截器作用范围2、拦截器的使用三、知识点总结1、拦截器的使用2、拦截器和过滤器的相同与不同一、拦截器简介 拦截器通常通过动态代理的方...
    99+
    2024-04-02
  • struts2拦截器的工作原理是什么
    Struts2拦截器的工作原理是基于责任链模式。当请求到达Struts2框架时,它会依次经过一系列的拦截器。每个拦截器可以在请求被传...
    99+
    2023-10-24
    struts2
  • Struts2拦截器的实现原理是什么
    Struts2拦截器的实现原理是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Struts2的核心在于它复杂的拦截器,几乎70%的工作都是由拦截器完成的。比...
    99+
    2023-05-31
    struts st
  • 详解SpringMVC HandlerInterceptor拦截器的使用与参数
    目录拦截器概念:拦截器VS过滤器自定义拦截器开发过程:拦截器配置项:多拦截器配置:拦截器概念: 拦截器( Interceptor)是一种动态拦截方法调用的机制,请求处理过程解析核心原...
    99+
    2024-04-02
  • 如何使用SpringBoot拦截器实现登录拦截
    小编给大家分享一下如何使用SpringBoot拦截器实现登录拦截,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!可以对URL路径进行拦截,可以用于权限验证、解决乱码...
    99+
    2023-06-29
  • Mybatis-Plus实现SQL拦截器的示例
    目录起源实现拦截器接口InnerInterceptor修改sql常用的工具类起源 最近公司要做多租户,Mybatis-Plus的多租户插件很好用,但是有一个场景是:字典表或者某些数据...
    99+
    2023-05-19
    Mybatis-Plus SQL拦截器 Mybatis-Plus 拦截器
  • 如何使用Java MyBatis拦截器提高工作效率
    小编给大家分享一下如何使用Java MyBatis拦截器提高工作效率,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!场景:在后端服务开发时,现在很流行的框...
    99+
    2023-06-29
  • MyBatis-Plus 使用拦截器实现数据权限控制
    前言背景 平时开发中遇到根据当前用户的角色,只能查看数据权限范围的数据需求。列表实现方案有两种,一是在开发初期就做好判断赛选,但如果这个需求是中途加的,或不希望每个接口都加一遍,就可以方案二加拦截器的...
    99+
    2023-09-07
    mybatis java
  • SpringMVC 拦截器的使用示例
    目录简介 拦截器初体验 拦截器再体验-登录验证 简介 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己...
    99+
    2024-04-02
  • SpringBoot拦截器的使用介绍
    目录定义拦截器实现HandleInterceptor接口继承HandleInterceptorAdapter类实现WebRequestInterceptor接口实现RequestIn...
    99+
    2024-04-02
  • 利用Mybatis Plus实现一个SQL拦截器
    目录起源实现拦截器接口InnerInterceptor修改sql常用的工具类起源 最近公司要做多租户,Mybatis-Plus的多租户插件很好用,但是有一个场景是:字典表或者某些数据...
    99+
    2023-05-19
    Mybatis Plus实现SQL拦截器 Mybatis Plus SQL拦截 Mybatis Plus SQL
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作