SpringCloud如何創(chuàng)建一個(gè)服務(wù)提供者provider
前幾篇主要集中在注冊(cè)中心eureka的使用上,接下來(lái)可以創(chuàng)建服務(wù)提供者provider來(lái)注冊(cè)到eureka。
demo源碼見(jiàn): https://github.com/Ryan-Miao/spring-cloud-Edgware-demo/tree/master/provider-demo
為了方便版本控制,接下來(lái)的項(xiàng)目都是基于https://github.com/Ryan-Miao/spring-cloud-Edgware-demo 這個(gè)parent配置的。
創(chuàng)建子moudle provider-demo
創(chuàng)建一個(gè)子module,項(xiàng)目名叫provider-demo. 填充springboot和springcloud依賴
<dependencies> <!--springboot 依賴start--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!--springboot 依賴結(jié)束--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> </dependency> <!--工具類 start--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> </dependency> <!--工具類end--> </dependencies>
spring-boot-starter-web
提供web能力,必須spring-boot-starter-actuator
提供項(xiàng)目統(tǒng)計(jì)和基礎(chǔ)的監(jiān)控endpoint, 想要使用spring-boot-admin監(jiān)控就必須添加了 spring-boot-devtools
開(kāi)發(fā)模式 jackson-datatype-jsr310
可以解決Java8新的時(shí)間APILocalDate解體 spring-cloud-starter-eureka
eureka客戶端,負(fù)責(zé)維護(hù)心跳和注冊(cè) swagger
提供Restful契約 lombok
看起來(lái)很清爽的編譯級(jí)別getter setter工具 guava
大而全的Java必備類庫(kù) logstash-logback-encoder
想要收集日志到ELK,使用這個(gè)appender
啟動(dòng)類
@EnableDiscoveryClient @SpringBootApplication public class ProviderDemoApplication { public static void main(String[] args) { SpringApplication.run(ProviderDemoApplication.class, args); } }
@EnableDiscoveryClient
來(lái)啟用服務(wù)注冊(cè)
這個(gè)ProviderDemoApplication應(yīng)該放置于項(xiàng)目包的最外層,因?yàn)锧SpringbootAppliatin包含了@ComponentScan的注解,默認(rèn)掃描本類包下,否則必須手動(dòng)指定scan。
Swagger
swagger就是一個(gè)配置類
@EnableSwagger2 @Configuration public class SwaggerConfiguration { private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("服務(wù)提供者 API") .description("提供用戶信息查詢") .termsOfServiceUrl("") .version("1.0.0") .build(); } /** * 定義api配置. */ @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) .build() .apiInfo(apiInfo()); } }
對(duì)于swagger頁(yè)面的路由,需要我們來(lái)引導(dǎo)下:
創(chuàng)建一個(gè)controller來(lái)導(dǎo)航
@Controller public class HomeController { @GetMapping(value = {"/api", "/"}) public String api() { return "redirect:/swagger-ui.html"; } }
來(lái)一個(gè)Controller 接口
@Api @RestController @RequestMapping("/api/v1/users") public class UserController{ private List<User> users = Lists.newArrayList( new User(1, "譚浩強(qiáng)", 100, LocalDate.now()), new User(2, "嚴(yán)蔚敏", 120, LocalDate.now()), new User(3, "譚浩強(qiáng)", 100, LocalDate.now()), new User(4, "James Gosling", 150, LocalDate.now()), new User(6, "Doug Lea", 150, LocalDate.now()) ); @GetMapping("/") public List<UserVo> list() { return users.stream() .map(u -> new UserVo(u.getId(), u.getName(), u.getAge(), u.getBirth())) .collect(Collectors.toList()); } }
一些簡(jiǎn)單的環(huán)境配置
application.yml
spring: application: name: provider-demo jackson: serialization: WRITE_DATES_AS_TIMESTAMPS: false default-property-inclusion: non_null #服務(wù)過(guò)期時(shí)間配置,超過(guò)這個(gè)時(shí)間沒(méi)有接收到心跳EurekaServer就會(huì)將這個(gè)實(shí)例剔除 #注意,EurekaServer一定要設(shè)置eureka.server.eviction-interval-timer-in-ms否則這個(gè)配置無(wú)效,這個(gè)配置一般為服務(wù)刷新時(shí)間配置的三倍 #默認(rèn)90s eureka.instance.lease-expiration-duration-in-seconds: 15 #服務(wù)刷新時(shí)間配置,每隔這個(gè)時(shí)間會(huì)主動(dòng)心跳一次 #默認(rèn)30s eureka.instance.lease-renewal-interval-in-seconds: 5 server: port: 8082 springfox: documentation: swagger: v2: path: /swagger-resources/api-docs log: path: logs
application-dev.yml
management: security: enabled: false eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ logstash: url: localhost:4560
這里需要提一點(diǎn),由于我集成了logstash, 所以必須安裝好logstash, 見(jiàn)ELK入門使用。 當(dāng)然可以跳過(guò),只要不提供logback.xml的配置就行,把依賴中l(wèi)ogstash移除即可。
Log配置
默認(rèn)采用logback作為日志框架,簡(jiǎn)單配置如下,對(duì)于不想使用logstash的,移除logstash的appender即可。
在resource下新建logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <springProperty scope="context" name="appName" source="spring.application.name" defaultValue="unknown"/> <springProperty scope="context" name="log.path" source="log.path" defaultValue="logs"/> <springProperty scope="context" name="logstashurl" source="logstash.url" defaultValue="localhost:4560"/> <include resource="org/springframework/boot/logging/logback/base.xml"/> <!--輸出到控制臺(tái)--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">LoggingInterceptor <encoder> <pattern>%d{HH:mm:ss.SSS} %X{req.remoteHost} %X{req.requestURI} ${appName} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <!--輸出到文件--> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.path}/${appName}.%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} ${appName} %X{req.remoteHost} %X{req.requestURI} %X{req.userAgent} %X{req.method} - [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <!-- 輸出到logstash--> <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>${logstashurl}</destination> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/> </appender> <springProfile name="dev"> <root level="info"> <appender-ref ref="console"/> <appender-ref ref="file"/> <appender-ref ref="LOGSTASH"/> </root> </springProfile> <springProfile name="test, prod"> <root level="info"> <appender-ref ref="file"/> <appender-ref ref="LOGSTASH"/> </root> </springProfile> </configuration>
啟動(dòng)
確保eureka已啟動(dòng),admin最好也啟動(dòng),方便查看app狀態(tài),ELK的日志系統(tǒng)也最好可以使用。當(dāng)然,只有eureka是剛需。
編譯打包
mvn clean install package spring-boot:repackage
運(yùn)行main方法,指定profile為dev, 可以在idea中編輯運(yùn)行配置,添加參數(shù)
--spring.profiles.active=dev
或者命令行jar啟動(dòng)
啟動(dòng)后,訪問(wèn)eureka
訪問(wèn)admin
訪問(wèn)provider-demo
暴露我們的API給consumer
既然有服務(wù)提供者,必然是為了consumer消費(fèi)。consumer應(yīng)該如何消費(fèi)?手動(dòng)調(diào)用這個(gè)http請(qǐng)求即可。前面提到swagger Restful契約,就是服務(wù)提供者提供請(qǐng)求訪問(wèn)的參數(shù)和要求。consumer如果手動(dòng)去開(kāi)發(fā)這個(gè)client必然耗時(shí),而且容易出錯(cuò)。所以,作為服務(wù)提供者,理應(yīng)提供sdk或者client給consumer來(lái)用。
在spring cloud技術(shù)體系中,遠(yuǎn)程調(diào)用自然是重中之重。目前我找到的具體用法為Feign+Ribbon+Hystrix.
通過(guò)Feign的聲明式接口對(duì)接,實(shí)現(xiàn)了consumer對(duì)provider的調(diào)用。ribbon客戶端負(fù)載均衡,hystrix作健康熔斷。
在這里,我們就首先要提供Feign的接口了。
把controller的api提煉成一個(gè)接口。首先,我們創(chuàng)建一個(gè)新的項(xiàng)目
https://github.com/Ryan-Miao/spring-cloud-Edgware-demo/tree/master/provider-api
將這個(gè)項(xiàng)目放到provider-demo的依賴列表里
<!--內(nèi)部依賴--> <dependency> <groupId>com.test</groupId> <artifactId>provider-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!--內(nèi)部依賴end-->
抽離UserApi接口道provider-api項(xiàng)目中
@RequestMapping("/api/v1/users") public interface UserApi { @GetMapping("/") List<UserVo> list(); }
在provider-demo的controller里改造如下
@Api @RestController public class UserController implements UserApi { private List<User> users = Lists.newArrayList( new User(1, "譚浩強(qiáng)", 100, LocalDate.now()), new User(2, "嚴(yán)蔚敏", 120, LocalDate.now()), new User(3, "譚浩強(qiáng)", 100, LocalDate.now()), new User(4, "James Gosling", 150, LocalDate.now()), new User(6, "Doug Lea", 150, LocalDate.now()) ); @Override public List<UserVo> list() { return users.stream() .map(u -> new UserVo(u.getId(), u.getName(), u.getAge(), u.getBirth())) .collect(Collectors.toList()); } }
這樣,controller沒(méi)有變化,只是被抽離了api路徑。而獨(dú)立出來(lái)的module provider-api就是我們給consumer提供的client。下一節(jié)使用consumer消費(fèi)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java使用list集合remove需要注意的事項(xiàng)(使用示例)
List集合的一個(gè)特點(diǎn)是它其中的元素是有序的,也就是說(shuō)元素的下標(biāo)是根據(jù)插入的順序來(lái)的,在刪除頭部或者中間的一個(gè)元素后,后面的元素下標(biāo)會(huì)往前移動(dòng),本文給大家介紹Java使用list集合remove需要注意的事項(xiàng),感興趣的朋友一起看看吧2022-01-01利用Springboot+Caffeine實(shí)現(xiàn)本地緩存實(shí)例代碼
Caffeine是一個(gè)基于Java8開(kāi)發(fā)的提供了近乎最佳命中率的高性能的緩存庫(kù),下面這篇文章主要給大家介紹了關(guān)于利用Springboot+Caffeine實(shí)現(xiàn)本地緩存的相關(guān)資料,需要的朋友可以參考下2023-01-01Python爬蟲(chóng) 12306搶票開(kāi)源代碼過(guò)程詳解
這篇文章主要介紹了Python爬蟲(chóng) 12306搶票開(kāi)源代碼過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09Python爬蟲(chóng)之爬取2020女團(tuán)選秀數(shù)據(jù)
本文將對(duì)比《青春有你2》和《創(chuàng)造營(yíng)2020》全體小姐姐,鑒于兩個(gè)節(jié)目的數(shù)據(jù)采集和處理過(guò)程基本相似,在使用Python做數(shù)據(jù)爬蟲(chóng)采集的章節(jié)中將只以《創(chuàng)造營(yíng)2020》為例做詳細(xì)介紹。感興趣的同學(xué)可以照貓畫虎去實(shí)操一下《青春有你2》的數(shù)據(jù)爬蟲(chóng)采集,需要的朋友可以參考下2021-04-04SpringCloud實(shí)現(xiàn)基于RabbitMQ消息隊(duì)列的詳細(xì)步驟
在Spring Cloud框架中,我們可以利用RabbitMQ實(shí)現(xiàn)強(qiáng)大而可靠的消息隊(duì)列系統(tǒng),本篇將詳細(xì)介紹如何在Spring Cloud項(xiàng)目中集成RabbitMQ,并創(chuàng)建一個(gè)簡(jiǎn)單的消息隊(duì)列,感興趣的朋友一起看看吧2024-03-03java后端pageHelper分頁(yè)實(shí)現(xiàn)方法步驟
這篇文章主要給大家介紹了關(guān)于java后端pageHelper分頁(yè)實(shí)現(xiàn)方法的相關(guān)資料,在我們的Java項(xiàng)目中分頁(yè)是必不可少的數(shù)據(jù)展示頁(yè)面,文中通過(guò)圖文以及示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07解決spring boot環(huán)境切換失效的問(wèn)題
這篇文章主要介紹了解決spring boot環(huán)境切換失效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09