当前位置: 首页 > 知识库问答 >
问题:

spring-mvc - spring MVC 配置类被成功加载,但拦截器没有生效怎么排查?

许俊雅
2024-09-23

配置类成功加载,但 addInterceptors 方法没有执行

我的 spring.xml 文件中包扫描配置包含如下:

    <!--扫描基本包-->
    <context:component-scan base-package="com.springSSM.ssm">
        <!--context:exclude-filter标签:排除对某个注解的扫描(过滤controller层,因为已经在 springMVC 配置文件中扫描了)-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

上面的配置中已经扫描了 com.springSSM.ssm 下除 controller 外的所有子包其中也包括配置类,而且通过在配置类的构造方法中输出日志可以看到项目启动的时候构造函数确实被执行了。
配置类的完整代码如下:

package com.springSSM.ssm.config;

import com.springSSM.ssm.interceptor.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    //确实有输出,已经被扫描添加被实例化了
    public WebConfig(){
        System.out.println("---如果有输出,则说明被实例化,被扫描到");
    }

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        System.out.println("只要执行就有输出");
        //WebMvcConfigurer.super.addInterceptors(registry);
        //registry.addInterceptor(jwtTokenUtil).addPathPatterns("/**").excludePathPatterns("/login");
        registry.addInterceptor(jwtTokenUtil).addPathPatterns("/**");

    }
}

从包扫描配置和 WebConfig 路径来看,它是可以被扫描的
但 addInterceptors 中的输出语句始终没有被执行,而且其中添加的拦截器也没有生效。

我的项目中已经有 servlet-context.xml 配置文件了,但是感觉拦截器用配置类配置会更方便一些,所以就出现了两个文件并存的局面,不知道 WebConfig 中的 addInterceptors 没有被执行是不是和这个有关系,servlet-context.xml 文件的全部内容如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启扫描器 ,spring的配置文件扫描时将 controller 排除掉了,这里添加上-->
    <context:component-scan base-package="com.springSSM.ssm.controller"/>

    <!--mvc 注解驱动并添加json 支持-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!--返回信息为字符串时 处理-->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <!--将对象转换为json 对象-->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!--使用默认的 Servlet 来响应静态文件-->
    <mvc:default-servlet-handler/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!--前缀:在WEB-INF目录下的jsp目录下-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀:以.jsp结尾的资源-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--文件上传-->
    <bean id="mutipartResollver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--允许文件上传的最大尺寸-->
        <property name="maxUploadSize">
            <value>10485700</value>
        </property>
        <!--设置文件放入临时文件夹的最大大小限制-->
        <!--此值是阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的的临时文件-->
        <property name="maxInMemorySize">
            <value>4096</value>
        </property>
    </bean>
</beans>

从网上查找,说 SpringBoot会判断,如果有 WebMvcConfigurationSupport 就不会加载 WebMvcConfigurer 。但我的项目并没有用 springBoot,只是 SSM ,用了 springMVC,而且全局查找也没有搜到包含 WebMvcConfigurationSupport 的代码,接下来应该怎么排查?

共有2个答案

童琪
2024-09-23

回答:问题很明确哈,描述的也很清楚,问题已经找到了,第一个问题是 servlet-context.xml 配置文件中的扫描基本包写错了,写那个controller和config包的父目录即可,不然你的config包是不会被扫描到的;第二个问题也很明确了,你提出的问题可以采用RBAC模型来解决,它可以帮你很好的进行这样的接口鉴权;具体的你可以参考这篇文章:https://gitee.com/anxwefndu/rbac-model-simulation

小牛23058
2024-09-23

第一个问题:配置类为什么没有被成功加载

原因分析与排查步骤

  1. 检查配置类位置:确保WebConfig类位于Spring的组件扫描路径内。从您的配置来看,WebConfig位于com.springSSM.ssm.config包中,但您的spring.xml配置文件中仅排除了@Controller注解的类,并没有明确指定扫描com.springSSM.ssm.config包。
  2. XML与Java配置混合使用:当同时使用XML配置和Java配置时,需要确保两者都被正确加载。如果您的Spring容器是通过DispatcherServlet(通常对应servlet-context.xml)和ContextLoaderListener(通常对应spring.xml)来分别加载的,那么需要确认WebConfig是否位于DispatcherServlet的扫描路径中,或者是否应该通过ContextLoaderListener加载。
  3. 启用注解驱动:在servlet-context.xml中,您已经启用了<mvc:annotation-driven>,这确保了Spring MVC的注解支持,但还需要确保Java配置类(如WebConfig)被Spring容器识别并注册。
  4. 检查启动类和配置文件:如果您的项目是基于Spring Boot的,那么通常不需要显式地配置ContextLoaderListenerDispatcherServlet。在这种情况下,Spring Boot会自动扫描带有@SpringBootApplication@ComponentScan注解的类所在的包及其子包。请检查您的启动类是否位于合适的包,并且其包扫描路径是否包括了WebConfig所在的包。
  5. 日志和调试:增加日志输出或使用调试工具来跟踪Spring容器的启动过程,查看是否有关于组件扫描或配置类加载的日志信息。
  6. 检查其他配置文件:确认没有其他配置文件或注解(如@EnableWebMvc)可能干扰了MVC的配置。

第二个问题:使用拦截器鉴权

设计思路

  1. 角色与权限管理:在数据库中设计一个角色表和一个权限表,每个角色可以关联多个权限。接口权限则通过接口URL路径或某种标识符与权限表关联。
  2. 鉴权逻辑

    • 拦截器捕获请求,解析请求中的用户信息(如Token)。
    • 使用用户信息从数据库中查询用户角色和权限。
    • 根据请求的接口URL或标识符,查询该接口所需的权限。
    • 对比用户权限与接口所需权限,判断是否允许访问。
  3. 灵活配置

    • 使用通配符或正则表达式来匹配接口URL,以减少配置量。
    • 可以在数据库中动态管理接口与权限的对应关系,无需修改代码即可调整鉴权策略。
  4. 前端与后端的协作

    • 前端在发送请求时,根据用户角色和权限动态生成可访问的接口列表。
    • 后端拦截器根据用户请求进行鉴权,拒绝未授权的请求。
  5. 缓存优化

    • 对于频繁访问的接口,可以考虑将用户权限和接口权限的对应关系缓存起来,以提高鉴权效率。

示例实现

  • 在数据库中设计roles(角色表)、permissions(权限表)和role_permissions(角色权限关联表)等表。
  • 拦截器中根据用户Token解析出用户ID,查询用户角色和权限。
  • 使用AOP或拦截器中的逻辑,根据请求URL和权限表进行鉴权。
  • 对于动态权限管理,可以在数据库中添加接口URL与权限的对应关系,并在拦截器中查询这些关系。
 类似资料:
  • 主要内容:定义拦截器,配置拦截器,拦截器的执行流程,多个拦截器的执行流程。拦截器(Interceptor)是 Spring MVC 提供的一种强大的功能组件。它可以对用户请求进行拦截,并在请求进入控制器(Controller)之前、控制器处理完请求后、甚至是渲染视图后,执行一些指定的操作。 在 Spring MVC 中,拦截器的作用与 Servlet 中的过滤器类似,它主要用于拦截用户请求并做相应的处理,例如通过拦截器,我们可以执行权限验证、记录请求信息日志、判断用户是

  • 我的项目是基于spring mvc的,我写了一个拦截器来拦截请求,我想从请求中获取参数,下面是我的代码: 但现在它抛出了一个异常: 出现例外的原因是什么?

  • 在我们的应用程序中,我们使用JSON进行请求和响应。控制器方法用@RequestBody()注释。返回的对象,例如TransferResponse。我想从@ResponseBody中找到这个对象。我已经设置了一个拦截器postHandle方法: 那么如何在这个postHandle方法中获取JSON呢? 提前感谢GM

  • 问题很简单 在这里打破头! 编辑:一个小突破。我打印了目标,它返回的是SimpleJPrepository,而不是实际的存储库。

  • 我不知道咋拦截,我想不修改源代码的情况下进行拦截增强,我发现使用cglib需要手动使用Enhancer#create()方法创建一个代理类,手动调用才能触发Callback的钩子函数

  • 本文向大家介绍详解springmvc拦截器拦截静态资源,包括了详解springmvc拦截器拦截静态资源的使用技巧和注意事项,需要的朋友参考一下 springmvc拦截器interceptors springmvc拦截器能够对请求的资源路径进行拦截,极大的简化了拦截器的书写。但是,千万千万要注意一点:静态资源的放行。 上代码: 问题来了,在请求jsp页面的时候,你的静态资源的访问仍然会被自定义拦截器