spring里配置应用上下文

应用上下文的核心类是threadLocal类来实现线程隔离的核心


package com.company.common.context;

/**
 * 用户上下文支持
 */
public final class UserContextHolder {

    private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>();

    private UserContextHolder() {
    }

    public static UserContext getContext() {

        // 获取线程私有内存信息
        UserContext context = CONTEXT_HOLDER.get();

        if (context == null) {
            context = new UserContext();
            CONTEXT_HOLDER.set(context);
        }
        return context;
    }

    public static void setContext(UserContext context) {
        CONTEXT_HOLDER.set(context);
    }

    public static void clearContext() {
        CONTEXT_HOLDER.remove();
    }

}

package com.company.common.context;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserContext {

    /**
     * 登录用户ID
     */
    private Long id;
    /**
     * 登录用户名称
     */
    private String name;

}

应用上下文主要用来存储用户登录信息的token
存入token的地方在拦截器处

package com.company.common.iam;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import lombok.extern.slf4j.Slf4j;

import com.company.common.context.UserContext;
import com.company.common.context.UserContextHolder;
import com.company.common.exception.UnauthorizedException;
import com.company.common.memory.caches.AbstractMemoryStorage;
import com.company.common.memory.caches.RedisMemoryStorage;
import com.company.common.util.TokenUtils;

import org.springframework.util.StringUtils;
import org.springframework.web.servlet.AsyncHandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;


@Slf4j
public class IamInterceptor implements AsyncHandlerInterceptor {

    private final AbstractMemoryStorage memoryStorage;

    public IamInterceptor(AbstractMemoryStorage memoryStorage) {
        this.memoryStorage = memoryStorage;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.info("request_url: {}", request.getRequestURI());
        String token = TokenUtils.getRequestToken(request);

        if (!StringUtils.hasText(token) || "undefined".equalsIgnoreCase(token)) {
            throw new UnauthorizedException("认证失败");
        }

        JWT jwt = JWTUtil.parseToken(token);
        JSONObject payloads = jwt.getPayloads();
        Long id = payloads.getLong(TokenUtils.KEY_ID);
        String userName = payloads.getStr(TokenUtils.KEY_USER_NAME);

        String key = RedisMemoryStorage.LOGIN_TOKEN_KEY + SecureUtil.md5(userName + token);
        String memToken = memoryStorage.get(key);

        if (!token.equals(memToken)) {
            throw new UnauthorizedException("认证失败");
        }

        UserContextHolder.setContext(new UserContext(id, userName));

        memoryStorage.set(key, token, TokenUtils.TOKEN_TIMEOUT, TimeUnit.MILLISECONDS);
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        UserContextHolder.clearContext();
    }

}

内存缓存用的redis

package com.company.common.memory.caches;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

public class RedisMemoryStorage extends AbstractMemoryStorage {

    public final static String IP_BLOCK_KEY = "IpBlock:";

    public final static String REFERRAL_CODE_KEY = "ReferralCode:";

    public final static String LOGIN_TOKEN_KEY = "LoginToken:";

    public static final String WX_SESSION_ID = "wx_session_id";
    
    public static final String MA_USER_TOKEN_KEY = "ma_user_token:";
    
    public static final String MA_USER_ORDER_KEY = "ma_user_order:";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void set(String key, String value) {
        ValueOperations ops = stringRedisTemplate.opsForValue();

        ops.set(key, value);
    }

    @Override
    public void set(String key, String value, long timeout, TimeUnit unit) {

        ValueOperations ops = stringRedisTemplate.opsForValue();

        ops.set(key, value, timeout, unit);
    }

    @Override
    public String get(String key) {
        ValueOperations ops = stringRedisTemplate.opsForValue();
        return ops.get(key);
    }

    @Override
    public  T get(String key, Class clazz) {

        ValueOperations ops = stringRedisTemplate.opsForValue();

        String s = ops.get(key);

        if (!StringUtils.hasText(s)) {
            return null;
        }

        return JSONObject.parseObject(s, clazz);
    }

    @Override
    public Long getExpire(String key, TimeUnit unit) {
        return stringRedisTemplate.getExpire(key, unit);
    }

    @Override
    public void delete(String key) {
        stringRedisTemplate.delete(key);
    }

    @Override
    public Boolean hasKey(String key) {
        return stringRedisTemplate.hasKey(key);
    }

}

你可能感兴趣的:(spring里配置应用上下文)