再玩springmvc的拦截器

spingmvc的执行步骤

用户发送请求到dispatcherservlet,

前端控制器到handermaping去找对应的handler,

然后返回一个执行链,是handler和响应的拦截器,

执行链经过适配器,做一些处理,

到达对应的handler,

经过handler来处理后,返回modelandview,

前端控制器会先对视图对象进行解析,解析完成后,

前端控制器会对视图进行渲染,

渲染完成之后,将视图返回给用户。


首先,我们发现以上步骤中包含了handlermaping,handlerAdpdater(适配器),和handler,那么springmvc执行的时候,这些都应该作为对象存在的,这就是我们springmvc配置的由来

1.我们配置扫描包,将controller全都交给spring管理

2.然后我们开启注解的自动,来注册handlermaping和handlerAdpdater

3.因为我们要解析视图,所以要有视图解析器的配置。

4.我们看到经过handlerMaping后,返回的是一个handler和拦截器的执行链,那么重点来了,我们的拦截器开始配置了。

步骤是:我们首先用一个类实现HandlerAdpter,实现里面的方法,有前置拦截(在handler之前),后置拦截,最终拦截(视图渲染完成之后)

public class LoginInterceptor implements HandlerInterceptor {
    
     @Autowired
     private UserServiceImpl userService;

     @Override
     public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler)
             throws Exception {
         //在Handler执行之前处理
         //判断用户是否登录
         //从cookie中取token
         String token = CookieUtils. getCookieValue(request, "TT_TOKEN");
        
         /*if(StringUtils.isBlank(token)){
            //跳转到登录页面,把用户请求的url作为参数传递给登录页面。
            response.sendRedirect(userService.SSO_BASE_URL + userService.SSO_PAGE_LOGIN
                    + "?redirect=" + request.getRequestURL());
            //返回false
            return false;
        }*/
        
         //根据token换取用户信息,调用sso系统的接口。
         TbUser user = userService. getUserByToken(token);
         //取不到用户信息
         if ( null == user) {
             //跳转到登录页面,把用户请求的url作为参数传递给登录页面。
             response. sendRedirect( userService. SSO_BASE_URL + userService. SSO_PAGE_LOGIN
                    + "?redirect=" + request. getRequestURL());
             //返回false
             return false;
        }
         //取到用户信息,放行
         //把用户信息放入request
         request. setAttribute( "user", user); 
         //返回值决定handler是否执行。true:执行,false:不执行。
         return true;
    }

     @Override
     public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler,
             ModelAndView modelAndView) throws Exception {
         // handler执行之后,返回ModelAndView之前

    }

     @Override
     public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
             throws Exception {
         // 返回ModelAndView之后。
         //响应用户之后。

    }

}



以上是springmvc的拦截器,那么springboot中的拦截器又是怎么实现的呢?

springboot中使用拦截器,

  • 自定义一个拦截器,
  • 一个类通过实现WebMvcConfigurer并添加@Configuration,
  • 在这个类中重写   addInterceptors方法,这里还有一点巧妙的是通过@Bean的方式,将日志引入
    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }
    
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.loginInterceptor()).addPathPatterns("/**");
    }

这个方式来添加拦截器,那么我们真实开发是怎么用的呢?

首先跟mvc一样,用一个类继承handlerintercapter

public class LoginInterceptor extends HandlerInterceptorAdapter {

    private JwtProperties jwtProperties;

    // 定义一个线程域,存放登录用户
    private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>();

    public LoginInterceptor(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 查询token
        String token = CookieUtils.getCookieValue(request, "LY_TOKEN");
        if (StringUtils.isBlank(token)) {
            // 未登录,返回401
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
        // token,查询用户信息
        try {
            // 解析成功,证明已经登录
            UserInfo user = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());
            // 放入线程域
            tl.set(user);
            return true;
        } catch (Exception e) {
            // 抛出异常,证明未登录或超时,返回401
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }

    }

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

    public static UserInfo getLoginUser() {
        return tl.get();
    }
}
然后用mvcconfig实现webmvcconfigurer

@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {

    @Autowired
    private JwtProperties jwtProperties;

    @Bean
    public LoginInterceptor loginInterceptor() {
        return new LoginInterceptor(jwtProperties);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor())
                .addPathPatterns("/**");
    }
}


猜你喜欢

转载自blog.csdn.net/qpc672456416/article/details/80827688