eureka注冊中心和restTemplate的使用說明
eureka的作用
-
消費(fèi)者該如何獲取服務(wù)提供者的具體信息
1.服務(wù)者啟動時(shí)向eureka注冊自己的信息
2.eureka保存這些信息
3.消費(fèi)者根據(jù)服務(wù)名稱向eureka拉去提供者的信息
-
如果有多個(gè)服務(wù)提供者,消費(fèi)者該如何選擇?
服務(wù)消費(fèi)者利用負(fù)載均衡算法,從服務(wù)列表中挑選一個(gè)
-
消費(fèi)者如何感知服務(wù)提供者的健康狀態(tài)?
服務(wù)提供者每隔30s向eurekaserver發(fā)送心跳請求,報(bào)告健康狀態(tài)。
eureka會更新記錄服務(wù)列表信息,心跳不正常會被剔除。
消費(fèi)者就可以拉取到最新的消息。
搭載eureka注冊中心
1.引入依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
2.在啟動類加@EnableEurekaServer注解
3.編寫配置文件
server:
port: 10086 #端口
spring:
application:
name: eurekaserver #應(yīng)用名
eureka:
client:
service-url: #eureka注冊中心地址
defaultZone: http://localhost:10086/eureka
服務(wù)注冊
1.加入eureka客服端的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.添加客服端的配置
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
服務(wù)發(fā)現(xiàn)
1.修改url訪問路徑,用服務(wù)名代替ip地址
package cn.itcast.order.web;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import cn.itcast.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private RestTemplate restTemplate;
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
// 根據(jù)id查詢訂單并返回
Order order = orderService.queryOrderById(orderId);
String url="http://userserver/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);
order.setUser(user);
return order;
}
}
2.加負(fù)載均衡的注解
package cn.itcast.order;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
/* @Bean
public IRule randomRule(){
return new RandomRule();
}*/
}
負(fù)載均衡
1.通過定義IRule實(shí)現(xiàn)可以修改負(fù)載均衡的規(guī)則
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
@Bean
public IRule randomRule(){
return new RandomRule();
}
2.通過配置文件更改負(fù)載均衡規(guī)則
userservice: # 給某個(gè)微服務(wù)配置負(fù)載均衡規(guī)則,這里是userservice服務(wù)
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 負(fù)載均衡規(guī)則
RestTemplate接口調(diào)用
簡介
在項(xiàng)目中,當(dāng)我們需要遠(yuǎn)程調(diào)用一個(gè) HTTP 接口時(shí),我們經(jīng)常會用到 RestTemplate 這個(gè)類。這個(gè)類是 Spring 框架提供的一個(gè)工具類。
RestTemplate
: The original Spring REST client with a synchronous, template method API.
從上面的介紹中我們可以知道:RestTemplate 是一個(gè)同步的 Rest API 客戶端。下面我們就來介紹下 RestTemplate 的常用功能。
RestTemplate的使用
1.創(chuàng)建 RestTemplate
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
return restTemplate;
}
/**
* 創(chuàng)建 RestTemplate 時(shí)需要一個(gè) ClientHttpRequestFactory,
* 通過這個(gè)請求工廠,我們可以統(tǒng)一設(shè)置請求的超時(shí)時(shí)間,設(shè)置代理以及一些其他細(xì)節(jié)。
* 通過上面代碼配置后,我們直接在代碼中注入 RestTemplate 就可以使用了。
* @return
*/
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);
factory.setConnectTimeout(15000);
// 設(shè)置代理
//factory.setProxy(null);
return factory;
}
2.方法介紹
getForObject
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
- 參數(shù)1:http請求路徑
- 參數(shù)2:返回值類型
- 參數(shù)3:url參數(shù) 傳參數(shù)的方式不一樣而已,本質(zhì)是一樣的
@Resource
private RestTemplate restTemplate;
@Test
void testGetRequestForShopById() {
String url="http://127.0.0.1:8081/shop/{id}";
Result result = restTemplate.getForObject(url, Result.class, 1);
System.out.println(result);
}
# 響應(yīng)結(jié)果
Result(success=true, errorMsg=null, data={id=1, name=103茶餐廳, typeId=1, images=https://qcloud.dpfile.com/pc/jiclIsCKmOI2arxKN1Uf0Hx3PucIJH8q0QSz-Z8llzcN56-_QiKuOvyio1OOxsRtFoXqu0G3iT2T27qat3WhLVEuLYk00OmSS1IdNpm8K8sG4JN9RIm2mTKcbLtc2o2vfCF2ubeXzk49OsGrXt_KYDCngOyCwZK-s3fqawWswzk.jpg,https://qcloud.dpfile.com/pc/IOf6VX3qaBgFXFVgp75w-KKJmWZjFc8GXDU8g9bQC6YGCpAmG00QbfT4vCCBj7njuzFvxlbkWx5uwqY2qcjixFEuLYk00OmSS1IdNpm8K8sG4JN9RIm2mTKcbLtc2o2vmIU_8ZGOT1OjpJmLxG6urQ.jpg, area=大關(guān), address=金華路錦昌文華苑29號, x=120.149192, y=30.316078, avgPrice=80, sold=4215, comments=3035, score=37, openHours=10:00-22:00, createTime=2021-12-22T18:10:39, updateTime=2023-04-06T22:18:52}, total=null)
getForEntity
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType)
/**
* 這個(gè)方法比getforobject多了一層包裝??梢垣@取更多的響應(yīng)信息
*/
@Test
void testGetRequestForShopById_getForEntity() {
String url="http://127.0.0.1:8081/shop/{id}";
ResponseEntity<Result> response = restTemplate.getForEntity(url, Result.class,1);
Result body = response.getBody();
System.out.println(body);
}
響應(yīng)結(jié)果
Result(success=true, errorMsg=null, data={id=1, name=103茶餐廳, typeId=1, images=https://qcloud.dpfile.com/pc/jiclIsCKmOI2arxKN1Uf0Hx3PucIJH8q0QSz-Z8llzcN56-_QiKuOvyio1OOxsRtFoXqu0G3iT2T27qat3WhLVEuLYk00OmSS1IdNpm8K8sG4JN9RIm2mTKcbLtc2o2vfCF2ubeXzk49OsGrXt_KYDCngOyCwZK-s3fqawWswzk.jpg,https://qcloud.dpfile.com/pc/IOf6VX3qaBgFXFVgp75w-KKJmWZjFc8GXDU8g9bQC6YGCpAmG00QbfT4vCCBj7njuzFvxlbkWx5uwqY2qcjixFEuLYk00OmSS1IdNpm8K8sG4JN9RIm2mTKcbLtc2o2vmIU_8ZGOT1OjpJmLxG6urQ.jpg, area=大關(guān), address=金華路錦昌文華苑29號, x=120.149192, y=30.316078, avgPrice=80, sold=4215, comments=3035, score=37, openHours=10:00-22:00, createTime=2021-12-22T18:10:39, updateTime=2023-04-06T22:18:52}, total=null)
head請求用的很少見。
Head 與服務(wù)器索與get請求一致的相應(yīng),響應(yīng)體不會返回,獲取包含在小消息頭中的原信息(與get請求類似,返回的響應(yīng)中沒有具體內(nèi)容,用于獲取報(bào)頭)
HEAD和GET本質(zhì)是一樣的,區(qū)別在于HEAD不含有呈現(xiàn)數(shù)據(jù),而僅僅是HTTP頭信息。有的人可能覺得這個(gè)方法沒什么用,其實(shí)不是這樣的。想象一個(gè)業(yè)務(wù)情景:欲判斷某個(gè)資源是否存在,我們通常使用GET,但這里用HEAD則意義更加明確。
public HttpHeaders headForHeaders(String url, Object... uriVariables)
public HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables)
public HttpHeaders headForHeaders(URI url)
@Test
void headForHeaders() throws URISyntaxException {
String url="http://127.0.0.1:8081/shop-type/list";
URI uri = new URI(url);
HttpHeaders headers = restTemplate.headForHeaders(uri);
System.out.println(headers.toString());
}
head請求的響應(yīng)
[Content-Type:"application/json", Content-Length:"652", Date:"Wed, 19 Apr 2023 09:49:28 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]
在之后的內(nèi)容之前我們先看看restTemplate的攔截器設(shè)置,主要設(shè)置請求頭或者一些權(quán)限認(rèn)證的需要
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
public class MyRestTemplateInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
HttpHeaders headers = request.getHeaders();
//設(shè)置請求頭 做權(quán)限認(rèn)證
headers.set("authorization","50da33fa5c0a4ccea49a08bcdf3ee757");
return execution.execute(request,body);
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
RestTemplate restTemplate = new RestTemplate(factory);
MyRestTemplateInterceptor restTemplateInterceptor = new MyRestTemplateInterceptor();
List<ClientHttpRequestInterceptor> list=new ArrayList<>(1);
list.add(restTemplateInterceptor);
restTemplate.setInterceptors(list);
return restTemplate;
}
/*@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
return new RestTemplate(factory);
}*/
/**
* 創(chuàng)建 RestTemplate 時(shí)需要一個(gè) ClientHttpRequestFactory,
* 通過這個(gè)請求工廠,我們可以統(tǒng)一設(shè)置請求的超時(shí)時(shí)間,設(shè)置代理以及一些其他細(xì)節(jié)。
* 通過上面代碼配置后,我們直接在代碼中注入 RestTemplate 就可以使用了。
* @return
*/
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//設(shè)置超時(shí)的時(shí)間
factory.setConnectTimeout(10000);
//客戶端從服務(wù)端讀取數(shù)據(jù)的超時(shí)時(shí)間
factory.setReadTimeout(10000);
// 設(shè)置代理
//factory.setProxy(null);
return factory;
}
}
postForLocation方法
public URI postForLocation(String url, @Nullable Object request, Object... uriVariables)
public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)
/**
*不做過多的介紹了
* 主要是與上面的也大差不差。
*/
最后我們看restTemplate中最豐富的一個(gè)方法。不用配置攔截器也能實(shí)現(xiàn)設(shè)置請求頭。
exchange這個(gè)方法的重載也不少
public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
@Nullable HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
@Nullable HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables)
-
參數(shù)一:url 請求路徑
-
參數(shù)二:method 請求方式
-
參數(shù)三:requestEntity
這個(gè)可以設(shè)置請求體和請求頭,我們看一下這個(gè)類的構(gòu)造器,我挑了一個(gè)參數(shù)最多的構(gòu)造器。
很明顯第一個(gè)參數(shù)就是請求體,第二個(gè)參數(shù)就是設(shè)置請求頭的一個(gè)map。
也就是說我們不用設(shè)置攔截器就可以實(shí)現(xiàn)復(fù)雜的http請求
public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers) { this.body = body; HttpHeaders tempHeaders = new HttpHeaders(); if (headers != null) { tempHeaders.putAll(headers); } this.headers = HttpHeaders.readOnlyHttpHeaders(tempHeaders); }
-
參數(shù)四:responseType 響應(yīng)值類型
-
參數(shù)五:url參數(shù) 也可以理解為請求行參數(shù)。
底下是一個(gè)實(shí)列。文章來源:http://www.zghlxwxcb.cn/news/detail-429348.html
/**
* get請求設(shè)置請求頭!
* 設(shè)置url參數(shù)
*/
@Test
void testGetRequestForShop() {
long shopId = 1l;
/**
* authorization: ba8d06d954a04c32bc1e75e2625fe192
*/
String url="http://127.0.0.1:8081/shop/{id}";
HttpHeaders httpHeaders=new HttpHeaders();
httpHeaders.add("authorization","ba8d06d954a04c32bc1e75e2625fe192");
HttpEntity httpEntity=new HttpEntity(httpHeaders);
ResponseEntity<Result> result = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Result.class, shopId);
System.out.println(result.getStatusCode());
System.out.println("============header==============");
System.out.println(result.getHeaders());
System.out.println("=============result==============");
Object data = result.getBody().getData();
System.out.println(data);
}
Entity=new HttpEntity(httpHeaders);文章來源地址http://www.zghlxwxcb.cn/news/detail-429348.html
ResponseEntity<Result> result = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Result.class, shopId);
System.out.println(result.getStatusCode());
System.out.println("============header==============");
System.out.println(result.getHeaders());
System.out.println("=============result==============");
Object data = result.getBody().getData();
System.out.println(data);
}
到了這里,關(guān)于eureka注冊中心和RestTemplate的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!