RestTemplate 是通過攔截器改變請求的URI的方式來指定服務器的,此處將通過一個自定義LoadBalanced的方式來進行說明
1.導入jar包
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
2.自定義 MyLoadBalanced 注解
import org.springframework.beans.factory.annotation.Qualifier; import java.lang.annotation.*; @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface MyLoadBalanced { }
3.編寫配置類
import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; import java.util.Collections; import java.util.List; @Configuration public class MyConfig { @Autowired(required = false) @MyLoadBalanced private List<RestTemplate> tpls = Collections.emptyList(); @Bean public SmartInitializingSingleton lbInitializing() { return new SmartInitializingSingleton() { @Override public void afterSingletonsInstantiated() { System.out.println("tpls 的數量:"+tpls.size()); for (RestTemplate tpl : tpls) { List<ClientHttpRequestInterceptor> interceptors = tpl.getInterceptors(); interceptors.add(new MyInterceptor()); tpl.setInterceptors(interceptors); } } }; } }
4.編寫Controller測試接口 (訪問 /getUser 可以發現執行的是自定義的 MyLoadBalanced 此處應該會報錯,因為地址不存在,不過我們主要是為了測試是否會執行 MyLoadBalanced)
import com.idelan.ribbon.config.MyLoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @Configuration public class MyController { @Bean @MyLoadBalanced public RestTemplate tplA() { return new RestTemplate(); } @GetMapping(value = "/getUser") public String getUser() { RestTemplate restTemplate = tplA(); String json = restTemplate.getForObject("http://smart-platform-base/platform/base/getUser", String.class); return json; } @GetMapping(value = "/hello") public String hello() { return "hello world"; } }
5.自定義攔截器來更改接口的訪問地址 (@LoadBalanced 此處的邏輯會別我們復雜很多,我們只是簡單模擬一下)
(1)自定義 Request 類
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; import java.net.URI; import java.net.URISyntaxException; public class MyRequest implements HttpRequest { HttpRequest httpRequest; public MyRequest(HttpRequest httpRequest) { this.httpRequest = httpRequest; } @Override public HttpMethod getMethod() { return httpRequest.getMethod(); } @Override public String getMethodValue() { return httpRequest.getMethodValue(); } @Override public URI getURI() { try { URI newUri = new URI("http://localhost:8080/hello"); return newUri; } catch (URISyntaxException e) { e.printStackTrace(); } return httpRequest.getURI(); } @Override public HttpHeaders getHeaders() { return httpRequest.getHeaders(); } }
(2)自定義攔截器
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 MyInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException { System.out.println("~~~~~~~~自定義攔截器,uri:"+httpRequest.getURI()); System.out.println("舊的uri:"+httpRequest.getURI()); HttpRequest newRequest = new MyRequest(httpRequest); System.out.println("新的uri:"+newRequest.getURI()); return clientHttpRequestExecution.execute(newRequest, bytes); } }
測試:可以通過訪問 /getUser 接口來測試,最終會返回 /hello 接口的內容,因為我們更改了訪問地址