在使用 Spring Boot 开发 Web 应用时,我们常常需要使用拦截器(Interceptor)来对请求进行预处理。例如,验证用户是否登录。然而,很多开发者会遇到一个常见的问题:拦截器配置了却不生效。本文将讨论一种常见的原因及其解决方案——将配置类移入正确的包下。
问题描述
我们创建了一个
LoginCheckInterceptor
类,并在
WebConfig
类中进行注册。但是,启动应用后发现拦截器并没有生效。
示例代码:
LoginCheckInterceptor
类:
package com.itheima.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.itheima.pojo.Result;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
String url = req.getRequestURL().toString();
log.info("请求的url: {}", url);
if (url.contains("login")) {
log.info("登录操作, 放行...");
return true;
}
String jwt = req.getHeader("token");
if (!StringUtils.hasLength(jwt)) {
log.info("请求头token为空,返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {
e.printStackTrace();
log.info("解析令牌失败, 返回未登录错误信息");
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
log.info("令牌合法, 放行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle ...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
WebConfig
类:
package com.config;
import com.itheima.interceptor.LoginCheckInterceptor;
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 {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}
解决方案
将
WebConfig
类移到
itheima
包下即可解决问题。原因在于 Spring Boot 的默认包扫描机制。
原因分析
Spring Boot 使用
@SpringBootApplication
注解的主应用类启动应用。该注解包含了
@ComponentScan
,默认扫描主应用类所在包及其子包中的所有组件。如果
WebConfig
类不在主应用类所在包或其子包下,Spring Boot 将无法自动扫描到它,从而导致拦截器不生效。
解决方法
将
WebConfig
类移到
com.itheima
包下,确保其在主应用类的扫描路径内。
调整后的目录结构:
src/main/java └── com └── itheima ├── MyApplication.java ├── interceptor │ └── LoginCheckInterceptor.java └── config └── WebConfig.java
代码调整
将
WebConfig
类从
com.config
包移到
com.itheima.config
包下:
package com.itheima.config;
import com.itheima.interceptor.LoginCheckInterceptor;
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 {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}
其他解决方案
如果不想移动配置类,还可以通过以下方法显式指定扫描路径:
**1. 使用
@ComponentScan
注解指定扫描包**:
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = {"com.itheima", "com.config"})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
**2. 使用
@Import
注解导入配置类**:
package com.itheima;
import com.itheima.config.WebConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import(WebConfig.class)
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
通过这些方式,可以确保 Spring Boot 正确扫描和加载拦截器配置类,使拦截器生效。
结论
在使用 Spring Boot 开发 Web 应用时,正确配置包扫描路径非常重要。确保配置类在主应用类的扫描路径内,可以有效解决拦截器不生效的问题。希望这篇文章能够帮助大家更好地理解 Spring Boot 的包扫描机制,并顺利解决开发中遇到的问题。
版权归原作者 True_aFalse 所有, 如有侵权,请联系我们删除。