網(wǎng)站首頁 編程語言 正文
????????在日常開發(fā)中,經(jīng)常我們需要在請求controller時傳遞用戶信息。那么有沒有一種方式可以讓我們的程序在用戶登錄后自動向controller接口中注入用戶用戶信息呢?
? ? ? ?答案是yes!!!現(xiàn)在我們來看看博主當(dāng)前的項目是如何實現(xiàn)的吧!
? ? ? ? 1.首先登錄時,賬號密碼校驗通過后生成一個token,并將用戶基本信息存入redis。將key返回給前端。
? ? ? ? 2.前端收到后將當(dāng)前用戶的token緩存起來,每次像后臺發(fā)請求時在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:{} 參數(shù):{}", uri.getPath(), query);
}
//獲取redis中用戶的緩存信息,拼接到請求參數(shù)后面
HttpHeaders headers = exchange.getRequest().getHeaders();
String token = headers.getFirst("token");
if (StringUtils.hasText(token)) {
AccountEntity accountEntity = accountAdminApiService.loginAccountAdmin(token);
if (accountEntity != null) {
//先去header中獲取診所ID,如果沒有去請求參數(shù)中獲取
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)));
}
}
//封裝其他參數(shù)
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 {
//獲取應(yīng)用類型
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參數(shù)解析器會自動將url后面的參數(shù)解析為對應(yīng)的AccountBean,這樣我們在需要用到Account信息的Controller方法中只需要在參數(shù)中加入AccountBean參數(shù)即可,。前端也不必刻意傳Account信息,因為Header中攜帶了Token。
? ? ? ?
原文鏈接:https://blog.csdn.net/weixin_47987440/article/details/125694110
相關(guān)推薦
- 2022-04-08 Swift實現(xiàn)簡單計算器_Swift
- 2022-05-26 簡單聊一聊SQL注入及防止SQL注入_數(shù)據(jù)庫其它
- 2022-03-26 使用C語言如何輸出逆序數(shù)_C 語言
- 2022-11-15 Python函數(shù)式編程之返回函數(shù)實例詳解_python
- 2022-05-29 利用Python將list列表寫入文件并讀取的方法匯總_python
- 2023-07-02 如何遠(yuǎn)程使用服務(wù)器上的Jupyter?notebook_python
- 2022-04-28 .net項目使用日志框架log4net_實用技巧
- 2023-01-18 GoLang完整實現(xiàn)快速列表_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支