记一次springboot配置登录拦截器踩的坑
写在前面的话
系统采用的springboot+Mybatis+js+Mysql+Redis前后端分离的一个系统,在写拦截器时,遇到很多的坑,想记录这一次踩坑。
springboot版本
// An highlighted block
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/>
</parent>
新建WebConfigurer
在springboot2.0之后WebConfigurer需要实现 WebMvcConfigurer 这个接口,并实现里面的两个方法。(在老版本的 spring-boot 中使用的是WebMvcConfigurerAdapter,新版本中已过时,还有不能通过继承 WebMvcConfigurationSupport 这个类来实现,这样会在某些情况下失效),第二个 addInterceptors 方法用来注册添加拦截器。
package com.example.config;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//import com.example.demo.Interceptors.AdminLoginInterceptor;
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Autowired
private AdminLoginInterceptor adminLoginInterceptor;
// @Bean
// public AdminLoginInterceptor adminLoginInterceptor() {
// return new AdminLoginInterceptor();
// }
//前后端分离解决跨域问题
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
// 用来配置静态资源的,比如html,js,css,等等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminLoginInterceptor).addPathPatterns("/Site/**").addPathPatterns("/Test/**")
.excludePathPatterns("/Login/adminLogin");
}
}
拦截器部分
新建一个AdminLoginInterceptor ,这里封装了一个message的实体类,
主要有state,massage,和token
package com.example.config;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.example.demo.Redis.RedisDao;
import com.example.demo.base.baseEntity.Message;
import com.example.demo.base.baseTool.Constans;
import com.example.demo.entity.Admin;
import com.example.demo.base.baseTool.GsonUtil;;
@Component
public class AdminLoginInterceptor implements HandlerInterceptor {
@Autowired private RedisDao redisDao;
// 这个方法是在访问接口之前执行的,我们只需要在这里写验证登陆状态的业务逻辑,就可以在用户调用指定接口之前验证登陆状态了
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//测试
System.out.println("来到了拦截器");
Message message = new Message();
// Object admin = request.getSession().getAttribute("token");
String admin2 = request.getHeader("token");
System.out.println(admin2);
// 去redis查看有没有这个token存在,
if ( admin2 == null || !redisDao.existKey(admin2)) {
message.setState(3);
message.setMessage("账号过期!请重新登录");
response.getWriter().write(GsonUtil.object2Json(message));
System.out.println("未登录");
return false;
} else {
System.out.println("登录");
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
需要特别注意的地方
我的application的文件和拦截器的文件不再同一一个包下
application所在包com.example.demo
拦截器所在包在com.example.config
需要加一个@ComponentScan(basePackages={“com.example”})
这个程序就能够扫描,不然拦截器不会起作用
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages={"com.example"})
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}