5-21 拦截器 Interceptor

Spring MVC拦截器

什么是拦截器

拦截器是SpringMvc框架提供的功能

它可以在控制器方法运行之前或运行之后(还有其它特殊时机)对请求进行处理或加工的特定接口

常见面试题:过滤器和拦截器的区别

过滤器和拦截器都可以在控制器方法运行前后加入额外代码,实现aop效果

  • 提供者不同

    • 过滤器是由javaEE提供的
    • 拦截器是SpringMvc提供的
  • 作用目标不同

    • 过滤器作用目标更广:可以作用在所有请求当前服务器资源的流程中
    • 拦截器作用目标单一:只能作用在请求目标为当前服务器控制器的流程中
  • 功能强度不同

    • 过滤器是原生的JavaEE的功能,功能较弱,不能直接处理Spring容器中的内容和对象
    • 拦截器是SpringMvc框架提供的,所以天生和Spring容器有更好的兼容性,可以直接操作Spring容器中的对象,而且拦截器相比于过滤器有更完善的参数返回值的处理,也有更多的运行时机
  • 结论

    如果请求的目标能确定是一个控制器方法,优先使用拦截器

    如果请求的目标可能是其他静态资源,那么就需要使用过滤器

详细操作,见成老师笔记

Mybatis 拦截器

简介:

Mybatis框架提供的一个功能

能够在Mapper接口方法运行之前或之后添加额外代码的功能

之前我们通过设置,实现将运行的sql语句输出到控制台的效果,就是拦截器实现的

我们也可以简单的进行一个类似的演示

首先,要想能够成功的拦截Mybatis中mapper运行的sql语句

需要先在Spring中设置相关的代码

步骤1:编写拦截器

// Mybatis拦截器测试类
@Slf4j
// Mybatis拦截器配置声明用的注解
// 可以配置拦截多个jdbc中的对象
@Intercepts({@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class,Integer.class}
)})
public class MyInterceptor implements Interceptor {
    // Mybatis拦截器方法
    // invocation 就是要运行的目标(这里就是sql语句)
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.info("进入拦截器,准备拦截sql语句");
        // 从参数invocation中获得要运行的sql语句对象BoundSql
        BoundSql boundSql=((StatementHandler)invocation.getTarget())
                                        .getBoundSql();
        // 从boundSql中获取sql语句
        String sql=boundSql.getSql();
        log.info("要运行的原sql语句为:{}",sql);
        // 下面可以将sql语句进行更改
        sql=sql+" and 1=1";
        log.info("变更后的sql语句:{}",sql);
        // 利用反射强制赋值,将boundSql中的sql属性变化
        reflectUpdateSql(boundSql,"sql",sql);
        
        return invocation.proceed();
    }

    // 需要定义个方法,能够将sql语句进行改写
    // 但是sql语句已经在invocation我么需要利用反射,将其中的属性改写
    private void reflectUpdateSql(BoundSql boundSql,
                                  String attrName,String attrValue)
            throws NoSuchFieldException, IllegalAccessException {
        // 这个方法目标是将boundSql对象的sql强制赋值赋值
        // 反射的属性类
        Field field=boundSql.getClass().getDeclaredField(attrName);
        // 设置属性可强制赋值 设置之后就不是私有属性了
        field.setAccessible(true);
        // 将准备好的值赋值到这个属性中
        field.set(boundSql,attrValue);
    }
    // User 类   User类中有个私有属性password  没有getset方法
    // 反射是可以强制给password属性赋值的
    // BoundSql相当于User对象
    // attrName相当于password属性
    // attrValue相当于我们要强制付给属性的值
    
}

步骤2:

将拦截器设置在SpringBoot框架下使其生效

config包中

//这个类是配置Mybatis拦截器生效的配置类
@Configuration
// 配置Mybatis拦截器生效的固定代码
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class InterceptorConfig {
    // 获得Mybatis的会话管理器
    // Mybatis会话管理器就是执行连接操作数据库的核心类
    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    // 下面方法是将Mybatis会话管理器中所有连接和我们编写的拦截器关联,使拦截器生效
    @PostConstruct
    public void addInterceptors(){
        // 实例化我们编写的拦截器
        Interceptor interceptor=new MyInterceptor();
        for (SqlSessionFactory factory:sqlSessionFactoryList){
            factory.getConfiguration().addInterceptor(interceptor);
        }
    }
}
posted @   Y_Zoran  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
-->
点击右上角即可分享
微信分享提示