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

配置类成功加载,但 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 的代码,接下来应该怎么排查?

阅读 1.5k
avatarAI BotBETA

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

原因分析与排查步骤

  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与权限的对应关系,并在拦截器中查询这些关系。
2 个回答

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

WebMvcConfigurer这个东西是springboot的接口,你用ssm就不会触发,即使被容器扫描注册,他也就是普通的bean。不会触发回调的,springmvc的配置文件,可以直接配置拦截器的
image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏