欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot Web开发——拦截器的基本使用

程序员文章站 2022-07-09 17:02:57
...

SpringBoot Web开发——拦截器的基本使用

1.拦截器简介

拦截器会对处理器进行拦截,拦截的目的就是做一些预处理,以此来增强处理器的功能。

常见的拦截器使用场景:

  • 登录拦截:身份验证
  • 日志记录:记录请求信息的日志
  • 性能监控:记录处理器方法执行时间。

下面以登录请求为例,简单使用拦截器,来实现登录拦截。

2.为什么需要使用拦截器?

比如一个XX后台管理系统,首先需要登录:

假设路径为: http://localhost:8080/login

输入账号信息登录后进入XX后台管理系统主页: http://localhost:8080/index

那如果直接访问http://localhost:8080/index呢?还是会返回主页,那这登录有啥意义呢?

而使用拦截器的话,浏览器请求http://localhost:8080/index时,拦截器可做预处理,判断会话对象Session中是否存在用户信息,不存在则跳转登录界面。

3.代码实现登录拦截

3.1 控制层将登录成功的用户名添加至Session中

使用前端使用thymeleaf模板引擎,浏览器GET请求/login和/index返回对应的html,还有一个/login的POST请求用于登录。

和之前没有登录拦截的区别:多了个HttpSession httpSession参数,前端请求不用管,登录成功后将用户名保存至Session中:

httpSession.setAttribute("loginUser",username);//将登陆成功的用户名添加至Session中

完整如下:

@Controller
public class TestController {

    Map<String, Object> result;

    @GetMapping("/login")
    public String login() {
        return "login";
    }
    
    @PostMapping("/login")
    @ResponseBody
    public Map<String, Object> login(@RequestParam("username") String username,
                                     @RequestParam("password") String password,
                                     HttpSession httpSession) {
        result = new HashMap<>();
        if (username.equals("123") && "123".equals(password)) {
            httpSession.setAttribute("loginUser",username);//将登陆成功的用户名添加至Session中
            result.put("resultCode", 200);
            return result;//登陆成功,前端根据resultCode跳转主页面
        } else {//登录失败
            result.put("resultCode", 500);
            return result;
        }
    }

    @GetMapping("/index")
    public String index() {
        return "index";
    }
}

3.2 自定义登录拦截器类

  • 使用@Component标注该拦截器类,将其添加至IOC容器

  • 实现HandlerInterceptor接口中的三个方法preHandle/postHandle/afterCompletion

这三个方法分别在DispatcherServlet之前执行/之后执行/结果返回给客户端之前执行,我们如果需要拦截登录,当然是在DispatcherServlet之前执行,也就是前端发送了我们指定拦截的请求路径后,我们先执行这个方法,再处理请求。

具体到登录拦截,判断上述添加至session中的loginUser是否存在,存在的话说明已经登录过,可放行请求,session中的loginUser为空的话,说明没有登录过,则返回至登录界面。

详情可看注释:

@Component
public class LoginInterceptor implements HandlerInterceptor {
    //在DispatcherServlet之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("1.我是在DispatcherServlet之前执行的方法");
        Object loginUser = request.getSession().getAttribute("loginUser");//获取已登录的用户名
        if (loginUser == null) {
            //未登录,返回登陆页面
            request.setAttribute("msg", "请先登录");
            request.getRequestDispatcher("/login").forward(request, response);//前端可获取request中的msg,来提示用户“请先登录”
            return false;
        } else {
            //已登录,放行请求
            return true;
        }
    }

    //在DispatcherServlet之后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("2.在controller执行之后的DispatcherServlet之后执行");
    }

    //在页面渲染完成返回给客户端之前执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("3.在页面渲染完成返回给客户端之前执行");
    }
}

3.3 配置类中注册拦截器

项目中一般都会有配置类,即实现WebMvcConfigurer接口的类:

只需重写addInterceptors方法即可,使用回调参数InterceptorRegistry对象中的这三个方法:

  • addInterceptor():添加拦截器,传入拦截器对象
  • addPathPatterns():添加需要拦截的请求路径,若为/demo/**代表/demo下所有请求
  • excludePathPatterns():排除不需要拦截的请求路径,以登录为例,进入登录页面的/login当然要排除
@Configuration
public class MyConfig implements WebMvcConfigurer {


    @Resource
    private LoginInterceptor loginInterceptor;

    //注册拦截器,springboot已经做好静态资源(js/css等)的映射,无需额外配置
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)//增加过滤的方法类
                .addPathPatterns("/**")//定义过滤的范围,拦截/下所有请求
                .excludePathPatterns("/login");//排除某些请求,这些请求无需拦截
    }

    //其他配置...
}

3.4 测试登录拦截:直接访问index首页

效果就是直接访问index管理界面会被拦截,自动跳转至登录界面。正常登录跳转还是和以前一样。

SpringBoot Web开发——拦截器的基本使用