Springcloud Eureka详解
Eureka Server 详解
-
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> -
配置文件
spring: application: name: springcloud-demo-eureka-server eureka: client: # server端也是一个客户端,需要注册到服务端,需要配置服务端的地址 service-url: defaultZone: http://localhost:8762/eureka/ # 是否需要将该服务注册到服务端,自己就是服务端,不用注册自己 register-with-eureka: false # 是否同步其他server的注册信息,当有多个Eureka Server端时,需要同步信息 fetch-registry: false # 关掉自我保护,由于服务上线率低,会有警告提示,会认为该服务是在线的,即使该服务已经掉线了。 server: enable-self-preservation: false server: port: 8762 -
启动类配置注解@EnableEurekaServer
@SpringBootApplication @EnableEurekaServer public class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } } -
访问地址http://localhost:8762,可以看到界面
Euraka Client详解
-
pom依赖
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>-
作为eureka 客户端,依赖spring-cloud-starter-netflix-eureka-client
-
对外要提供服务,所以要提供spring-boot-starter-web(没有就会报错,无法启动,204)
2020-04-14 11:30:28.271 INFO 33156 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091 - registration status: 204 2020-04-14 11:30:28.272 INFO 33156 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091: registering service... 2020-04-14 11:30:28.277 INFO 33156 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091 - registration status: 204 2020-04-14 11:30:28.277 INFO 33156 --- [extShutdownHook] com.netflix.discovery.DiscoveryClient : Unregistering ... 2020-04-14 11:30:28.283 INFO 33156 --- [extShutdownHook] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091 - deregister status: 200 -
-
配置文件
spring: application: name: springcloud-demo-provier server: port: 8091 eureka: client: # eureka服务端的地址 service-url: defaultZone: http://localhost:8762/eureka -
启动类配置注解@EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
- 访问地址http://localhost:8762
可以看到用该服务已经注册到eureka服务端
服务间通信
Feign
提供者
-
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> -
服务对外暴露接口信息
@FeignClient(value = "springcloud-demo-provier") public interface ProviderApiClient { @GetMapping("/provider/info") String info(@RequestParam("msg") String msg); @PostMapping("/provider/userinfo") String userInfo(@RequestBody User user); }其他服务通过注入ProviderApiClient类,调用info方法,从而间接调用对应的接口。
注意:
- @FeignClient value值是该服务的名称
- 参数需要用注解标明,@RequestParam/@PathVariable/@RequestHeader等来构造http请求。
-
接口
@RestController @RequestMapping("/provider") public class ProviderController { @GetMapping("/info") public String info(@RequestParam("msg") String msg) { return "springcloud-demo-provider info ----- " + msg; } @PostMapping("/userinfo") public String userInfo(@RequestBody User user) { return user.toString(); } }
消费者
-
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>com.wc</groupId> <artifactId>springcloud-demo-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency>依赖openFeign还要依赖FeignClient所在服务的jar.
-
启动类需要标注@EnableFeignClients(basePackages = {"com.wc.api"}),basePackages的值是@FeignClient注解的类所在的包名
-
接口
@RestController @RequestMapping("/consumer") public class ConsumerController { @Autowired private ProviderApiClient providerApiClient; @GetMapping("/info") public String info(@RequestParam("msg") String msg) { System.out.println("ConsumerController msg: " + msg); return providerApiClient.info(msg); } @PostMapping("/userinfo") public String userInfo(@RequestBody User user) { return providerApiClient.userInfo(user); } }注入服务提供者的接口,调用方法。
参考链接:
RestTemplate
-
配置restTemplate,@LoadBalanced注解是从Ribbon负载均衡器,从所有的目标服务中按照自己配置的规则找到对应的服务。
@Component public class RestTemplateConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } } -
get请求调用
@RestController @RequestMapping("/consumer") public class ConsumerController { @Autowired private RestTemplate restTemplate; private static final String URL = "http://SPRINGCLOUD-DEMO-PROVIER"; @GetMapping("/restinfo") public String restInfo(@RequestParam("msg") String msg) { String url = String.format(URL + "/provider/info?msg=%s", msg); return restTemplate.getForObject(url, String.class); } @GetMapping("/restinfo/{id}") public String restInfo(@PathVariable("id" Integer id)) { return restTemplate.getForObject(URL + "/provider/info/{id}", String.class, id); } }如果传参值在请求路径中,调用这个方法,后面的参数是请求路径中的参数
T getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException;
-
post请求
如果是请求体传参,直接透传,提供者接口也是使用@RequestBody接收
@PostMapping("/rest-userinfo2") public String restUserInfo2(@RequestBody User user) { return restTemplate.postForObject(URL + "/provider/userinfo", user, String.class); }如果是表单传参,稍微复杂一点,需要设置content-type。
public String restUserInfo1(User user) { HttpHeaders headers = new HttpHeaders(); // 请勿轻易改变此提交方式,大部分的情况下,提交方式都是表单提交 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 封装参数,千万不要替换为Map与HashMap,否则参数无法传递 MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>(); // 也支持中文 params.add("name", user.getName()); params.add("age", user.getAge().toString()); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers); // 执行HTTP请求 return restTemplate.postForObject(URL + "/provider/userinfo", requestEntity, String.class); }自定义MessageConverter,继承MappingJackson2HttpMessageConverter
public class MyMessageConverter extends MappingJackson2HttpMessageConverter { public MyMessageConverter() { List<MediaType> list = new ArrayList<>(); list.add(MediaType.TEXT_PLAIN); list.add(MediaType.TEXT_HTML); setSupportedMediaTypes(list); } }@Bean @LoadBalanced public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new MyMessageConverter()); return restTemplate; }RestTemplate中的方法详细参考: