介绍
- 见名知意,用于拦截controller请求,在进入controller之前进行一些处理,如果可以,进入controller处理方法,如果不可以,则不会进入controller处理方法。基本原理是采用AOP面相切面编程,基于动态代理,在所执行的controller方法前后添加代码,这就是拦截器
- 拦截器不依赖任何Servlet容器
- 拦截器只能对controller处理方法的url进行拦截,这里提到过滤器则可以对所有的请求进行过滤
- 在controller的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
实列(IDEA)
- 创建简单的SpringBoot项目,原始的即可,不需要改动,就用内置的Tomcat就行
- 编写POJO类
1 @Data
2 @AllArgsConstructor
3 @RequiredArgsConstructor
4 @NoArgsConstructor
5 public class User implements Serializable {
6 private Integer id;
7 @NonNull private String name;
8 @NonNull private String sex;
9 private Integer age;
10
11 /*
12 * 类上面的注解是使用的lombok插件,不知道的朋友可自行查阅资料
13 * */
14 }
- 创建UserController处理器类
1 import org.springframework.web.bind.annotation.RequestMapping;
2 import org.springframework.web.bind.annotation.RestController;
3
4 import javax.servlet.http.HttpSession;
5 import java.util.List;
6
7 @RestController
8 @RequestMapping("/user/")
9 public class UserController {
10 //模拟user的增删改查操作,假设增删改必须有用户且已登录才可执行
11 @RequestMapping("delete")
12 public String delete(){
13 return "delete操作";
14 }
15 @RequestMapping("insert")
16 public String insert(){
17 return "insert操作";
18 }
19 @RequestMapping("update")
20 public String update(){
21 return "update操作";
22 }
23 @RequestMapping("login")
24 public String login(HttpSession session){
25 //模拟登录效果,不查询数据库
26 User user = new User("admin","男");
27 session.setAttribute("user",user);
28 return "登录成功";
29 }
30 @RequestMapping("logout")
31 public String logout(HttpSession session){
32 //登出
33 session.removeAttribute("user");
34 return "登出成功";
35 }
36 }
- 编写LoginInterceptor拦截器类
- 可以使用实现HandlerInterceptor接口,也可直接继承HandlerInterceptorAdapter抽象类,因为这个类就是对HandlerInterceptor接口的一个空实现,看这边源码,注意方法上面的文档注释,如果选择HandlerInterceptorAdapter,再次重写这三个方法即可
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* Abstract adapter class for the {@link AsyncHandlerInterceptor} interface,
* for simplified implementation of pre-only/post-only interceptors.
*
* @author Juergen Hoeller
* @since 05.12.2003
*/
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
/**
* This implementation always returns {@code true}.
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/**
* This implementation is empty.
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
/**
* This implementation is empty.
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
/**
* This implementation is empty.
*/
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
}
}
- 此处我选择实现接口
1 import org.springframework.web.servlet.HandlerInterceptor;
2 import org.springframework.web.servlet.ModelAndView;
3
4 import javax.servlet.http.HttpServletRequest;
5 import javax.servlet.http.HttpServletResponse;
6 import java.io.IOException;
7
8 /**
9 * 登录验证
10 */
11 public class LoginInterceptor implements HandlerInterceptor {
12 @Override
13 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
14 //从session中取出user,如果取出的对象对空,向响应流中给出信息,并且返回false,不再进入controller方法
15 // 如果取出的对象不为空,表示用户已经登录,则返回true,继续进入controller方法
16 System.out.println("LoginInterceptor--preHandle");
17 boolean hasAlready=false;
18 Object user = request.getSession().getAttribute("user");
19 if(user!=null) {
20 hasAlready = true;
21 }else {
22 response.getWriter().write("<h1 style='color:red;'>not login</h1>");
23 }
24
25 return hasAlready;
26 }
27
28 @Override
29 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
30 System.out.println("LoginInterceptor--postHandle");
31 }
32
33 @Override
34 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
35 System.out.println("LoginInterceptor--afterCompletion");
36 }
37 }
- 编写MvcConfigurer类,代码如下
1 import cn.bdqn.ylm.sssmc.interceptor.LoginInterceptor;
2 import org.springframework.context.annotation.Configuration;
3 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
4 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
5
6 import java.util.ArrayList;
7 import java.util.List;
8
9 @Configuration
10 public class MvcConfigurer implements WebMvcConfigurer {
11 @Override
12 public void addInterceptors(InterceptorRegistry registry) {
13 LoginInterceptor li=new LoginInterceptor();
14 List<String> pathPatterns=new ArrayList<>();
15 List<String> excludePathPatterns=new ArrayList<>();
16 pathPatterns.add("/**");
17 excludePathPatterns.add("/user/log**");
18
19 //pathPatterns表示所有的信息需要拦截的请求,这里写了/**,全部拦截
20 //excludePathPatterns表示不拦截的请求,这里除了用户退出和登录操作以外,其他的都需要由用户登录才可以操作
21 registry.addInterceptor(li).addPathPatterns(pathPatterns).excludePathPatterns(excludePathPatterns);
22
23 }
24 }
- OK,可以在浏览器访问观察结果了
- 首先访问/user/logout,浏览器显示登出成功即为成功,因为拦截器中设置了不拦截/user/log**请求
- 浏览器访问/user/增删改,浏览器显示not login即可成功,表示用户没有登录,被拦截器拦下并且向响应流中写出内容
- 浏览器访问/user/login,浏览器显示登录成功,此时session已经存在user对象,再次访问/user/增删改,如果增删改操作正常执行,并且页面显示对应的操作的成功提示即为正常,表示拦截器正常获取session中的对象判断对象状态放行拦截器
- 推荐进一步学习
- 拦截器的三个方法的执行时机、特征等
- 拦截器链(简单提一下:多拦截器会形成拦截器链,比如可以先用一个拦截器验证用户是否登录,如果登录,下一个拦截器再次验证权限问题)
- 过滤器、监听器
- 拦截器与ServletAPI的过滤器、监听器的不同
- 那么这些知识点我在这里并没有详细讲,大家自己下去学习
风萧萧兮易水寒,壮士一去兮不复还