需求介绍—显示登录信息

  我们需要在每个页面的头部都要把登录用户的头像显示出来,另外在详细信息里面你需要显示用户的名字,除此之外如果登录了,我们显示首页 信息 头像 三个功能的链接,否则显示首页 登录两个功能点,也就是根据登录与否显示头部的内容。

  我们每个静态页面都有这个内容,都需要显示登录信息,那么开发这个功能你需要每个请求都需要实现这个工能。我们想要低耦合的解决这个功能,就利用 Spring 的拦截器,它可以拦截访问服务器的请求,拦截请求之后可以在拦截这个请求之后的开始或者结束的部分插入一些代码,从而解决一些请求共有点的一些功能实现。

代码实现

使用拦截器的方法:

先写一个类实现 HandlerInterceptor 接口,然后配置拦截器的处理范围,拦截哪些请求,不拦截哪些请求。写个实例,先写类 AlphaInterceptor 实现 HandlerInterceptor 接口:

package com.nowcoder.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之前执行
// Object是拦截的方法
@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之后执行
// 异常是在调用Controller或者模板过程中出现了异常就会赋值给这个ex参数
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.debug("afterCompletion: " + handler.toString());
}
}

  

我们写好了之后要写一个配置类 WebMvcConfig:

一般配置类都是引入第三方的 Bean,但是拦截器需要实现 WebMvcConfigurer 接口。

package com.nowcoder.community.config;

import com.nowcoder.community.controller.interceptor.AlphaInterceptor;
import com.nowcoder.community.controller.interceptor.LoginRequiredInterceptor;
import com.nowcoder.community.controller.interceptor.LoginTicketInterceptor;
import com.nowcoder.community.controller.interceptor.MessageInterceptor;
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;
// .excludePathPatterns 表示哪些路径不被拦截比方说一些静态资源,
// .addPathPatterns 表示确定的拦截的路径
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(alphaInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
.addPathPatterns("/register", "/login");
}

  

知道拦截器怎么用了,我们就正式来写一下,根据我们的需求,

我们需要在请求开始时查询登录用户,然后在本次请求中持有用户数据(就是存到内存里),然后在模板视图上引用,最后在请求结束时清理用户数据。

第一步我们知道 Cookie 是从 HttpServletRequest 对象里面取出来的,因为很多情况下都需要获获取 Cookie,所以写一个工具帮我们实现一下 CookieUtil:

package com.nowcoder.community.util;

import org.springframework.web.bind.annotation.CookieValue;

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

  

  其次我们说了我们通过 Ticket 查询到的用户,我们需要把它存下来,但是由于服务器对应客户端是一对多的,它是一个处理多线程的,每个线程隔离的存这个对象,那么我们写个工具 HostHolder 存 User 对象,起到一个容器的作用:

package com.nowcoder.community.util;

import com.nowcoder.community.entity.User;
import org.springframework.stereotype.Component; /**
* 持有用户信息,用于代替session对象
*/
@Component
public class HostHolder {
private ThreadLocal<User> users = new ThreadLocal<>(); public void setUser(User user) {
users.set(user);
} public User getUser() {
return users.get();
} public void clear() {
users.remove();
}
}

  

然后写个拦截器 LoginTicketInterceptor:

package com.nowcoder.community.controller.interceptor;

import com.nowcoder.community.entity.LoginTicket;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.UserService;
import com.nowcoder.community.util.CookieUtil;
import com.nowcoder.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.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
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.net.Authenticator;
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());
// 在本次请求中持有用户,多线程,利用ThreadLocal
hostHolder.setUser(user);
}
}
return true;
}
// 在模板引擎调用之前把这个User存放到modelAndView里面
@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();
SecurityContextHolder.clearContext();
}
}

  

写好拦截器就要注入到 WebMvcConfig:

package com.nowcoder.community.config;

import com.nowcoder.community.controller.interceptor.AlphaInterceptor;
import com.nowcoder.community.controller.interceptor.LoginRequiredInterceptor;
import com.nowcoder.community.controller.interceptor.LoginTicketInterceptor;
import com.nowcoder.community.controller.interceptor.MessageInterceptor;
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; @Autowired
private LoginTicketInterceptor loginTicketInterceptor; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(alphaInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
.addPathPatterns("/register", "/login"); registry.addInterceptor(loginTicketInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");
}

  

然后就是处理页面了。

SpringBoot开发十一-显示登录信息的更多相关文章

  1. World Wind Java开发之三 显示状态栏信息

    先来看下本篇博客索要达到的效果: 找到源代码下的gov.nasa.worldwind.util下的StatusBar.java文件,能够看到状态栏显示的信息主要包含视点高度以及相应空间点三维坐标以及是 ...

  2. World Wind Java开发之三 显示状态栏信息(转)

    http://blog.csdn.net/giser_whu/article/details/40920315 先来看下本篇博客索要达到的效果: 找到源码下的gov.nasa.worldwind.ut ...

  3. SpringBoot开发十三-检查登录状态

    需求介绍-检查登录状态 防止用户知道我们的一些功能的链接,直接就进到了该页面,就像有些功能是管理员访问才能进的,就需要进行登录状态的判断. 我们知道这个功能点很多其他的功能点都需要使用,所以我们需要使 ...

  4. Centos启动时停止在登录界面但不显示登录信息(一直在转圈)

    进入单用户模式  执行 iscsiadm -m node -o delete,然后reboot

  5. SpringBoot Web开发(5) 开发页面国际化+登录拦截

    SpringBoot Web开发(5) 开发页面国际化+登录拦截 一.页面国际化 页面国际化目的:根据浏览器语言设置的信息对页面信息进行切换,或者用户点击链接自行对页面语言信息进行切换. **效果演示 ...

  6. [springboot 开发单体web shop] 5. 用户登录及首页展示

    用户登录及前端展示 用户登录 在之前的文章中我们实现了用户注册和验证功能,接下来我们继续实现它的登录,以及登录成功之后要在页面上显示的信息. 接下来,我们来编写代码. 实现service 在com.l ...

  7. DedeCMS中实现在顶层banner中显示自定义登录信息

    一.需求描述 dedeCMS自带的模板中有互动中心模块,如下图所示: 由于会员登陆对我来说不是网站的重要模块且默认DedeCMS的会员中心模块的初始化很慢,常会显示“正在载入中,请稍候...”, 所以 ...

  8. Linux显示登录Shell信息

    Linux显示登录Shell信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ finger -p Login Name Tty Idle Login Tim ...

  9. SpringBoot 使用 RestTemplate 调用exchange方法 显示错误信息

    SpringBoot使用RestTempate SpringBoot使用RestTemplate摘要认证 SpringBoot使用RestTemplate基础认证 SpringBoot使用RestTe ...

随机推荐

  1. Docker Swarm介绍

    1 什么是swarmSwarm是Docker公司推出的docker集群管理平台,它将一群Docker主机变成了一台单一的虚拟Docker主机.Swarm使用标准的Docker API接口,因此,任何支 ...

  2. promise的基本使用

    // 什么情况下适用promise? // 一般情况下是有异步请求操作时,使用promise对这个异步操作进行封装 // new ->构造函数(1.保存了一些状态信息 2.执行传入的函数) // ...

  3. vim编辑器使用方法(相关指令)

    1.跳到文本的最后一行:按"G",即"shift+g" 2.跳到最后一行的最后一个字符 : 先重复1的操作即按"G",之后按"$& ...

  4. coretext简单使用

    相对于UIKit,使用coretext绘制文本效率高,具有更高的自由度,可随时插入图片,增加文本点击事件等. 1.增加文本的点击事件 思路:定义UILabel子类,设置可点击的富文本range及其他属 ...

  5. tcp三次握手四次挥手----转

    序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生:给字节编上序号后,就给每一个报文段指派一个序号:序列号seq就是这个报文 ...

  6. WPF教程十四:了解元素的渲染OnRender()如何使用

    上一篇分析了WPF元素中布局系统的MeasureOverride()和ArrangeOverride()方法.本节将进一步深入分析和研究元素如何渲染它们自身. 大多数WPF元素通过组合方式创建可视化外 ...

  7. ADC采集电流相关知识

    1.AD电流采样电路,是把电路中的电流用采样元件转换为电压信号,然后用ADC量化转换为相应的数字信号.需要你在被采集端串联一个采样电阻,然后采集采样电阻两端的电压,这样就可以把电流输出变换为电压输出. ...

  8. 基于Flink构建全场景实时数仓

    目录: 一. 实时计算初期 二. 实时数仓建设 三. Lambda架构的实时数仓 四. Kappa架构的实时数仓 五. 流批结合的实时数仓 实时计算初期 虽然实时计算在最近几年才火起来,但是在早期也有 ...

  9. NOIP 模拟赛 day5 T2 水 故事题解

    题目描述 有一块矩形土地被划分成 \(\small n×m\) 个正方形小块.这些小块高低不平,每一小块都有自己的高度.水流可以由任意一块地流向周围四个方向的四块地中,但是不能直接流入对角相连的小块中 ...

  10. 建立属于自己的scrapy crawl模板

    本人安装PYTHON3.7安装位置:D:\Python\Python37模板位置:D:\Python\Python37\Lib\site-packages\scrapy\templates\spide ...