springboot项目中拦截器的应用

1.应用场景

  • 这个拦截器其实和面向切面编程的思想很像,主要用来处理一些公共的可复用的一些请求,这些东西每次都实现很麻烦,所有我们直接将其用拦截器编写会方便很多。

2.应用

  • springboot中提供了HandlerInterceptor接口,里面提供了三个方法
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

3.案例

  • 我们编写一个类去实现这个接口看一看
  • 然后我们去编写一个配置类,让这个拦截器具体要拦截哪些请求,然后启动项目
  • 最后可以得出以下代码中的结论
  • 拦截器类:
package com.nowcoder.community.controller.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;

/**
 * @author : wys
 * @date : 2020-11-22 21:27
 **/

@Component
public class AlphaInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(AlphaInterceptor.class);

    /**
     * 在Controller之前执行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.debug("preHandle :" + handler.toString());
        return true;
    }

    /**
     * 在controller之后执行,模板之前
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.debug("postHandle :" + handler.toString());
    }

    /**
     * 在模板执行之后执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.debug("afterCompletion :" + handler.toString());
    }
}

  • config配置类
import com.nowcoder.community.controller.interceptor.AlphaInterceptor;
import com.nowcoder.community.controller.interceptor.LoginTicketInterceptor;
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;

/**
 * @author : wys
 * @date : 2020-11-22 21:35
 **/

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private AlphaInterceptor alphaInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(alphaInterceptor)
       			//除去哪些请求
                .excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
                //具体拦截哪些请求
                .addPathPatterns("/register", "/login");
    }
}

  • 然后我们启动项目看一下
    在这里插入图片描述
  • 可以清楚看到请求的过程,所以我们可以利用这三个方法的特性完成一些特定的功能,比如用户的识别。下面我们就来看看这个案例

4.登录案例(后台代码)

  • 我们在登录后,无论哪个页面都应该保存我的个人信息,那么就意味着每次都要发请求,每次都要写肯定是非常麻烦的,我们可以借助拦截器,让他每次帮我们做就好了,我们只需要写一次就够了。
  • 首先和上面一样,创建一个拦截器类和一个配置类
  • 拦截器类:
package com.nowcoder.community.controller.interceptor;

import com.nowcoder.community.entity.LoginTicket;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.UserService;

import com.nowcoder.community.util.CookieUtil;
import com.nowcoder.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * @author : wys
 * @date : 2020-11-22 21:52
 **/

@Component
public class LoginTicketInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Autowired
    private HostHolder hostHolder;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //从cookie中获取凭证
        String ticket = CookieUtil.getValue(request, "ticket");
        //System.out.println(ticket+"-------------===");

        if(ticket != null){
            // 查询凭证
            LoginTicket loginTicket = userService.findLoginTicket(ticket);
            // 检查凭证是否有效
            if(loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())){
                // 根据凭证查询用户
                User user = userService.findUserById(loginTicket.getUserId());
                // 在本次请求中持有用户
                hostHolder.setUser(user);
            }
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        User user = hostHolder.getUser();
        if(user != null && modelAndView != null){
            System.out.println(user.getUsername());
            modelAndView.addObject("loginUser", user);
        }

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        hostHolder.clear();
    }
}

  • 配置类:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private AlphaInterceptor alphaInterceptor;

    @Autowired
    private LoginTicketInterceptor loginTicketInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(alphaInterceptor)
                .excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
                .addPathPatterns("/register", "/login");
		//除了静态资源,我们对所有的请求都进行拦截,看看用户是否进行了登录
        registry.addInterceptor(loginTicketInterceptor)
                .excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");
    }
}
  • 上面的拦截器类中,我们用到了多线程的知识,用到了ThreadLocal类来帮我们处理并发的情况,因为如果只是单纯的放入容器很有可能会出现问题。用多线程就不会有问题了。接下来看看怎么编写,其实也很简单,我们就用这个类(因为以后要复用,我们单独封装一下)代替session对象
 /* 持有用户信息,用于代替session对象
 **/
@Component
public class HostHolder {

    private ThreadLocal<User> users = new ThreadLocal<>();

    public void setUser(User user){
        users.set(user);
    }

    public User getUser(){
        return users.get();
    }

    public void clear(){
        users.remove();
    }

}

5.登录案例(前台代码)

  • 写完了后台代码,估计还是不知道怎么用,我们看看前端代码就懂了
  • index.html
    在这里插入图片描述
  • 可以看到这里,就是我们从拦截器中取到的东西,我们用这个东西,来判断用户每次请求是否登录了,然后改变头部的显示标志
  • 如下图,未登录之前:
    在这里插入图片描述
  • 登录之后:
    在这里插入图片描述
  • 这样就完成了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值