当前位置: 首页 > 后端技术 > Java

还在使用HttpUtil吗?SpringBoot3.0新HTTP客户端工具来了,够优雅好用!

时间:2023-04-01 16:04:23 Java

我们平时开发项目的时候,经常需要远程调用其他服务提供的接口,所以会用到一些HTTP工具,比如Hutool提供的HttpUtil。不久前,SpringBoot3.0发布了,HttpInterface的一个新特性发布了,它允许我们使用声明式服务调用来调用远程接口。今天我们就来说说它的用途吧!SpringBoot实战电商项目商城(50k+star)地址:https://github.com/macrozheng/mall简介Http接口允许你像Java接口一样定义HTTP服务,用法和你的方法完全一样通常写在Controller中。它会自动为这些HTTP服务接口生成代理实现类,底层是基于Webflux的WebClient实现的。使用声明式服务调用确实很优雅。下面是一段使用HttpInterface声明的Http服务代码。在SpringBoot3.0中使用HttpInterface非常简单,下面就来体验一下。依赖集成首先在项目的pom.xml中定义SpringBoot的版本为3.0.0;org.springframework.bootspring-boot-starter-parent3.0.0由于SpringBoot最低要求是Java17,所以我们需要先安装JDK17,安装后配置工程SDK版本为Java17,JDK下载地址:https://www.oracle。com/cn/jav...由于HttpInterface需要依赖webflux来实现,所以我们需要添加它的依赖。org.springframework.bootspring-boot-starter-webflux基本使用下面是mall-tiny-swagger中调用接口的例子.下面来体验一下HttpInterface的基本使用。首先,我们准备一个服务,方便远程调用。我们使用之前的mall-tiny-swaggerDemo。打开Swagger可以看到有一个登录界面和一个需要登录认证的产品品牌CRUD界面。项目地址:https://github.com/macrozheng...首先在application.yml中配置mall-tiny-swagger的服务地址;remote:baseUrl:http://localhost:8088/然后通过@HttpExchange声明一个Http服务,使用@PostExchange注解表示一个POST请求;/***@authermacrozheng*@description定义调用远程UmsAdmin服务的Http接口*@date2022/1/19*@githubhttps://github.com/macrozheng*/@HttpExchangepublicinterfaceUmsAdminApi{@PostExchange("admin/login")CommonResultlogin(@RequestParam("username")Stringusername,@RequestParam("password")Stringpassword);}再创建一个接口远程调用品牌服务,参数注解可以使用我们通常用于编写Controller方法;/***@authermacrozheng*@description定义调用远程PmsBrand服务的Http接口*@date2022/1/19*@githubhttps://github.com/macrozheng*/@HttpExchangepublicinterfacePmsBrandApi{@GetExchange("品牌/列表")CommonResult>列表(@RequestParam("pageNum")整数pageNum,@RequestParam("pageSize")整数pageSize);@GetExchange("brand/{id}")CommonResultdetail(@PathVariable("id")Longid);@PostExchange("brand/create")CommonResultcreate(@RequestBodyPmsBrandpmsBrand);@PostExchange("brand/update/{id}")CommonResultupdate(@PathVariable("id")长id,@RequestBodyPmsBrandpmsBrand);@GetExchange("brand/delete/{id}")CommonResultdelete(@PathVariable("id")Longid);}为了方便后续调用需要登录认证的接口,我创建了TokenHolder类,将token存放在Session中;/***@authermacrozheng*@description登录令牌存储(在会话中)*@date2022/1/19*@githubhttps://github.com/macrozheng*/@ComponentpublicclassTokenHolder{/***添加令牌*/publicvoidputToken(Stringtoken){RequestAttributesra=RequestContextHolder.getRequestAttributes();HttpServletRequest请求=((ServletRequestestAttributes)ra).getRequest();request.getSession().setAttribute("token",token);}/***获取令牌*/publicStringgetToken(){RequestAttributesra=RequestContextHolder.getRequestAttributes();HttpServletRequest请求=((ServletRequestAttributes)ra).getRequest();对象令牌=request.getSession().getAttribute("token");如果(令牌!=空){返回(字符串)令牌;}返回空值;}}创建JavaConfiguration,只需配置请求使用的客户端WebClient和Http服务对象即可。由于品牌服务需要添加认证头才能正常访问,所以使用过滤器统一添加;@ConfigurationpublicclassHttpInterfaceConfig{@Value("${remote.baseUrl}")privateStringbaseUrl;@AutowiredprivateTokenHoldertokenHolder;@BeanWebClientwebClient(){returnWebClient.builder()//添加全局默认请求header.defaultHeader("source","http-interface")//给Request添加过滤器和添加自定义认证header.filter((request,next)->{ClientRequestfiltered=ClientRequest.from(request).header("Authorization",tokenHolder.getToken()).build();returnnext.exchange(filtered);}).baseUrl(baseUrl).build();}@BeanUmsAdminApiumsAdminApi(WebClient客户端){HttpServiceProxyFactoryfactory=HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();返回factory.createClient(UmsAdminApi.class);}@ApianPmspmsBrandApi(WebClientclient){HttpServiceProxyFactoryfactory=HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();返回factory.createClient(PmsBrandApi.class);接下来在Controller中注入Http服务对象,然后调用Just;/***@authermacrozheng*@descriptionHttpInterface测试接口*@date2022/1/19*@githubhttps://github.com/macrozheng*/@RestController@Api(tags="HttpInterfaceController")@Tag(name="HttpInterfaceController",description="HttpInterface测试接口")@RequestMapping("/remote")publicclassHttpInterfaceController{@AutowiredprivateUmsAdminApiumsAdminApi;@Autowired私有PmsBrandApipmsBrandApi;@AutowiredprivateTokenHoldertokenHolder;@ApiOperation(value="调用远程登录接口获取token")@PostMapping(value="/admin/login")publicCommonResultlogin(@RequestParamStringusername,@RequestParamStringpassword){CommonResultresult=umsAdminApi.login(用户名,密码);登录信息loginInfo=result.getData();if(result.getData()!=null){tokenHolder.putToken(loginInfo.getTokenHead()+""+loginInfo.getToken());}返回结果;}@ApiOperation("调用远程接口查询品牌列表")@GetMapping(value="/brand/list")publicCommonResult>listBrand(@RequestParam(value="pageNum",defaultValue="1")@ApiParam("pagenumber")IntegerpageNum,@RequestParam(value="pageSize",defaultValue="3")@ApiParam("每页页数")IntegerpageSize){returnpmsBrandApi.list(pageNum,pageSize);}@ApiOperation("调用远程接口获取指定id的品牌详情")@GetMapping(value="/brand/{id}")publicCommonResultbrand(@PathVariable("id")Longid){返回pmsBrandApi.detail(id);}@ApiOperation("调用远程接口添加品牌")@PostMapping(value="/brand/create")publicCommonResultcreateBrand(@RequestBodyPmsBrandpmsBrand){returnpmsBrandApi.create(pmsBrand);}@ApiOperation("调用远程接口更新指定id的品牌信息")@PostMapping(value="/brand/update/{id}")publicCommonResultupdateBrand(@PathVariable("id")Longid,@RequestBodyPmsBrandpmsBrand){returnpmsBrandApi.update(id,pmsBrand);}@ApiOperation("调用远程接口删除指定id的brand")@GetMapping(value="/delete/{id}")publicCommonResultdeleteBrand(@PathVariable("id")Longid){returnpmsBrandApi.delete(id);}}测试接下来我们通过Postman进行测试,首先调用登录接口获取远程服务返回的token;然后调用需要登录认证的品牌列表接口,发现可以正常访问。总结Http接口允许我们只定义接口并进行远程HTTP调用,而无需定义方法实现。真的很方便!但是它的实现依赖于Webflux的WebClient,这在我们使用SpringMVC的时候会带来一些麻烦。如果能独立出来就更好了!参考官方文档:https://docs.spring.io/spring...项目源码地址https://github.com/macrozheng...