網站首頁 編程語言 正文
????????在日常開發中,經常我們需要在請求controller時傳遞用戶信息。那么有沒有一種方式可以讓我們的程序在用戶登錄后自動向controller接口中注入用戶用戶信息呢?
? ? ? ?答案是yes!!!現在我們來看看博主當前的項目是如何實現的吧!
? ? ? ? 1.首先登錄時,賬號密碼校驗通過后生成一個token,并將用戶基本信息存入redis。將key返回給前端。
? ? ? ? 2.前端收到后將當前用戶的token緩存起來,每次像后臺發請求時在header中攜帶token。
? ? ? ? 3.重點來了,在gateway中添加一個過濾器,在過濾器中獲取到tocken,用token作為鍵,去redis中獲取用戶的賬號,以及診所等基本信息。并將這些信息拼接到url后面。代碼示例如下:
package com.lvyuanji.gateway.filter;
import cn.hutool.core.util.StrUtil;
import com.lvyuanji.account.api.service.IAccountAdminApiService;
import com.lvyuanji.common.consts.SystemConsts;
import com.lvyuanji.common.vo.redis.AccountEntity;
import com.lvyuanji.common.vo.redis.SalesmanLoginVo;
import com.lvyuanji.stock.api.service.ISalesmanApiService;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator;
@Component
public class AccountRequestParameterGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
private static final Logger logger = LoggerFactory.getLogger(AccountRequestParameterGatewayFilterFactory.class);
@Reference
private IAccountAdminApiService accountAdminApiService;
@Reference
private ISalesmanApiService salesmanApiService;
@Override
public GatewayFilter apply(NameValueConfig config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
URI uri = request.getURI();
StringBuilder query = new StringBuilder();
String originalQuery = uri.getRawQuery();
if (StringUtils.hasText(originalQuery)) {
query.append(originalQuery);
if (originalQuery.charAt(originalQuery.length() - 1) != '&') {
query.append('&');
}
}
String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
// TODO urlencode?
query.append(config.getName());
query.append('=');
query.append(value);
String method = request.getMethodValue();
if ("GET".equals(method.toUpperCase())) {
logger.info("【GET】請求 URI:{} 參數:{}", uri.getPath(), query);
}
//獲取redis中用戶的緩存信息,拼接到請求參數后面
HttpHeaders headers = exchange.getRequest().getHeaders();
String token = headers.getFirst("token");
if (StringUtils.hasText(token)) {
AccountEntity accountEntity = accountAdminApiService.loginAccountAdmin(token);
if (accountEntity != null) {
//先去header中獲取診所ID,如果沒有去請求參數中獲取
String tenantId = headers.getFirst("tenantId");
if (StringUtils.hasText(tenantId)) {
accountEntity.setTenantId(Long.valueOf(tenantId));
} else {
List<String> tenantIds = request.getQueryParams().get("tenantId");
if (!CollectionUtils.isEmpty(tenantIds)) {
accountEntity.setTenantId(Long.valueOf(tenantIds.get(0)));
}
}
//封裝其他參數
Map<String, Object> beanMap = beanValue(accountEntity);
if (!CollectionUtils.isEmpty(beanMap)) {
for (String key : beanMap.keySet()) {
try {
Object obj = beanMap.get(key);
String param = obj != null ? URLEncoder.encode(obj.toString(), "UTF-8") : null;
query.append('&').append(key).append('=').append(param);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
} else {
//獲取應用類型
String appType = StrUtil.isNotEmpty(request.getHeaders().getFirst(SystemConsts.APP_TYPE)) ? request.getHeaders().getFirst(SystemConsts.APP_TYPE) : "";
if ("applets".equals(appType)) {
query.append("&").append("userType").append("=").append("SALESMAN");
}
}
} else {
String tenantId = headers.getFirst("tenantId");
if (StringUtils.hasText(tenantId)) {
query.append('&').append("tenantId").append('=').append(tenantId);
}
}
try {
String queryStr = filterOperator(query.toString());
URI newUri = UriComponentsBuilder.fromUri(uri)
.replaceQuery(queryStr).build(true).toUri();
ServerHttpRequest req = exchange.getRequest().mutate().uri(newUri)
.build();
return chain.filter(exchange.mutate().request(req).build());
} catch (RuntimeException ex) {
throw new IllegalStateException(
"Invalid URI query: \"" + query.toString() + "\"");
}
}
@Override
public String toString() {
return filterToStringCreator(AccountRequestParameterGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
}
};
}
/**
* 過濾特殊字符
*
* @param target
* @return
*/
private String filterOperator(String target) {
target = target.replace("[", "");
return target.replace("]", "");
}
/**
* 獲取bean的屬性和值
*
* @param bean
* @return
*/
private Map<String, Object> beanValue(AccountEntity bean) {
Map<String, Object> result = new HashMap<>();
Class clazz = bean.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
field.setAccessible(true);
Object value = null;
try {
value = field.get(bean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (value != null) {
result.put(name, value);
}
}
return result;
}
}
????????4.spring參數解析器會自動將url后面的參數解析為對應的AccountBean,這樣我們在需要用到Account信息的Controller方法中只需要在參數中加入AccountBean參數即可,。前端也不必刻意傳Account信息,因為Header中攜帶了Token。
? ? ? ?
原文鏈接:https://blog.csdn.net/weixin_47987440/article/details/125694110
相關推薦
- 2022-04-28 Python的命令行參數實例詳解_python
- 2022-07-27 Python中的re正則表達式模塊_python
- 2022-03-26 Android實現調用攝像頭拍照并存儲照片_Android
- 2022-12-03 FFmpeg?Principle分析Out?put?File?數據結構_Android
- 2023-04-18 antd中form表單的wrapperCol和labelCol問題詳解_React
- 2022-04-11 C++?std::initializer_list?實現原理解析及遇到問題_C 語言
- 2022-09-06 Python利用contextvars實現管理上下文變量_python
- 2022-10-28 Go語言開發保證并發安全實例詳解_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支