软件编程
位置:首页>> 软件编程>> java编程>> SpringCloud如何创建一个服务提供者provider

SpringCloud如何创建一个服务提供者provider

作者:Ryan Miao  发布时间:2023-08-01 01:56:33 

标签:SpringCloud,provider,服务

前几篇主要集中在注册中心eureka的使用上,接下来可以创建服务提供者provider来注册到eureka。

demo源码见: https://github.com/Ryan-Miao/spring-cloud-Edgware-demo/tree/master/provider-demo

为了方便版本控制,接下来的项目都是基于https://github.com/Ryan-Miao/spring-cloud-Edgware-demo 这个parent配置的。

创建子moudle provider-demo

创建一个子module,项目名叫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 依赖结束-->

<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 提供项目统计和基础的监控endpoint, 想要使用spring-boot-admin监控就必须添加了 spring-boot-devtools 开发模式 jackson-datatype-jsr310 可以解决Java8新的时间APILocalDate解体 spring-cloud-starter-eureka eureka客户端,负责维护心跳和注册 swagger 提供Restful契约 lombok 看起来很清爽的编译级别getter setter工具 guava 大而全的Java必备类库 logstash-logback-encoder 想要收集日志到ELK,使用这个appender

启动类


@EnableDiscoveryClient
@SpringBootApplication
public class ProviderDemoApplication {

public static void main(String[] args) {
   SpringApplication.run(ProviderDemoApplication.class, args);
 }

}

@EnableDiscoveryClient 来启用服务注册

这个ProviderDemoApplication应该放置于项目包的最外层,因为@SpringbootAppliatin包含了@ComponentScan的注解,默认扫描本类包下,否则必须手动指定scan。

Swagger

swagger就是一个配置类


@EnableSwagger2
@Configuration
public class SwaggerConfiguration {

private ApiInfo apiInfo() {
   return new ApiInfoBuilder()
     .title("服务提供者 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());
 }

}

对于swagger页面的路由,需要我们来引导下:

创建一个controller来导航


@Controller
public class HomeController {
 @GetMapping(value = {"/api", "/"})
 public String api() {
   return "redirect:/swagger-ui.html";
 }

}

来一个Controller 接口


@Api
@RestController
@RequestMapping("/api/v1/users")
public class UserController{

private List<User> users = Lists.newArrayList(
   new User(1, "谭浩强", 100, LocalDate.now()),
   new User(2, "严蔚敏", 120, LocalDate.now()),
   new User(3, "谭浩强", 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());
 }
}

一些简单的环境配置

application.yml


spring:
application:
 name: provider-demo
jackson:
 serialization:
  WRITE_DATES_AS_TIMESTAMPS: false
 default-property-inclusion: non_null

#服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除
#注意,EurekaServer一定要设置eureka.server.eviction-interval-timer-in-ms否则这个配置无效,这个配置一般为服务刷新时间配置的三倍
#默认90s
eureka.instance.lease-expiration-duration-in-seconds: 15
#服务刷新时间配置,每隔这个时间会主动心跳一次
#默认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

这里需要提一点,由于我集成了logstash, 所以必须安装好logstash, 见ELK入门使用。 当然可以跳过,只要不提供logback.xml的配置就行,把依赖中logstash移除即可。

Log配置

默认采用logback作为日志框架,简单配置如下,对于不想使用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"/>
<!--输出到控制台-->
<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>

启动

确保eureka已启动,admin最好也启动,方便查看app状态,ELK的日志系统也最好可以使用。当然,只有eureka是刚需。

编译打包


mvn clean install package spring-boot:repackage

运行main方法,指定profile为dev, 可以在idea中编辑运行配置,添加参数


--spring.profiles.active=dev

或者命令行jar启动

java -Xms256m -Xmx1g -XX:+UseG1GC -jar ./target/provider-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

启动后,访问eureka

SpringCloud如何创建一个服务提供者provider

访问admin

SpringCloud如何创建一个服务提供者provider

访问provider-demo

SpringCloud如何创建一个服务提供者provider 

暴露我们的API给consumer

既然有服务提供者,必然是为了consumer消费。consumer应该如何消费?手动调用这个http请求即可。前面提到swagger Restful契约,就是服务提供者提供请求访问的参数和要求。consumer如果手动去开发这个client必然耗时,而且容易出错。所以,作为服务提供者,理应提供sdk或者client给consumer来用。

在spring cloud技术体系中,远程调用自然是重中之重。目前我找到的具体用法为Feign+Ribbon+Hystrix.

通过Feign的声明式接口对接,实现了consumer对provider的调用。ribbon客户端负载均衡,hystrix作健康熔断。

在这里,我们就首先要提供Feign的接口了。

把controller的api提炼成一个接口。首先,我们创建一个新的项目

https://github.com/Ryan-Miao/spring-cloud-Edgware-demo/tree/master/provider-api

将这个项目放到provider-demo的依赖列表里


<!--内部依赖-->
<dependency>
<groupId>com.test</groupId>
<artifactId>provider-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--内部依赖end-->

抽离UserApi接口道provider-api项目中


@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, "谭浩强", 100, LocalDate.now()),
   new User(2, "严蔚敏", 120, LocalDate.now()),
   new User(3, "谭浩强", 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没有变化,只是被抽离了api路径。而独立出来的module provider-api就是我们给consumer提供的client。下一节使用consumer消费。

来源:http://www.cnblogs.com/woshimrf/p/springcloud-provider.html

0
投稿

猜你喜欢

  • 1. 基本概念的理解`绝对路径`:你应用上的文件或目录在硬盘上真正的路径,如:URL、物理路径例如:c:/xyz/test.txt代表了te
  • 一、获取当前文件的路径1. System.Diagnostics.Process.GetCurrentProcess().MainModul
  • 最近有一款2048的游戏非常火,本文将来介绍一下使用OGEngine游戏引擎开发游戏2048。OGEngine引擎是开源的,我们很容易找到,
  • 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异
  • 一:前言最近老师布置了给多级菜单的作业,感觉蛮有意思的,可以提升自己的逻辑!下面我写个简易版的多级菜单,本人还是菜鸟,欢迎各位给予宝贵的建议
  • 举个例子:我有如下的一个需求,当我想要取得用户信息的时候,会先从本地缓存中查找,找不到然后从分布式缓存中查找,最后找不到再从数据库中查询。但
  • 本文实例讲述了C#操作SQLite方法。分享给大家供大家参考。具体分析如下:地址:System.Data.Sqlite入手。。。首先impo
  •  这将会是一篇比较 * 的文章,当你想在某个人的生活中制造悲剧时你可能会去google搜索它。在Java的世界里,内存溢出仅仅只是你
  • Android的PopupWindow是个很有用的widget,利用它可以实现悬浮窗体的效果,比如实现一个悬浮的菜单,最常见的应用就是在视频
  • 使用@Tolerate实现冲突兼容使用Lombok能够减少程序员的重复工作提高工作效率,而Lombok的注解基本是基于标准的(如,标准的Bu
  • 背景何为延迟队列?顾名思义,延迟队列就是进入该队列的消息会被延迟消费的队列。而一般的队列,消息一旦入队了之后就会被消费者马上消费。场景一:在
  • 本文实例分析了C#中var关键字用法。分享给大家供大家参考。具体方法如下:C#关键字是伴随着.NET 3.5以后,伴随着匿名函数、LINQ而
  • 今天新建一个springboot项目时,项目建好后,在IDEA下载依赖包时,下载了很久都没有下载完,后来仔细一看,是下载不了。解决方法:在项
  • 本文实例为大家分享了C#实现串口示波器的具体代码,供大家参考,具体内容如下开发工具visual studio2019C#串口示波器,实时刷新
  • 一个线程的生命周期:新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态
  • Java Memory Model简称JMM, 是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见性、是否可以重排序等问题的无
  • 为什么要自定义缓存注解?Spring Cache本身提供@Cacheable、@CacheEvict、@CachePut等缓存注解,为什么还
  • Java实现简单的类似QQ聊天工具,供大家参考,具体内容如下所使用到的知识点:java socket编程之TCP协议java Swing简单
  • list.remove最近做项目的过程中,需要用到list.remove()方法,结果发现两个有趣的坑,经过分析后找到原因,记录一下跟大家分
  • 方法一,修改gradle.properties文件,增加一句gradle.user.home=D\:\\Android\\.gradle但这
手机版 软件编程 asp之家 www.aspxhome.com