拦截器(Intercepter)在controllor之前运行
拦截器在本项目中的应用:
1.在访问之前可以通过拦截器“看看浏览器中有没有可用cookie”,有则直接登录。
2.访问一些特定权限页面(如setting)时,“通过拦截器看看浏览器中有没有可用cookie”,有则访问,无则直接跳转至主页。
注册拦截器:
@Component
public class ToutiaoWebConfiguration extends WebMvcConfigurerAdapter {
@Autowired
PassportIntercepter passportIntercepter;
@Autowired
LoginRequiredIntercepter loginRequiredIntercepter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册两个拦截器
registry.addInterceptor(passportIntercepter);//看看这个用户是谁。这个拦截器处理全局路径
registry.addInterceptor(loginRequiredIntercepter).addPathPatterns("/setting*");//看看这个用户是否符合我的要求。这个拦截器只处理/setting或者以后的页面,不然则不调用这个拦截器
super.addInterceptors(registry);
}
}
第一个功能:
@Component
public class PassportIntercepter implements HandlerInterceptor {
@Autowired
private LoginTicketDAO loginTicketDAO;
@Autowired
private UserDAO userDAO;
@Autowired
private HostHolder hostHolder;
//override函数重载
//只有这个函数返回 true 的时候,才会去跑后面的两个函数
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String ticket = null;
if(httpServletRequest.getCookies()!=null)
{
for (Cookie cookie : httpServletRequest.getCookies())
{
System.out.println("跑了PassportIntercepter里的preHandle"+cookie.getName().toString()+" "+cookie.getValue().toString());
//去找找有没有ticket
if (cookie.getName().equals("ticket"))
{
ticket = cookie.getValue();
break;
}
}
}
//说明这个用户是登录过的,但是也不一定,因为可能会有伪造ticket的可能。所有要去查表二次验证
if(ticket !=null)
{
LoginTicket loginTicket = loginTicketDAO.selectByTicket(ticket);
if (loginTicket == null || loginTicket.getExpired().before(new Date())||loginTicket.getStatus()!=0 )
return true;
User user = userDAO.selectById(loginTicket.getUserId());
hostHolder.setUsers(user);
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
if(modelAndView != null && hostHolder.getUser() != null)
{
modelAndView.addObject("user",hostHolder.getUser());
}
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
hostHolder.clear();
}
}
第二个功能:
package com.nowcoder.interceptor;
import com.nowcoder.dao.LoginTicketDAO;
import com.nowcoder.dao.UserDAO;
import com.nowcoder.model.HostHolder;
import com.nowcoder.model.LoginTicket;
import com.nowcoder.model.User;
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.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
@Component
public class LoginRequiredIntercepter implements HandlerInterceptor {
@Autowired
private HostHolder hostHolder;
//将函数重载一下
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("跑了LoginRequiredIntercepter里的preHandle");
if(hostHolder.getUser() != null)
System.out.println("用户是: "+hostHolder.getUser().getId()+" "+hostHolder.getUser().getName());
//如果没有用户
if(hostHolder.getUser() == null)
{
System.out.println("hostholder里面已经没有用户了");
httpServletResponse.sendRedirect("/?pop=1");//pop是前端写的一个弹出的参数
return false;
}
//如果已经登录了,就直接返回true
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
在model中加一个hostholder类,用于记录目前的主机用户
//专门用来存储这次访问的用户是谁
@Component
public class HostHolder {
//每一个线程都有一份拷贝 理解成一个Map ThreadLocalMap<thread,User>
private static ThreadLocal<User> users = new ThreadLocal<User>();
public User getUser()
{
return users.get();
}
//set的时候默认把当前线程set到key中,引用类型User对象作为value.
public void setUsers(User user)
{
users.set(user);
}
public void clear()
{
users.remove();
}
}