中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

做企業(yè)網(wǎng)站要用什么軟件谷歌chrome官網(wǎng)

做企業(yè)網(wǎng)站要用什么軟件,谷歌chrome官網(wǎng),做學(xué)術(shù)研究的網(wǎng)站,dede大氣企業(yè)網(wǎng)站模板(一屏展示)FeignClient介紹 FeignClient 是 Spring Cloud 中用于聲明一個(gè) Feign 客戶端的注解。由于SpringCloud采用分布式微服務(wù)架構(gòu),難免在各個(gè)子模塊下存在模塊方法互相調(diào)用的情況。比如訂單服務(wù)要調(diào)用庫(kù)存服務(wù)的方法,FeignClient()注解就是為了解決這個(gè)問(wèn)題的…

@FeignClient介紹

@FeignClient 是 Spring Cloud 中用于聲明一個(gè) Feign 客戶端的注解。由于SpringCloud采用分布式微服務(wù)架構(gòu),難免在各個(gè)子模塊下存在模塊方法互相調(diào)用的情況。比如訂單服務(wù)要調(diào)用庫(kù)存服務(wù)的方法,@FeignClient()注解就是為了解決這個(gè)問(wèn)題的。

Feign 是一個(gè)聲明式的 Web Service 客戶端,它的目的是讓編寫(xiě) HTTP 客戶端變得更簡(jiǎn)單。通過(guò) Feign,只需要?jiǎng)?chuàng)建一個(gè)接口,并使用注解來(lái)描述請(qǐng)求,就可以直接執(zhí)行 HTTP 請(qǐng)求了。

@FeignClient()注解的源碼要求它必須在Interface接口上使用( FeignClient注解被@Target(ElementType.TYPE)修飾,表示FeignClient注解的作用目標(biāo)在接口上)

SpringBoot服務(wù)的啟動(dòng)類(lèi)必須要有@EnableFeignClients 注解才能使@FeginClient注解生效。

@FeignClient工作原理及整體流程

Feign服務(wù)調(diào)用的工作原理可以總結(jié)為以下幾個(gè)步驟

  1. 首先通過(guò)@EnableFeignCleints注解開(kāi)啟FeignCleint。
  2. 根據(jù)Feign的規(guī)則實(shí)現(xiàn)接口,添加@FeignCleint注解。程序啟動(dòng)后,會(huì)掃描所有有@FeignCleint的類(lèi),并將這些信息注入到ioc容器中。
  3. 注入時(shí)從FeignClientFactoryBean.class獲取FeignClient。
  4. 當(dāng)接口的方法被調(diào)用時(shí),通過(guò)jdk的代理,來(lái)生成具體的RequesTemplate,RequesTemplate生成http的Request。
  5. Request交給Client去處理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp。
  6. Client被封裝到LoadBalanceClient類(lèi),這個(gè)類(lèi)結(jié)合類(lèi)Ribbon做到了負(fù)載均衡。

整體流程
在這里插入圖片描述

@FeignClient常用屬性

name、value

指定FeignClient的名稱,如果項(xiàng)目使用了Ribbon,name屬性會(huì)作為微服務(wù)的名稱,用于服務(wù)發(fā)現(xiàn)
這兩個(gè)屬性的作用是一樣的,如果沒(méi)有配置url,那么配置的值將作為服務(wù)的名稱,用于服務(wù)的發(fā)現(xiàn),反之只是一個(gè)名稱。

@FeignClient(name = "order-server")
public interface OrderRemoteClient {@GetMapping("/order/detail")public Order detail(@RequestParam("orderId") String orderId);
}

注意

  • 這里寫(xiě)的是你要調(diào)用的那個(gè)服務(wù)的名稱(spring.application.name屬性配置),而不是你自己的那個(gè)服務(wù)的名稱。
  • 如果同一個(gè)工程中出現(xiàn)兩個(gè)接口使用一樣的服務(wù)名稱會(huì)報(bào)錯(cuò)。原因是Client名字注冊(cè)到容器中重復(fù)了。除非指定不同的contextId參數(shù)。

    Description:
    The bean ‘order-server.FeignClientSpecification’, defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.
    Action:
    Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

兩種解決方案:

  • 增加配置 spring.main.allow-bean-definition-overriding=true
  • 為每個(gè)FeignClient手動(dòng)指定不同的contextId

contextId

比如我們有個(gè)user服務(wù),但user服務(wù)中有很多個(gè)接口,我們不想將所有的調(diào)用接口都定義在一個(gè)類(lèi)中,那就可以給不同的client指定contextId,不然就會(huì)報(bào)Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true異常。
注意:contextId不能帶_等符號(hào)。

@FeignClient(name = "order-server")
public interface OrderRemoteClient {@GetMapping("/api/order/detail", contextId = "OrderRemoteClient")public Order detail(@RequestParam("orderId") String orderId);
}

上面給出了Bean名稱沖突后的解決方案,下面來(lái)分析下contextId在Feign Client的作用,在注冊(cè)Feign Client Configuration的時(shí)候需要一個(gè)名稱,名稱是通過(guò)getClientName方法獲取的:

String name = getClientName(attributes);registerClientConfiguration(registry, name,
attributes.get("configuration"));
private String getClientName(Map<String, Object> client) {if (client == null) {return null;}String value = (String) client.get("contextId");if (!StringUtils.hasText(value)) {value = (String) client.get("value");}if (!StringUtils.hasText(value)) {value = (String) client.get("name");}if (!StringUtils.hasText(value)) {value = (String) client.get("serviceId");}if (StringUtils.hasText(value)) {return value;}throw new IllegalStateException("Either 'name' or 'value' must be provided in @"+ FeignClient.class.getSimpleName());}

可以看到如果配置了contextId就會(huì)用contextId,如果沒(méi)有配置就會(huì)去value然后是name最后是serviceId。默認(rèn)都沒(méi)有配置,當(dāng)出現(xiàn)一個(gè)服務(wù)有多個(gè)Feign Client的時(shí)候就會(huì)報(bào)錯(cuò)了。

其次的作用是在注冊(cè)FeignClient中,contextId會(huì)作為Client 別名的一部分,如果配置了qualifier優(yōu)先用qualifier作為別名。

private void registerFeignClient(BeanDefinitionRegistry registry,AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {String className = annotationMetadata.getClassName();BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);validate(attributes);definition.addPropertyValue("url", getUrl(attributes));definition.addPropertyValue("path", getPath(attributes));String name = getName(attributes);definition.addPropertyValue("name", name);String contextId = getContextId(attributes);definition.addPropertyValue("contextId", contextId);definition.addPropertyValue("type", className);definition.addPropertyValue("decode404", attributes.get("decode404"));definition.addPropertyValue("fallback", attributes.get("fallback"));definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);// 拼接別名String alias = contextId + "FeignClient";AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();boolean primary = (Boolean) attributes.get("primary"); // has a default, won't be nullbeanDefinition.setPrimary(primary);// 配置了qualifier優(yōu)先用qualifierString qualifier = getQualifier(attributes);if (StringUtils.hasText(qualifier)) {alias = qualifier;}BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,new String[] { alias });BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);}

url

url用于配置指定服務(wù)的地址,相當(dāng)于直接請(qǐng)求這個(gè)服務(wù)。像調(diào)試等場(chǎng)景可以使用。

@FeignClient(name = "order-server", url = "http://localhost:8085")
public interface OrderRemoteClient {@GetMapping("/api/order/detail")public Order detail(@RequestParam("orderId") String orderId);
}

path

path定義當(dāng)前FeignClient訪問(wèn)接口時(shí)的統(tǒng)一前綴。
比如接口地址是/order/detail, 如果你定義了前綴是order, 那么具體方法上的路徑就只需要寫(xiě)/detail即可。

@FeignClient(name = "order-server", url = "http://localhost:8085", path = "/api/order")
public interface OrderRemoteClient {@GetMapping("/detail")public Order detail(@RequestParam("orderId") String orderId);
}

primary

primary對(duì)應(yīng)的是@Primary注解,默認(rèn)為true,官方這樣設(shè)置也是有原因的。當(dāng)我們的Feign實(shí)現(xiàn)了fallback后,也就意味著Feign Client有多個(gè)相同的Bean在Spring容器中,當(dāng)我們?cè)谑褂?#64;Autowired進(jìn)行注入的時(shí)候,不知道注入哪個(gè),所以我們需要設(shè)置一個(gè)優(yōu)先級(jí)高的,@Primary注解就是干這件事情的。

qualifier

qualifier對(duì)應(yīng)的是@Qualifier注解,使用場(chǎng)景跟上面的primary關(guān)系很淡,一般場(chǎng)景直接@Autowired直接注入就可以了。

如果我們的Feign Client有fallback實(shí)現(xiàn),默認(rèn)@FeignClient注解的primary=true, 意味著我們使用@Autowired注入是沒(méi)有問(wèn)題的,會(huì)優(yōu)先注入你的Feign Client。

如果你鬼斧神差的把primary設(shè)置成false了,直接用@Autowired注入的地方就會(huì)報(bào)錯(cuò),不知道要注入哪個(gè)對(duì)象。

解決方案很明顯,你可以將primary設(shè)置成true即可,如果由于某些特殊原因,你必須得去掉primary=true的設(shè)置,這種情況下我們?cè)趺催M(jìn)行注入,我們可以配置一個(gè)qualifier,然后使用@Qualifier注解進(jìn)行注入。
Feign Client 定義

@FeignClient(name = "order-server", path = "/api/order", qualifier="orderRemoteClient")
public interface OrderRemoteClient {@GetMapping("/detail")public Order detail(@RequestParam("orderId") String orderId);
}

Feign Client注入

@Autowired
@Qualifier("orderRemoteClient")
private OrderRemoteClient orderRemoteClient;

configuration

configuration是配置Feign配置類(lèi),在配置類(lèi)中可以自定義Feign的Encoder、Decoder、LogLevel、Contract等。

configuration定義

public class FeignConfiguration {@Beanpublic Logger.Level getLoggerLevel() {return Logger.Level.FULL;}@Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor() {return new BasicAuthRequestInterceptor("user", "password");}@Beanpublic CustomRequestInterceptor customRequestInterceptor() {return new CustomRequestInterceptor();}// Contract,feignDecoder,feignEncoder.....
}

使用示列

@FeignClient(value = "order-server", configuration = FeignConfiguration.class)
public interface OrderRemoteClient {@GetMapping("/api/order/detail")public Order detail(@RequestParam("orderId") String orderId);}

fallback

定義容錯(cuò)的處理類(lèi),也就是回退邏輯,當(dāng)調(diào)用遠(yuǎn)程接口失敗或超時(shí)時(shí),會(huì)調(diào)用對(duì)應(yīng)接口的容錯(cuò)邏輯,fallback指定的類(lèi)必須實(shí)現(xiàn)@FeignClient標(biāo)記的接口,無(wú)法知道熔斷的異常信息。

fallback定義

@Component
public class OrderRemoteClientFallback implements OrderRemoteClient {@Overridepublic Order detail(String orderId) {return new Order("order-998", "默認(rèn)fallback");}}

使用示列

@FeignClient(value = "order-server", fallback = OrderRemoteClientFallback.class)
public interface OrderRemoteClient {@GetMapping("/api/order/detail")public Order detail(@RequestParam("orderId") String orderId);}

fallbackFactory

也是容錯(cuò)的處理,可以知道熔斷的異常信息。工廠類(lèi),用于生成fallback類(lèi)示例,通過(guò)這個(gè)屬性我們可以實(shí)現(xiàn)每個(gè)接口通用的容錯(cuò)邏輯,減少重復(fù)的代碼。

fallbackFactory定義

@Component
public class OrderRemoteClientFallbackFactory implements FallbackFactory<OrderRemoteClient> {private Logger logger = LoggerFactory.getLogger(OrderRemoteClientFallbackFactory.class);@Overridepublic OrderRemoteClient create(Throwable cause) {return new OrderRemoteClient() {@Overridepublic Order detail(String id) {logger.error("OrderRemoteClient.detail 異常", cause);return new Order("order-998", "默認(rèn)");}};}
}

使用示列

@FeignClient(value = "order-server", fallbackFactory = OrderRemoteClientFallbackFactory.class)
public interface OrderRemoteClient {@GetMapping("/order/detail")public Order detail(@RequestParam("orderId") String orderId);}

@FeignClient添加Header信息

在@RequestMapping中添加

@FeignClient(url = "${orderServer_domain:http://order:8082}",value = "order-server",contextId = "OrderServerClient",path = "/api/order")
public interface OrderRemoteClient {@RequestMapping(value="/detail", method = RequestMethod.POST,headers = {"Content-Type=application/json;charset=UTF-8"})Order detail(@RequestParam("orderId") String orderId);
}

使用@RequestHeader注解添加

@FeignClient(url = "${orderServer_domain:http://order:8082}",value = "order-server",contextId = "OrderServerClient",path = "/api/order")
public interface OrderRemoteClient {@RequestMapping(value="/detail", method = RequestMethod.POST)List<String> detail(@RequestHeader Map<String, String> headerMap, @RequestParam("orderId") String orderId);
}

使用@Headers注解添加

@FeignClient(url = "${orderServer_domain:http://order:8082}",value = "order-server",contextId = "OrderServerClient",path = "/api/order")
public interface OrderRemoteClient {@RequestMapping(value="/detail", method = RequestMethod.POST)@Headers({"Content-Type: application/json;charset=UTF-8"})List<String> detail(@RequestHeader Map<String, String> headerMap, @RequestParam("orderId") String orderId);
}

實(shí)現(xiàn)RequestInterceptor接口

@Configuration
public class FeignRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate temp) {temp.header(HttpHeaders.AUTHORIZATION, "XXXXX");}}

FeignClient 源碼

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.cloud.openfeign;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {@AliasFor("name")String value() default "";String contextId() default "";@AliasFor("value")String name() default "";String[] qualifiers() default {};String url() default "";boolean dismiss404() default false;Class<?>[] configuration() default {};Class<?> fallback() default void.class;Class<?> fallbackFactory() default void.class;String path() default "";boolean primary() default true;
}
http://www.risenshineclean.com/news/47307.html

相關(guān)文章:

  • 做網(wǎng)站是不是要學(xué)編程外包公司怎么賺錢(qián)
  • ofbiz做的網(wǎng)站網(wǎng)絡(luò)輿情監(jiān)控
  • 網(wǎng)站備案很麻煩嗎網(wǎng)站模板圖片
  • 有哪些做普洱茶網(wǎng)站的seo關(guān)鍵詞優(yōu)化
  • 招標(biāo)采購(gòu)導(dǎo)航網(wǎng)蘇州吳中區(qū)seo關(guān)鍵詞優(yōu)化排名
  • 兼職做問(wèn)卷調(diào)查的網(wǎng)站個(gè)人網(wǎng)站設(shè)計(jì)內(nèi)容
  • 網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣方法是什么和什么的合理利用百度seo按天計(jì)費(fèi)
  • 做商城網(wǎng)站需要什么超級(jí)外鏈發(fā)布
  • 如今做哪些網(wǎng)站能致富長(zhǎng)沙seo就選智優(yōu)營(yíng)家
  • 網(wǎng)站路徑優(yōu)化怎么做淘寶運(yùn)營(yíng)一般要學(xué)多久
  • 專門(mén)做汽車(chē)動(dòng)力性測(cè)試的網(wǎng)站seo站長(zhǎng)綜合查詢工具
  • 建微網(wǎng)站有什么好處做網(wǎng)站優(yōu)化哪家公司好
  • 大型網(wǎng)站urlseo具體是什么
  • 幫他人做視頻網(wǎng)站違法嗎推薦就業(yè)的培訓(xùn)機(jī)構(gòu)
  • 網(wǎng)站登陸界面怎么做藝人百度指數(shù)排行榜
  • 網(wǎng)站建設(shè)方案標(biāo)準(zhǔn)模板網(wǎng)站流量查詢網(wǎng)站統(tǒng)計(jì)查詢
  • wordpress4.9下載東莞網(wǎng)站建設(shè)優(yōu)化技術(shù)
  • 寶山專業(yè)做網(wǎng)站百度官網(wǎng)平臺(tái)
  • 網(wǎng)站中的冒號(hào)外貿(mào)建站與推廣
  • 泰國(guó)做網(wǎng)站網(wǎng)絡(luò)營(yíng)銷(xiāo)戰(zhàn)略的內(nèi)容
  • 武漢網(wǎng)站開(kāi)發(fā)軟件程序員百度保障中心人工電話
  • 學(xué)做網(wǎng)站 書(shū)陜西seo快速排名
  • 陜西專業(yè)網(wǎng)站建設(shè)公司品牌網(wǎng)站建設(shè)解決方案
  • 做影視網(wǎng)站關(guān)停人民日?qǐng)?bào)最新新聞
  • 建網(wǎng)站免費(fèi)咨詢長(zhǎng)春網(wǎng)站優(yōu)化哪家好
  • 網(wǎng)站開(kāi)發(fā)專業(yè)有哪些營(yíng)銷(xiāo)推廣文案
  • 中企業(yè)網(wǎng)站建設(shè)哪里做網(wǎng)站便宜
  • 楚雄微網(wǎng)站建設(shè)關(guān)鍵詞優(yōu)化分析工具
  • 90設(shè)計(jì)網(wǎng)站怎么樣google廣告投放技巧
  • 如何在手機(jī)上做網(wǎng)站搜索引擎調(diào)價(jià)工具哪個(gè)好