最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot獲取當(dāng)前用戶信息的三種方式

 更新時(shí)間:2024年10月16日 11:10:40   作者:何中應(yīng)  
本文詳細(xì)介紹了在開發(fā)中獲取當(dāng)前操作用戶信息的三種方式:使用ThreadLocal存儲(chǔ)用戶信息、通過攔截器和注解結(jié)合Shiro框架獲取用戶信息、以及使用Redis存儲(chǔ)用戶信息,每種方式都有具體的實(shí)現(xiàn)步驟和注意事項(xiàng),可根據(jù)實(shí)際需求選擇合適的方法

說明:在開發(fā)中,我們經(jīng)常需要獲取當(dāng)前操作的用戶信息,如創(chuàng)建用戶、創(chuàng)建訂單時(shí),我們需要記錄下創(chuàng)建人,本文介紹獲取當(dāng)前用戶信息的三種方式。

方式一:使用ThreadLocal

ThreadLocal本質(zhì)上是一個(gè)Map,鍵是當(dāng)前線程,值是存入的信息。我們可以在用戶登錄,校驗(yàn)用戶信息后,將所需要的用戶信息存入到ThreadLocal中,如用戶ID、用戶Token等,然后在需要的時(shí)候直接使用即可。

如下,在preHandle()方法中,將當(dāng)前用戶的ID存入到TokenThreadLocal對(duì)象中,

@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Value("${token.key}")
    private String tokenKey;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
        // 獲取請(qǐng)求頭 拿到Token
        String token = request.getHeader("Token");
        String authToken = request.getHeader("authentication");

        if (StrUtil.isAllEmpty(token,authToken)){
           return responseHandler(response);
        }

        //  校驗(yàn)Token的合法性和有效性
        JWT jwt = JWTUtil.parseToken(StrUtil.isBlank(token) ? authToken : token);

        try {
            // 校驗(yàn)Token是否合法 校驗(yàn)Token是否過期
            if (!(jwt.setKey(tokenKey.getBytes()).verify() && jwt.validate(0))){
                return responseHandler(response);
            }
        } catch (Exception e) {
            // 拋出自定義異常 Token是非法的
            // throw new RuntimeException(e);
            return responseHandler(response);
        }

        // 把Token的信息解析出來放到ThreadLocal
        Long id = Convert.toLong(jwt.getPayload("id"));

        // 設(shè)置本地線程池中的用戶ID
        TokenThreadLocal.set(id);
        
        // 放行
        return true;
    }

本地線程對(duì)象,TokenThreadLocal

/**
 * 本地線程對(duì)象
 *
 * 存放用戶ID
 */
public class TokenThreadLocal {

    /**
     * 創(chuàng)建一個(gè)ThreadLocal對(duì)象
     */
    private static final ThreadLocal<Long> THREAD_LOCAL= new ThreadLocal<>();

    /**
     * 添加一個(gè)數(shù)據(jù)
     * @param key
     */
    public static void set(Long key){
        THREAD_LOCAL.set(key);
    }

    /**
     * 獲取一個(gè)數(shù)據(jù)
     * @return
     */
    public static Long get(){
        return THREAD_LOCAL.get();
    }

    /**
     * 刪除一個(gè)數(shù)據(jù)
     */
    public static void remove(){
        THREAD_LOCAL.remove();
    }
}

需要的時(shí)候,直接調(diào)用其get()方法,下面是使用AOP+自定義注解實(shí)現(xiàn)對(duì)創(chuàng)建、更新操作字段的填充;

在這里插入圖片描述

注意,需要在afterCompletion()方法中調(diào)用ThreadLocal的remove()方法,避免內(nèi)存泄漏;

在這里插入圖片描述

方式二:通過攔截器和相應(yīng)注解實(shí)現(xiàn)

如果項(xiàng)目中,登錄校驗(yàn)框架使用的是Shiro,有一種更方便的方式,如下:

第一步:創(chuàng)建一個(gè)自定義注解,如LoginInfo,表示登錄用戶的信息,注意元注解的屬性;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 登錄用戶
 * @author 
 */
@Target(value = ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginInfo {
}

第二步:創(chuàng)建MVC的配置類,注入一個(gè)在線用戶解析對(duì)象,后面實(shí)現(xiàn);

import org.decent.modules.integral.resolver.LoginUserArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import java.util.List;

/**
 * web設(shè)置
 * @author
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Resource
    private LoginUserArgumentResolver loginUserArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(loginUserArgumentResolver);
    }
}

第三步:創(chuàng)建在線用戶解析類,其中獲取當(dāng)前用戶的信息使用的是Shiro框架的方法,SecurityUtils.getSubject().getPrincipal(),該方法返回的是一個(gè)Object類型的對(duì)象;

import org.apache.shiro.SecurityUtils;
import org.decent.modules.integral.annotation.LoginInfo;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * 登錄解析實(shí)現(xiàn)
 *
 * @author
 */
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(LoginInfo.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        return SecurityUtils.getSubject().getPrincipal();
    }
}

第四步:創(chuàng)建一個(gè)在線用戶的JavaBean,存放一些可能會(huì)用得上的屬性;

import lombok.Data;

/**
 * 在線用戶信息
 */
@Data
public class LoginUser {

    /**
     * 登錄人id
     */
    private String id;

    /**
     * 登錄人賬號(hào)
     */
    private String username;

    /**
     * 登錄人名字
     */
    private String realname;
}

第五步:在需要使用的接口上,直接使用注解即可。當(dāng)請(qǐng)求訪問該接口時(shí),會(huì)被前面的攔截器攔截住,然后把當(dāng)前用戶的信息取出來并封裝到JavaBean對(duì)象中,非常方便;

	@PostMapping(value = "/add")
	public Result<?> add(@LoginInfo LoginUser loginUser) {
        ......
	}

方式三:使用Redis存儲(chǔ)用戶信息

這種方式思路和第一種相同,當(dāng)用戶通過校驗(yàn)時(shí),將用戶信息查詢出來并存起來,需要的時(shí)候再取出來用。當(dāng)然,使用Redis存儲(chǔ)比ThreadLocal更靈活一點(diǎn),可以設(shè)置有效時(shí)間。實(shí)現(xiàn)如下:

第一步:登錄驗(yàn)證通過,將用戶信息存入Redis;

    @PostMapping("/login")
    public Result<?> counterLogin(@RequestBody LoginBody LoginUser){
        // 登錄
        LoginUser userInfo = sysLoginService.login(LoginUser.getUsername(), LoginUser.getPassword(),LoginUser.getCounterType());
        
        // 創(chuàng)建Token并返回
        return Result.success(tokenService.createToken(userInfo));
    }
     @Autowired
    private RedisService redisService;

	// 定義有效時(shí)間,為720 * 60 秒,即12小時(shí)
    private final static long EXPIRE_TIME = 720 * 60;

	/**
     * 創(chuàng)建令牌
     */
    public Map<String, Object> createToken(LoginUser loginUser){
        // 生成token
        String token = IdUtils.fastUUID();
        loginUser.setToken(token);
        loginUser.setUserid(loginUser.getSysUser().getUserId());
        loginUser.setUsername(loginUser.getSysUser().getUserName());

        // 保存用戶token
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("token", token);
        map.put("loginUser",loginUser);

		// 將該用戶的信息存入到Redis中
        redisService.setCacheObject(token, loginUser, EXPIRE_TIME, TimeUnit.SECONDS);
        
        return map;
    }

RedisService類相關(guān)方法

/**
 * spring redis 工具類
 **/
@Component
public class RedisService{

    @Autowired
    public RedisTemplate redisTemplate;
    
    /**
     * 緩存基本的對(duì)象
     */
    public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit){
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 獲得緩存的基本對(duì)象
     */
    public <T> T getCacheObject(final String key){
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }
}

第三步:需要時(shí),根據(jù)當(dāng)前用戶的Token,去Redis中取出該用戶的信息;

    /**
     * 根據(jù)用戶Token獲取用戶身份信息
     *
     * @return 用戶信息
     */
    public LoginUser getLoginUser(String token){
        if (StringUtils.isNotEmpty(token)){
            String userKey = getTokenKey(token);
            LoginUser user = redisService.getCacheObject(userKey);
            return user;
        }
        return null;
    }

用戶的Token是需要放在Request對(duì)象里面的,所以可以再寫一個(gè)TokenService對(duì)象,用來獲取當(dāng)前用戶的Token,并調(diào)用RedisService獲取當(dāng)前用戶信息,進(jìn)行進(jìn)一步的封裝。

總結(jié)

以上是三種獲取當(dāng)前用戶信息的方式,可以根據(jù)實(shí)際情況選擇;更多相關(guān)springboot獲取當(dāng)前用戶信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Mybatis中萬能的Map和模糊查詢寫法

    詳解Mybatis中萬能的Map和模糊查詢寫法

    這篇文章主要介紹了Mybatis中萬能的Map和模糊查詢寫法的相關(guān)資料,幫助大家更好的理解和使用Mybatis,感興趣的朋友可以了解下
    2021-03-03
  • Mybatis的核心配置文件使用方法

    Mybatis的核心配置文件使用方法

    Mybatis的核心配置文件有兩個(gè),一個(gè)是全局配置文件,它包含了會(huì)深深影響Mybatis行為的設(shè)置和屬性信息;一個(gè)是映射文件,它很簡單,讓用戶能更專注于SQL代碼,本文主要介紹了Mybatis的核心配置文件使用方法,感興趣的可以了解一下
    2023-11-11
  • Mybatis配置解析看這一篇就夠了

    Mybatis配置解析看這一篇就夠了

    這篇文章主要介紹了詳解Mybatis是如何解析配置文件的,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • 通俗易懂學(xué)習(xí)java并發(fā)工具類-Semaphore,Exchanger

    通俗易懂學(xué)習(xí)java并發(fā)工具類-Semaphore,Exchanger

    這篇文章主要介紹了java并發(fā)工具類-Semaphore,Exchanger,java并發(fā)工具類有很多,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面小編帶大家來一起學(xué)習(xí)一下吧
    2019-06-06
  • Java創(chuàng)建線程的七種方法總結(jié)(全網(wǎng)最全面)

    Java創(chuàng)建線程的七種方法總結(jié)(全網(wǎng)最全面)

    線程是Java中的基本執(zhí)行單元,它允許程序在同一時(shí)間執(zhí)行多個(gè)任務(wù),下面這篇文章主要給大家總結(jié)介紹了關(guān)于Java創(chuàng)建線程的七種方法,文中通過實(shí)例代碼將這七種方法介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • Maven統(tǒng)一版本管理的實(shí)現(xiàn)

    Maven統(tǒng)一版本管理的實(shí)現(xiàn)

    在使用Maven多模塊結(jié)構(gòu)工程時(shí),配置版本是一個(gè)比較頭疼的事,本文主要介紹了Maven統(tǒng)一版本管理的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • SpringBoot整合Mybatis-plus的具體過程使用

    SpringBoot整合Mybatis-plus的具體過程使用

    這篇文章主要介紹了SpringBoot?整合mybatis+mybatis-plus的步驟,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • spring中時(shí)間格式化的兩種方法示例講解

    spring中時(shí)間格式化的兩種方法示例講解

    這篇文章主要介紹了spring中時(shí)間格式化的兩種方法,方法一自己格式化,方法二通過配置,結(jié)合實(shí)例代碼講解的非常詳細(xì),文中補(bǔ)充介紹了Spring項(xiàng)目中時(shí)間格式化的方法,需要的朋友可以參考下
    2023-08-08
  • java創(chuàng)建以任意圖片為背景的窗口

    java創(chuàng)建以任意圖片為背景的窗口

    這篇文章主要為大家詳細(xì)介紹了java創(chuàng)建以任意圖片為背景的窗口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • mybatis之foreach用法詳解

    mybatis之foreach用法詳解

    這篇文章主要介紹了mybatis之foreach用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論

陕西省| 聂荣县| 临清市| 淮阳县| 永仁县| 石门县| 肥东县| 中阳县| 汉阴县| 临沂市| 北票市| 德江县| 牡丹江市| 临夏县| 馆陶县| 丰都县| 乌海市| 政和县| 宜丰县| 陈巴尔虎旗| 望谟县| 富宁县| 云南省| 土默特右旗| 长武县| 涡阳县| 灵璧县| 同江市| 阿克陶县| 增城市| 金坛市| 东山县| 镇赉县| 阜康市| 龙川县| 郯城县| 略阳县| 长沙市| 米泉市| 乳山市| 汉中市|