一:拦截器Interceptor
- 拦截器拦截以 .action结尾的url,拦截Action的访问。 Interfactor是基于Java的反射机制(APO思想)进行实现,不依赖Servlet容器。
- 拦截器可以在方法执行之前(preHandle)和方法执行之后(afterCompletion)进行操作,回调操作(postHandle),可以获取执行的方法的名称,请求(HttpServletRequest)
- Interceptor:可以控制请求的控制器和方法,但控制不了请求方法里的参数(只能获取参数的名称,不能获取到参数的值)
(用于处理页面提交的请求响应并进行处理,例如做国际化,做主题更换,过滤等)。
简而言之:Spring拦截器是基于AOP思想对HTTP资源进行拦截控制的一种手段
二:springmvc中拦截器的实现
1.创建一个自定义拦截器,实现接口HandlerInterceptor并重写方法preHandle,这个方法会在执行所有方法之前预先执行。
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/*
* 自定义重写拦截器
* */
@Component
public class LoginIntercept implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.得到session对象
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("userinfo") != null) {
//说明已经登陆,可以放行
return true;
}
// 执行到这行表示未登录,未登录就重定向到到登陆页面
response.sendRedirect("/user/login");
return false;
2.将自定义拦截器加入到 WebMvcConfigurer 的 addInterceptors 方法中。
代码实现
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 AppConfig implements WebMvcConfigurer {
@Autowired
private LoginIntercept loginIntercept;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginIntercept).
addPathPatterns("/**").
excludePathPatterns("/user/login").
excludePathPatterns("/user/reg").
excludePathPatterns("/login.html").
excludePathPatterns("/reg.html").
excludePathPatterns("/**/*.css").
excludePathPatterns("/**/*.jpg");
}
}
- addPathPatterns:表示需要拦截的 URL,
**的意思表示所有方法,在这表示拦截所有的方法 - excludePathPatterns:表示排除的 URL,也就是需要放行的方法。
3. 处理指定接口
我们也可以在拦截器里面进行一些业务逻辑的处理,比如放行部分接口、捕捉指定接口等。
public class LoginInterceptor implements HandlerInterceptor {
// 处理指定接口
private static final String TOKEN_LOGIN = "/user/token";
private static final String USER_NO_URL = "/user/no"; // 拦截不存在的接口路径
// 不要要校验的接口
private static final List<String> NO_NEED_LOGIN = new ArrayList<>(Arrays.asList("/user/health", "/logout"));
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取访问的接口名
String uri = request.getRequestURI();
String contentPath = request.getContextPath();
if (uri.startsWith(contentPath + "/")) {
// 去掉contextPath
uri = uri.replace(contentPath + "/", "/");
}
if (NO_NEED_LOGIN.contains(uri)) {
// log.info("资源{}不需要登录,直接访问", uri);
System.out.println("这个接口不需要验证,直接放行.");
return true;
}
if (uri.equals(TOKEN_LOGIN)) {
response.setStatus(200);
response.setCharacterEncoding("utf-8");
response.getWriter().println("处理指定接口,并返回数据信息."); // 可以返回相关json处理
return false;
}
if (uri.equals(USER_NO_URL)) {
response.setStatus(500);
response.setCharacterEncoding("utf-8");
response.getWriter().println("拦截的是未定义的接口."); // 可以返回相关json处理
return false;
}
// 可以对每个接口进行身份校验 或者 编写相关业务逻辑
System.out.println("执行了拦截器的preHandle方法");
return true;
}
}