5、使用拦截器显示登录信息:通过cookie获得ticket,通过ticket获取loginticket对象,进而获得loginticket。
userID得到userId,进而获得user,将user存到hostHolder中,让本次请求中持有用户,为防止并发请求,需要对每个请求线程数据做隔离,使用ThreadLocal来set和get用户user,用完要清理release,同时还能代替session,减少服务器压力;
6、配置拦截器:先注入拦截器bean,再添加需要拦截的界面即可
--------------------------------------------------------------------------------------------------------------------------------
1.编写获取Cookie的工具类CookieUtil:
package com.nowcoder.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;
}
}
2.编写线程容器工具类HostHolder:
package com.nowcoder.community.util;
import com.nowcoder.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();
}
}
3.编写拦截器LoginTicketInterceptor:
package com.nowcoder.community.interceptor;
import com.nowcoder.community.entity.LoginTicket;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.LoginTicketServiceImpl;
import com.nowcoder.community.service.UserServiceImpl;
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;
@Component
public class LoginTicketInterceptor implements HandlerInterceptor {
@Autowired
private HostHolder hostHolder;
@Autowired
private LoginTicketServiceImpl loginTicketService;
@Autowired
private UserServiceImpl userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//从Cookie中获取凭证
String ticket = CookieUtil.getValue(request, "ticket");
if (ticket!=null){
//查询凭证
LoginTicket loginTicket = loginTicketService.selectByTicket(ticket);
//查询凭证是否有效
if (loginTicket!=null&&loginTicket.getStatus()==0&&loginTicket.getExpired().after(new Date())){
//根据凭证查询用户
User user = userService.selectById(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();
}
}
4.配置拦截器WebMvcConfig:
package com.nowcoder.community.config;
import com.nowcoder.community.interceptor.LoginRequiredInterceptor;
import com.nowcoder.community.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;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginTicketInterceptor loginTicketInterceptor;
@Autowired
private LoginRequiredInterceptor loginRequiredInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginTicketInterceptor)
.excludePathPatterns("/**/*.css","/**/*.js","/**/*.jpg","/**/*.png","/**/*.jpeg");
registry.addInterceptor(loginRequiredInterceptor)
.excludePathPatterns("/**/*.css","/**/*.js","/**/*.jpg","/**/*.png","/**/*.jpeg");
}
}
5.index.html:
<!-- 功能 -->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item ml-3 btn-group-vertical">
<a class="nav-link" th:href="@{/index}">首页</a>
</li>
<li class="nav-item ml-3 btn-group-vertical" th:if="${loginUser!=null}">
<a class="nav-link position-relative" th:href="@{/letter/list}">消息<span class="badge badge-danger">12</span></a>
</li>
<li class="nav-item ml-3 btn-group-vertical" th:if="${loginUser==null}">
<a class="nav-link" th:href="@{/register}">注册</a>
</li>
<li class="nav-item ml-3 btn-group-vertical" th:if="${loginUser==null}">
<a class="nav-link" th:href="@{/login}">登录</a>
</li>
<li class="nav-item ml-3 btn-group-vertical dropdown" th:if="${loginUser!=null}">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img th:src="${loginUser.headerUrl}" class="rounded-circle" style="width:30px;"/>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item text-center" th:href="@{|/profile/${loginUser.id}|}">个人主页</a>
<a class="dropdown-item text-center" th:href="@{/setting}">账号设置</a>
<a class="dropdown-item text-center" th:href="@{/logout}">退出登录</a>
<div class="dropdown-divider"></div>
<span class="dropdown-item text-center text-secondary" th:utext="${loginUser.username}">nowcoder</span>
</div>
</li>
</ul>
<!-- 搜索 -->
<form class="form-inline my-2 my-lg-0" action="site/search.html">
<input class="form-control mr-sm-2" type="search" aria-label="Search" />
<button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button>
</form>
</div>