你会换掉Postman吗?我正在用HTTP Client...

本文详细介绍了如何在IDEA中使用HTTPClient替代POSTMAN进行接口测试,包括解决跨平台hosts配置问题,以及如何利用HTTPClient的环境变量和请求模板功能提高开发效率。

前言

只有光头才能变强。

文本已收录至我的GitHub精选文章,欢迎Star

https://github.com/ZhongFuCheng3y/3y

相信大家都用过POSTMAN吧,后端在开发的时候写完接口总得去自测调用一下,看符不符合自己的预期。

postman

因为我们的接口可能会有很多参数或者我们的参数是json格式的(等等原因),直接用浏览器去请求不太方便,而且使用浏览器去请求也不能复用(没有保存的功能)。

所以我们常常会用一些别的软件(插件),而POSTMAN就是这里边最出名的。

这篇文章不是在介绍POSTMAN,而是我们Java程序员最喜欢的IDEA,它也能做到POSTMAN的功能,而且我觉得更加好用。

小插曲

在前几天换了MacBookPro,自然就需要把在Windows上的hosts配置的东西搬移到MacBookPro上

毕业半年,买了一台MacBook Pro

于是我就把Windows上的hosts通过QQ复制到我的gas mark(Mac 上管理hosts的一个软件,我觉得挺好用的)

从Windows复制对应的hosts配置

于是我就很欢快愉悦地就将这些配置复制到gas mark。复制完了以后,我去访问自己的预发环境也是成功了(我这边一般预发环境都要配置hosts才能访问)。

但是等我用POSTMAN和IDEA自带的HTTP Clint去测试我自己接口的时候,一直都404了,我非常不明白为什么404

  • 明明我自己的机器从浏览器直接访问预发环境是没问题的啊

  • 我将相同的URL放在Windows上是可以访问的,放在Mac上就访问不了

  • 好奇怪啊….

于是我就喊来了我的小伙伴帮我看看什么情况(我没遇到过这种问题),小伙伴也给我分析起来了(搞着搞着就一群小伙伴都围着我看这问题了)

  1. 检查一下我的gas mark配置有没有问题----没看出有问题

  2. 检查一下我的绑定有没有相同的域名----没看出有问题

  3. 检查一下本机的hosts文件有没有问题(注:我这里是在图文上看的。快捷键:option+command+空格,然后command+shift+g,输入/etc/hosts查看文件----没看出有问题

  4. ping一下域名----发现能ping通,但不是我绑定的ip

  5. 怀疑DNS污染,去搜了几条命令刷新DNS----无果

  6. 此时有个声音:“是不是你的hosts文件有特殊的字符啊?“,我熟练地在iTerm2输入sudo vim /etc/hosts,一看,好多的特殊字符。----问题解决,复制的时候存在特殊字符。哎哟。

简单介绍HTTP Client

上面也讲到了,IDEA已经自带了类似POSTMAN的工具给我们使用了,如果它足够好用,我就不用去下载POSTMAN了。

首先,我们来找到它的入口:

入口

Tools->HTTP Client->Test RESTful Web Service,不会很难找

点开以后我们可以在底部发现REST Client

REST Client 界面

从界面上的小字,我们可以看出:IDEA是不推荐我们使用REST Client了,不妨让我们去使用new HTTP Client。从REST Client的风格我们可以看出跟POSTMAN没什么大的区别(从功能上长得差不多)

点击蓝字,我们跳到IDEA推荐用的new HTTP Client,可以发现这个界面:

一个新的界面

我对这种用写的方式还是挺喜欢的(个人)。我们尝试一下右边的几个链接就可以快速入门

首先是Add Request,从英文上我们已经可以得出这是增加一个常见的请求模板(供你选择)

Add Request

我们随便点一个试试,看一下是怎么样的:

尝试功能

然后我们可以点击Examples链接,看一下它的功能:

Examples链接

我们可以查看到各种的示例,非常方便我们去入门:

各种示例

更好用的是,我们可以定义变量(不同的环境使用不同的变量),我们可以定义http-client.env.json,里边写一些通用变量相关的值。然后我们在.http文件下就可以引用:

//http-client.env.json 样式
{
  "dev": {
    "baseUrl": "http://gateway.xxx.cn/",
    "username": "",
    "password": ""
  },
  "pre": {
    "baseUrl": "http://localhsot:8888/",
    "username": "",
    "password": ""
  }
}

.http文件中使用{{condition}}就可以引用到我们公用的环境变量了:

GET {{baseUrl}}/api/item?id=99
Accept: application/json

在执行的时候我们就可以选择不同的环境执行:

样式图

最后

我们可以发现的是,IDEA给我们以文件的方式就能构建自己的接口,这说明我们可以将文件上传到Git上,方便多人协作。

可以通过配置来帮我们快速切换对应的环境(变量),只要写一次的请求体,就可以用作于多个环境。

通过官方给的Examples我们也可以快速去了解如何使用,没有什么学习成本。

还有一些高级的功能….我就不说了(因为我也不懂),大家可以有兴趣可以去看一下。

参考资料:

  • https://github.com/corningsun/yuchigong/blob/httpClient/httpClient/README.md

  • https://segmentfault.com/a/1190000021118350?utm_source=tag-newest

当我写下这篇文章的时候,敖丙和鸡蛋都说:”POSTMAN才是世界上最好用的工具,三歪没有格局。等他发文章的时候我要举报他

如果是你,你会换掉POSTMAN吗?不妨在评论区留言。

欢迎加入交流群学习,备注加群

说实话在这个群,哪怕您不说话,光看聊天记录,都能学到东西

推荐阿里云推广服务器89/年,229/3年,买来送自己,送女朋友马上过年再合适不过了,买了搭建个项目给面试官看也香,还可以熟悉技术栈,(老用户用家人账号买就好了,我用我女朋友的????)。扫码购买

我这里还有购买后的教程:搭建教程,从0开始一步一步带你搭建 

两年呕心沥血的文章「面试题」「基础」「进阶」这里全都有!

现在我写了一个stomp客户端,用以跟服务端通信,我的连接和订阅的返回正常,如下: 10:08:22.915 [SimpleAsyncTaskExecutor-1] DEBUG org.springframework.web.client.RestTemplate - HTTP POST https://127.0.0.1:8081/api/vms/vms-8ff225f900a44a90a937143fe6774a98/ws/status/611/88a50e273a154f358a8a97a9fa3aff72/xhr_send 10:08:22.928 [SimpleAsyncTaskExecutor-1] DEBUG org.springframework.web.client.RestTemplate - Response 204 NO_CONTENT ************connected 10:08:22.937 [SimpleAsyncTaskExecutor-1] DEBUG org.springframework.web.client.RestTemplate - HTTP POST https://127.0.0.1:8081/api/vms/vms-8ff225f900a44a90a937143fe6774a98/ws/status/611/88a50e273a154f358a8a97a9fa3aff72/xhr_send 10:08:22.957 [SimpleAsyncTaskExecutor-1] DEBUG org.springframework.web.client.RestTemplate - Response 204 NO_CONTENT ****************收到订阅的 /user/exchange/amq.direct/trade 消息:{"errorCode":0,"message":"success.","result":null} 但是我通过postman发送http触发业务逻辑后,本该从服务端通过stomp发送过来的消息有点问题,客户端报错如下: STOMP Exception: No suitable converter for payload type [class java.lang.String] from handler type [class com.tplink.cloud.demo.websocket_client.WebsocketClientApplication$1$1] STOMP Exception: No suitable converter for payload type [class java.lang.String] from handler type [class com.tplink.cloud.demo.websocket_client.WebsocketClientApplication$1$1] STOMP Exception: No suitable converter for payload type [class java.lang.String] from handler type [class com.tplink.cloud.demo.websocket_client.WebsocketClientApplication$1$1] 客户端的代码如下: package com.tplink.cloud.demo.websocket_client; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.simp.stomp.StompCommand; import org.springframework.messaging.simp.stomp.StompFrameHandler; import org.springframework.messaging.simp.stomp.StompHeaders; import org.springframework.messaging.simp.stomp.StompSession; import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter; import org.springframework.web.socket.WebSocketHttpHeaders; import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.socket.messaging.WebSocketStompClient; import org.springframework.web.socket.sockjs.client.RestTemplateXhrTransport; import org.springframework.web.socket.sockjs.client.SockJsClient; import org.springframework.web.socket.sockjs.client.Transport; import org.springframework.web.socket.sockjs.client.WebSocketTransport; @SpringBootApplication public class WebsocketClientApplication { public static void main(String[] args) throws InterruptedException { // 禁用SSL验证 SSLUtil.disableSSLVerification(); // WebSocketClient webSocketClient = new StandardWebSocketClient(); List<Transport> transports = new ArrayList<>(2); transports.add(new WebSocketTransport(new StandardWebSocketClient())); transports.add(new RestTemplateXhrTransport()); SockJsClient webSocketClient = new SockJsClient(transports); WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient); stompClient.setMessageConverter(new StringMessageConverter()); // String url1 = "/api/vms/{vmsId}/ws/status"; String vmsId = "vms-8ff225f900a44a90a937143fe6774a98"; String url = String.format("wss://127.0.0.1:8081/api/vms/%s/ws/status", vmsId); // String url = "wss://127.0.0.1:8081/api/vms/vms-8ff225f900a44a90a937143fe6774a98/ws/status/230/xgydnmu0/websocket"; // 添加头,握手的那些http,比如cookie final WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); headers.set("Cookie", "JSESSIONID=1990891CA73E17ECE4DEC572A6C98990; VMS_SID=v-d9e8566c-7185-4be9-9a61-91690dc34510"); headers.set("SourceType", "vms_web"); headers.set("Content-Type", "application/json;charset=UTF-8"); // 头部字段 final StompHeaders connectHeaders = new StompHeaders(); connectHeaders.set("CSRF-TOKEN", "2b6c8a71a4e147709e72101d65e5e088"); connectHeaders.set("accept-version", "1.1,1.0"); // connectHeaders.set("heart-beat", "20000,20000"); // 链接到服务端 stompClient.connect(url, headers, connectHeaders, new StompSessionHandlerAdapter() { @Override public void afterConnected(StompSession session, StompHeaders connectedHeaders) { System.out.println("************connected"); // 订阅用户消息,"/topic/vms/{vmsId}/users/{userId}/device-add-progress/{uuid}" String subscribeUrl = "/topic/vms/{vmsId}/users/{userId}/device-add-progress/{uuid}"; session.subscribe(subscribeUrl, new StompFrameHandler() { @Override public Type getPayloadType(StompHeaders headers) { return String.class; } @Override public void handleFrame(StompHeaders headers, Object payload) { // String payloadStr; // if (payload instanceof byte[]) { // payloadStr = new String((byte[]) payload); // } else { // payloadStr = payload.toString(); // } System.out.println("****************收到订阅的 /user/exchange/amq.direct/trade 消息:" + payload); } }); // 发送更新消息 // session.send("/app/trade", "更新消息"); } @Override public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) { System.err.println("STOMP Exception: " + exception.getMessage()); } @Override public void handleTransportError(StompSession session, Throwable exception) { System.err.println("Transport Error: " + exception.getMessage()); } }); TimeUnit.SECONDS.sleep(1000); } } 帮我分析解决这个问题
10-11
postman中,API调用如下:https://localhost:8043/portal/sociallogin/forward?authType=19&clientMac=AA-BB-CC-11-22-33&clientIp=172.28.111.111&apMac=AA-BB-CC-DD-EE-11&gatewayMac=AA-BB-CC-DD-EE-22&ssidName=test ssid&radioId=1&vid=10&t=1760168285218&originUrl=www.original.com 代码对应接口为@GetMapping(SOCIAL_LOGIN_FORWARD) public void socialLoginForward( @RequestParam(value = AUTH_TYPE , required = false) Integer authType, @RequestParam(value = CLIENT_MAC, required = false) String clientMac, @RequestParam(value = CLIENT_IP, required = false) String clientIp, @RequestParam(value = AP_MAC, required = false) String apMac, @RequestParam(value = GATEWAY_MAC, required = false) String gatewayMac, @RequestParam(value = SSID_NAME, required = false) String ssidName, @RequestParam(value = RADIO_ID, required = false) Integer radioId, @RequestParam(value = VID, required = false) Integer vid, @RequestParam(value = T, required = false) Long t, @RequestParam(value = ORIGIN_URL, required = false) String originUrl, HttpServletRequest request, HttpServletResponse response) throws IOException 调用后报错500,日志为:ERROR [https-jsse-nio-8043-exec-10] [] o.a.c.c.C.[.[.[.[dispatcherServlet](): Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null] with root cause java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null at com.tplink.smb.omada.apigateway.dispatch.filter.PortFilter.isAccessAllowed(PortFilter.java:89) ~[api-gateway-core-6.0.0.18.jar:6.0.0.18]
最新发布
10-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值