Spring boot实现自定义拦截器

时间:2022-05-27 10:21:22

Sprintboot的拦截器提供了精细的控制:在request被响应之前、request被响应之后、request全部结束之后至视图渲染之前 三个时间点,我们都可以通过编写他们的函数来控制。

首先新建一个拦截器passportInterpretor,这个拦截器类必须实现HandlerInterceptor接口,并重写三个成员函数。

然后注册拦截器。

下面举例,我在拦截器中做的事情是,从请求中拿到我想要的ticket,判断是否合法(过期、废弃等),如果合法就在视图中添加一个线程本地变量user,否则不做任何改变(放行请求),用于登录状态的页面显示。

package com.example.market1.Interceptor;

import com.example.market1.DAO.TicketUserDAO;
import com.example.market1.DAO.UserDAO;
import com.example.market1.Model.HostHolder;
import com.example.market1.Model.TicketLogin;
import com.example.market1.Model.User;
import com.example.market1.Utils.MarketUtils;
import com.example.market1.Utils.MyTools;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

@Component
public class PassportInterceptor implements HandlerInterceptor {
    @Autowired
    private UserDAO userDAO;

    @Autowired
    private TicketUserDAO ticketUserDAO;

    @Autowired
    private HostHolder hostHolder;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ticket = MarketUtils.getTicketFromRequst(request);
        if(ticket != null){
            TicketLogin ticketLogin = ticketUserDAO.getTicketLogin(ticket);
            if(ticketLogin == null || ticketLogin.getExpired().before(new Date()) || ticketLogin.getStatus() == 1){
                return true;
            }
            User user = userDAO.getUserById(ticketLogin.getUserid());
            MyTools.log("User got by ticket:" + user.getMail());
            hostHolder.setUser(user);
        }
        return true;
    }

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

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

然后新建一个注册拦截器的配置类:

(这里有一点需要注意,新版本的springboot中该类需要实现的接口是WebMvcConfigurer,

旧版本要实现的接口是WebMvcConfigurerAdapter 并且此时registry.addInterceptor之后要super.addInterceptor(registry)。

package com.example.market1.Configuration;

import com.example.market1.Interceptor.PassportInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class MarketWebConfiguration implements WebMvcConfigurer {
    @Autowired
    PassportInterceptor passportInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(passportInterceptor);
    }
}