springboot-拦截器

package com.now.community.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;

@Component
public class AlphaInterceptor implements HandlerInterceptor {

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

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

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

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

配置:

package com.now.community.community.config;

import com.now.community.community.controller.interceptor.*;
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;

@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", "/**/*.woff", "/**/*.svg")
                .addPathPatterns("/register", "/login");
    }
}

访问register或者login时,拦截到了请求。

显示会话信息

springboot-拦截器_第1张图片

为什么不把用户信息保存在session 里,而是ThreadLocal里?

在分布式的环境下,使用session存在共享数据的问题。通常的解决方案,是将共享数据存入数据库,所有的应用服务器都去数据库获取共享数据。对于每一次请求,开始时从数据库里取到数据,然后将其临时存放在本地的内存里,考虑到线程之间的隔离,所以用threadlocal,这样在本次请求的过程中,就可以随时获取到这份共享数据了。所以,session的替代方案是数据库,ThreadLocal只是打了个辅助。

为什么不直接把user信息直接放在request里面?

request对象就是本次请求,我们可以在请求结束前的任意时刻,从request对象里获取与本次请求有关的数据。

实际上,确实可以通过request来持有用户数据的。但是从设计上、代码分层上来说,这样不好。

在Spring MVC框架中,request是一个比较底层的数据对象,一般我们不直接使用它。

而且并不是任意的位置都方便获取request对象,因为它不被容器管理,不是随便就能注入给一个Bean的。因为不鼓励这样做,requerst是表现层的对象,要是随便注入,你很可能会将其注入给service,从而产生耦合。所以,我们自己写一个组件,单独解决这个问题。原则上可以,但事实上不会,这是从代码合理性角度考量的。

我们封装一下:

package com.now.community.community.util;

import com.now.community.community.entity.User;
import org.springframework.stereotype.Component;

/**
 * 持有用户信息,用于代替session对象.
 */
@Component
public class HostHolder {

    private ThreadLocal users = new ThreadLocal<>();

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

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

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

}

取cookie封装:

package com.now.community.community.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

public class CookieUtil {
    public static String getValue(HttpServletRequest request, String name) {
        if (request == null || name == null) {
            throw new IllegalArgumentException("参数为空!");
        }
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }
}

 拦截器:

查用户放入hostholder

controller执行

查hostholder里的user

放入modelAndView

模板用数据显示界面

清除

package com.now.community.community.controller.interceptor;

import com.now.community.community.entity.LoginTicket;
import com.now.community.community.entity.User;
import com.now.community.community.service.UserService;
import com.now.community.community.util.CookieUtil;
import com.now.community.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
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;

@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");
        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) {
            modelAndView.addObject("loginUser", user);
        }
    }

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

}

 

你可能感兴趣的:(Java)