HTTP Interface —— Spring越来越关心你怎么写代码了

spring 6.0新特性

前段时间就一直听别人在说这个HTTP Interface了,说是spring 6.0新特性。只是自己一直没去了解具体情况。最近抽空把这个介绍看了。
Spring 允许你将HTTP服务定义为带有HTTP exchanges注解方法的Java接口。然后,你可以生成一个实现接口的代理执行HTTP请求。这有助于简化HTTP远程访问,通常涉及封装底层HTTP客户机使用细节的外观。

spring 很关心你怎么写代码

关于HTTP Interface的介绍,我是这么理解的:
在这之前,我们调用远程数据可能是在一个service里获取HTTPClient 比如在这里使用的WebClient,然后定义请求体,发送请求,获得数据后再进行业务操作。
定义了HTTP Interface之后,我们只要定义接口就行了,把它当成我们业务中的一个service,其他service怎么用,这个service就怎么用。至于HTTPClient是怎么样的,在使用之前就已经定义好了,这使我们在编码时可以更注重业务逻辑。

文档demo

interface RepositoryService {

    @GetExchange("/repos/{owner}/{repo}")
    Repository getRepository(@PathVariable String owner, @PathVariable String repo);

    // more HTTP exchange methods...

}
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();

RepositoryService service = factory.createClient(RepositoryService.class);
@HttpExchange(url = "/repos/{owner}/{repo}", accept = "application/vnd.github.v3+json")
interface RepositoryService {

    @GetExchange
    Repository getRepository(@PathVariable String owner, @PathVariable String repo);

    @PatchExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    void updateRepository(@PathVariable String owner, @PathVariable String repo,
            @RequestParam String name, @RequestParam String description, @RequestParam String homepage);

}

以上demo来自官方文档,让我来的话,就是生成代理那边,就直接注册bean了。然后就在其他的地方直接@Autowired

个人demo

以下是我自己使用时写的demo。此时我的本地启着2个应用,有一个应用需要调用另一个应用。先来定义一个service

@HttpExchange(url = "/goods")
public interface RemoteHttpService {
    @GetExchange(url = "/{id}")
    String get(@PathVariable String id);

    @PutExchange(url = "/")
    String put(@RequestBody String json);

    @PostExchange(url = "/")
    String post(@RequestBody String json);

    @DeleteExchange(url = "{id}")
    String delete(@PathVariable String id);
}

CRUD都有了,只要调用就行了。但是这个只是接口啊,没有实现呢,接下来生成HTTPClient代理的实现,并注册到bean。

@Configuration
public class WebClientConfig {
    @Bean
    public RemoteHttpService remoteHttpService(){
        WebClient webClient = WebClient.builder().baseUrl("localhost").build();
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)).build();
        return factory.createClient(RemoteHttpService.class);
    }
}

建议一个主机写一个Client吧,这边为了demo的演示效果,一个模块做了一个Client,毕竟访问一个主机的设置一般来说都是一样的吧。

其实我们可以看到形式上,这个接口类跟我们使用了@Service的方法差不多。但在写法上更像是写了个@Controller。最后再整个活,通过扫包注册远程调用的bean

@Configuration
public class WebClientConfig implements BeanFactoryPostProcessor {

    private MetadataReaderFactory metadataReaderFactory;

    private ResourcePatternResolver resourcePatternResolver;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        WebClient webClient = WebClient.builder().build();
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)).build();
        try {
            Resource[] resources = getResourcePatternResolver().getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "org/example/service/**");
            for (Resource resource: resources){
                String filename = resource.getFilename();
                MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                if (metadataReader.getAnnotationMetadata().hasAnnotation(HttpExchange.class.getName())) {
                    assert filename != null;
                    beanFactory.registerSingleton(filename.substring(0,filename.lastIndexOf(".")), factory.createClient(Class.forName(metadataReader.getClassMetadata().getClassName())));
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    private ResourcePatternResolver getResourcePatternResolver() {
        if (this.resourcePatternResolver == null) {
            this.resourcePatternResolver = new PathMatchingResourcePatternResolver();
        }
        return this.resourcePatternResolver;
    }

    public final MetadataReaderFactory getMetadataReaderFactory() {
        if (this.metadataReaderFactory == null) {
            this.metadataReaderFactory = new CachingMetadataReaderFactory();
        }
        return this.metadataReaderFactory;
    }
}
# HttpInterface Windows上C++封装的HTTP库,包含三种实现模式(WinInet、WinHttp、socket) 主要实现了HTTP的get\post方法,下载到内存、下载到本地文件,回调下载进度等接口 测试程序中展现了常用的几个方法。 接口类声明: class IHttpBase { public: virtual void SetDownloadCallback(IHttpCallback* pCallback, void* pParam)= 0; virtual bool DownloadFile(LPCWSTR lpUrl, LPCWSTR lpFilePath)= 0; virtual bool DownloadToMem(LPCWSTR lpUrl, OUT void** ppBuffer, OUT int* nSize)= 0; virtual void FreeInstance()= 0; virtual HttpInterfaceError GetErrorCode()= 0; }; //////////////////////////////////////////////////////////////////////////////////// //HTTP请求接口类 class IWininetHttp :public IHttpBase { public: //HTTP请求功能 virtual string Request(LPCSTR lpUrl, HttpRequest type, LPCSTR lpPostData = NULL, LPCSTR lpHeader = NULL)= 0; virtual string Request(LPCWSTR lpUrl, HttpRequest type, LPCSTR lpPostData = NULL, LPCWSTR lpHeader = NULL)= 0; }; /////////////////////////////////////////////////////////////////////////////////////// //HTTP socket类 class ISocketHttp :public IHttpBase { public: virtual LPCWSTR GetIpAddr()const= 0; }; /////////////////////////////////////////////////////////////////////////////////////// //WinHttp类 class IWinHttp : public IWininetHttp { public: //设置超时时间,单位:毫秒 virtual void SetTimeOut(int dwConnectTime, int dwSendTime, int dwRecvTime)= 0; }; 能力有限,有bug欢迎指正 email:jelinyao@163.com
Spring Cloud 是一个基于 Spring Boot 的微服务架构开发工具,可以快速搭建分布式系统的基础设施,提供了大量的开箱即用的组件,比如服务发现、配置中心、负载均衡、断路器等。 下面是一个简单的 Spring Cloud 代码示例: 1. 在 pom.xml 中引入相关依赖: ```xml <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> </dependencies> ``` 2. 在启动类上添加注解 @EnableEurekaServer 和 @EnableConfigServer,开启 Eureka 和 Config Server 功能: ```java @SpringBootApplication @EnableEurekaServer @EnableConfigServer public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 3. 在 application.properties 中配置 Eureka 和 Config Server: ```properties # Eureka 配置 spring.application.name=eureka-server server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false # Config Server 配置 spring.cloud.config.server.git.uri=https://github.com/my-org/config-repo spring.cloud.config.server.git.username=my-username spring.cloud.config.server.git.password=my-password spring.cloud.config.server.git.clone-on-start=true ``` 4. 创建一个 RESTful API,通过 Feign 调用其他微服务: ```java @RestController public class MyController { @Autowired private MyFeignClient myFeignClient; @GetMapping("/hello") public String hello() { return myFeignClient.hello(); } } @FeignClient("my-service") interface MyFeignClient { @GetMapping("/hello") String hello(); } ``` 以上是一个简单的 Spring Cloud 代码示例,实际项目中还需根据业务需求添加其他组件和功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值