权限实现
业务需求
当用户进行敏感操作时,必须要求用户先登录之后才可以访问后端服务器,例如淘宝、京东.....
使用技术:
1.AOP
2.拦截器:拦截用户的请求
定义拦截器
SpringMVC调用原理图
SpringMVC拦截器工作原理
配置拦截器
package com.jt.interceptor;
import com.jt.pojo.User;
import com.jt.theardLocal.UserTheardLocal;
import com.jt.util.CookieUtil;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import redis.clients.jedis.JedisCluster;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//将拦截器交给spring容器管理
@Component
public class UserInterceptor implements HandlerInterceptor {
//spring4版本必须实现所有的接口方法,在spring5中只需要重写指定的方法即可
@Autowired
private JedisCluster jedisCluster;
/**
*需求:拦截/cart开头的所有的请求进行拦截,并且校验用户是否登录。。。。
* 拦截器选择:preHanler
* 如何判断用户是否登录:1.检查cookie的信息,2.检查redis中是否有记录
* 如果已经登录过了true:请求应该放行
* 如果没有登录false:请求应该拦截,配合重定向的语法实现页面跳
* 转到登录页面,使的程序流转起来
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.判断用户是否登录
// 1.1检查cookie是否有值
String ticket = CookieUtil.getCookieValue(request, "JT_TICKET");
//1.2检查ticket是否为null
if(!StringUtils.isEmpty(ticket)){
//2.校验redis中是否有数据
if(jedisCluster.exists(ticket)){
//3.动态获取用户信息
String userJson=jedisCluster.get(ticket);
//4.将userJson转换成对象
User user = ObjectMapperUtil.toObj(userJson, User.class);
//5.用request将对象当做参数传输给handler,但是有个缺点,不是所有的方法中都可以用request
//request.setAttribute("JT_USER", user);
//在java中可以用ThreadLocal本地线程变量来完成参数的传输
UserTheardLocal.set(user);
return true;//如果有值则拦截器放行
}
}
//重定向到登录页面
response.sendRedirect("/user/login.html");
return false;//如果没有登录false:请求应该拦截,配合重定向的语法实现页面跳
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//销毁数据
//request.removeAttribute("JT_USER");
UserTheardLocal.remove();
}
}
动态获取UserId
ThreadLocal简单介绍
ThreadLocal作用
名称:本地线程变量
作用:可以在同一个线程内,实现数据的共享。
ThreadLocal入门案例
private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public void a(){
int a = 100;
threadLocal.set(a);
b();
}
public void b(){
int a = threadLocal.get();
int b = 100*a;
}
编辑ThreadLocal工具API
package com.jt.theardLocal;
import com.jt.pojo.User;
public class UserTheardLocal {
//这里的static不会影响线程,threadLocal在创建时跟随线程
//private static ThreadLocal<Map<k,v>> threadLocal = new ThreadLocal<>();
private static ThreadLocal<User> threadLocal=new ThreadLocal<>();
public static void set(User user){
threadLocal.set(user);
}
public static User get(){
return threadLocal.get();
}
public static void remove(){
threadLocal.remove();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。