Fegin拦截器解决各微服务之间数据下沉
上篇說(shuō)了當(dāng)前端訪(fǎng)問(wèn)微服務(wù)網(wǎng)關(guān),借助ZuulFilter過(guò)濾器來(lái)過(guò)濾所有請(qǐng)求,獲取request,判斷cookie是否有身份短令牌,request的header中是否有Jwt令牌,redis中是否有Jwt令牌。但是這個(gè)數(shù)據(jù)傳遞只能是前端訪(fǎng)問(wèn)微服務(wù)時(shí),網(wǎng)關(guān)進(jìn)行過(guò)濾,在微服務(wù)訪(fǎng)問(wèn)微服務(wù)時(shí),則沒(méi)有數(shù)據(jù)向下傳遞。
所以我們使用Fegin攔截器來(lái)做微服務(wù)之間的數(shù)據(jù)下沉,數(shù)據(jù)傳遞。
因?yàn)樵诿總€(gè)微服務(wù)使用Fegin遠(yuǎn)程調(diào)用時(shí)都會(huì)使用,所以寫(xiě)在了common包下。
import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest; import java.util.Enumeration;/** Fegin遠(yuǎn)程調(diào)用攔截器*/ public class FeignClientInterceptor implements RequestInterceptor {/*** 每次遠(yuǎn)程調(diào)用都會(huì)走這個(gè)方法* @param requestTemplate*/@Overridepublic void apply(RequestTemplate requestTemplate) {//的到requst中Header數(shù)據(jù)ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if(requestAttributes!=null){HttpServletRequest request = requestAttributes.getRequest();//取出header中的Jwt令牌Enumeration<String> headerNames = request.getHeaderNames();if(headerNames!=null){while(headerNames.hasMoreElements()){String headerName = headerNames.nextElement();String headerValue = request.getHeader(headerName);//向下傳遞requestTemplate.header(headerName,headerValue);}}}}}可以從代碼中看到,implements RequestInterceptor每個(gè)微服務(wù)遠(yuǎn)程調(diào)用都會(huì)走下面的實(shí)現(xiàn)方法,在apply()方法中,我們獲取當(dāng)前的request中Header中所有數(shù)據(jù),然后用requestTemplate.header(headerName,headerValue) 將所有數(shù)據(jù)下沉。
?
所以在使用fegin遠(yuǎn)程調(diào)用時(shí)是可以這樣利用fegin攔截器進(jìn)行數(shù)據(jù)下沉的,但是在使用別的方法遠(yuǎn)程調(diào)用微服務(wù)時(shí)這個(gè)攔截器是不會(huì)處理的。
比如說(shuō),當(dāng)我們使用的是restTemplate進(jìn)行遠(yuǎn)程調(diào)用時(shí),
//注入restTemplate@Bean@LoadBalanced//開(kāi)啟客戶(hù)端負(fù)載均衡public RestTemplate restTemplate(){return new RestTemplate(new OkHttp3ClientHttpRequestFactory());} //rest遠(yuǎn)程獲取數(shù)據(jù)ResponseEntity<Map> forEntity = restTemplate.getForEntity(dataUrl, Map.class);此時(shí)進(jìn)行數(shù)據(jù)下沉需要進(jìn)行數(shù)據(jù)處理,借助request中header的HttpEntity進(jìn)行數(shù)據(jù)存儲(chǔ),數(shù)據(jù)傳遞。
比如
private AuthToken applyToken(String clientId, String clientSecret, String username, String password) {//獲取認(rèn)證服務(wù) 的微服務(wù)實(shí)例ServiceInstance serviceInstance = loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH);if (serviceInstance == null) {LOGGER.error("choose an auth instance fail");ExceptionCast.cast(AuthCode.AUTH_LOGIN_AUTHSERVER_NOTFOUND);}// http://IP:port/URI uri = serviceInstance.getUri();String authUrl = uri + "/auth/oauth/token";//HttpEntity//bodyLinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<>();body.add("grant_type","password");body.add("username",username);body.add("password",password);//headersLinkedMultiValueMap<String, String> header = new LinkedMultiValueMap<>();header.add("Authorization",getHttpBasic(clientId,clientSecret));HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, header);//設(shè)置restTemplate遠(yuǎn)程調(diào)用時(shí),對(duì)400,401錯(cuò)誤不報(bào)錯(cuò),正確返回?cái)?shù)據(jù)restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){@Overridepublic void handleError(ClientHttpResponse response) throws IOException {if(response.getRawStatusCode()!=400&&response.getRawStatusCode()!=401){super.handleError(response);}}});//申請(qǐng)令牌的信息Map map = null;try {ResponseEntity<Map> bodyMap = restTemplate.exchange(authUrl, HttpMethod.POST, httpEntity, Map.class);map = bodyMap.getBody();} catch (RestClientException e) {e.printStackTrace();LOGGER.error("request oauth_token_password error: {}",e.getMessage());e.printStackTrace();ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);}if(map == null ||map.get("access_token") == null ||map.get("refresh_token") == null ||map.get("jti") == null){//確定用戶(hù)名 或者 密碼錯(cuò)誤異常拋出if(map!=null){String error_description = (String) map.get("error_description");if(error_description.indexOf("UserDetailsService returned null")>=0){ExceptionCast.cast(AuthCode.AUTH_ACCOUNT_NOTEXISTS);}else if(error_description.indexOf("壞的憑證")>=0){ExceptionCast.cast(AuthCode.AUTH_CREDENTIAL_ERROR);}}//jti是jwt令牌的唯一標(biāo)識(shí)作為用戶(hù)身份令牌ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);}AuthToken authToken = new AuthToken();//訪(fǎng)問(wèn)令牌(jwt)String jwt_token = (String) map.get("access_token");//刷新令牌(jwt)String refresh_token = (String) map.get("refresh_token");//jti,作為用戶(hù)的身份標(biāo)識(shí)String access_token = (String) map.get("jti");authToken.setJwt_token(jwt_token);authToken.setAccess_token(access_token);authToken.setRefresh_token(refresh_token);return authToken;}?
總結(jié)
以上是生活随笔為你收集整理的Fegin拦截器解决各微服务之间数据下沉的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言中声明复数用什么字母,用c语言定义
- 下一篇: org.hibernate.QueryT