一、项目中添加Spring MVC拦截器,拦截器怎么实现的,它的作用是什么?

拦截器的作用:让未登录的用户不能访问某些页面。 拦截器是在controller代码执行之前,根据用户请求做出相应的处理;

Spring Boot中的拦截器和Spring MVC中的一样,流程是:
1、先定义一个拦截器类,并且这个类需要实现HandlerInterceptor接口,重写接口中的三个方法:preHandle、postHandler、afterCompletion;

preHandle:此方法在进入controller之前执行,如果该方法返回ture,则程序继续向下执行处理器中的方法,否则程序将不再往下继续执行;
注意:会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则执行用户请求的url方法。
postHandler:此方法将在controller执行后执行;
afterCompletion:此方法在整个请求结束(请求结束,但是并未返回给客户端)之后执行;

2、将拦截器注入到配置类中(Config/WebMvcConfig.java)
配置拦截器,通过实现WebMvcConfigurer接口,重写addInterceptors方法,具体代码如下:

public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(alphaInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
.addPathPatterns("/register", "/login");}}

excludePathPatterns:表示不拦截的资源(这里主要是静态资源:图片,js、css也属于静态资源);
addPathPatterns:表示需要拦截的资源(即登录、注册)

拦截器执行流程:
1)单个拦截器执行流程:prehandle()—Handle(也就是控制器里的方法)—postHandle()—afterCompletion()。
2)多个拦截器执行流程:
preHandleA—preHandleC——Handle——postHandleC—postHandleA——afterCompletionC—afterCompletionA。

二、项目中使用redis优化登录功能,怎么优化?

1、为什么需要使用Redis的原因?
1)使用Redis存储验证码kaptcha;
a.验证码需要频繁的访问与刷新,对性能要求比较高;
b.验证码不需要永久保存,通常在很短的时间后就会失效;
c.分布式部署时,存在Session共享问题。
Session 是保存在服务器的⽂件中,如果是集群服务,同⼀个⽤户过来可能落在不同机器上,这就会导致⽤户频繁登陆;采⽤ Redis 保存 Session 后,无论⽤户落在那台机器上都能够获取到对应的Session 信息。
2)使用Redis存储登录凭证ticket;
a.处理每次请求时,都需要查询用户的登录凭证,访问的频率非常高。
3)使用Redis缓存用户信息user。
a.处理每次请求时,都要根据凭证查询用户信息,访问的频率非常高。

2、为什么Redis速度快、性能好?
(1)数据存放在内存中:内存的读写速度比磁盘(数据库)快的多;
(2)数据结构简单,对数据操作也简单;
(3)采⽤单线程,没有多线程竞争锁的性能消耗,也没有多线程导致的切换而消耗CPU, 或者多线程死锁等问题;
(4)使⽤多路 I/O 复⽤模型(解决单线程速度慢的问题),⾮阻塞 IO。

3、之前基于Session的登录功能怎么使用Redis优化?
1)登录注册功能的验证码之前是存放在Session中,会增加服务端的内存压力,现在通过Cookie获取信息存储到Redis中,Redis的key存随机字符串,Value存生成的字符串;并且设置60s后自动清理;然后就从redis中获取验证码,赋值给kaptcha;
Key值的获取:

String kaptchaOwner = CommunityUtil.generateUUID();
String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);

Key和Value值存储到Redis中:(其中text是value)

String text = kaptchaProducer.createText();
redisTemplate.opsForValue().set(redisKey, text,60, TimeUnit.SECONDS);

2)使用Redis存储登录凭证

String redisKey = RedisKeyUtil.getTicketKey(ticket.getTicket());     
redisTemplate.opsForValue().set(redisKey, ticket);        
map.put("ticket", ticket.getTicket());

3)每次请求,根据登录凭证,查询用户信息
a.优先从缓冲中取值;
b.取不到时初始化缓冲数据(redis存值);
c.数据变更时清除缓存(删除redis的Key)