在工作中碰到需要在服务端中转Http请求的需求,一般的请求其实问题不大,用apache的HttpClient 提供的jar包即可解决问题,但是带文件上传的请求中转,遇到了一些小麻烦,在此记录一下。
业务场景是这样的,由于是做系统升级,升级的同时不影响老版本的使用,同时又不和新版本的代码耦合,所以做了一个适配模块,这个模块是个单独的项目。在前端请求新版本系统时会先进入新版本系统的拦截器中,在拦截器中判断该请求是调用新版本的系统接口还是老版本的系统接口,如果调用老版本系统接口,就会先走适配模块,在适配模块中调用老系统的接口。整个流程大致如下图:
在适配器中使用了apache的HttpClient包,而在拦截器中使用的是jdk自带的java.net.URL类。因此两种方式我都会提供,此外还可以通过java.net.socket类实现Http请求,这几种种方式大同小异,只是HttpClient做了一下封装。最重要的还是要对Http请求协议有比较全面的认识,然后模拟出一个符合协议标准的请求报文就可以像浏览器那样模拟Http请求了。
1 . Http请求报文
通过Fiddler抓包工具,可以抓取网络请求,查看请求信息,下面是我抓取的Get和Post请求的请求报文
(1) . Get请求
1 | GET http://localhost:8081/test?name=111 HTTP/1.1 |
(2) . Post请求
1 | POST http://localhost:8081/upload HTTP/1.1 |
大部分属性大致看一下也能明白它的含义,需要注意的是Post请求中content-type是multipart/form-data时,必须指定boundary,这是属性是参数的分隔符。明白请求报文的格式后,只需中拼凑出这样格式相同的报文头就可以了。
2 . 响应报文
1 | HTTP/1.1 200 |
3 . 模拟客户端请求
下面使用了3种方式模拟客户端请求
(1) . HttpCilent
需要用到apache的两个jar包
1 | <dependency> |
客户端代码如下:
1 | /** |
(2) . URL
URL的方式需要自己去拼接请求报文的格式
1 | /** |
(3) . Socket
1 | public static void sendTest(){ |
这里一定要注意的是Content-Length的计算,因为在HTTP协议中,如果你的长度计算错误,那么服务器就会一直在等待读取,导致请求超时。
4 . 在服务端中转Http请求
上面的代码只是模拟客户端发送http请求,而如果需要在服务端请求第三方的接口,并把接口返回的数据再返回到前台,方式就稍微有点区别。主要的区别就是对返回的输入流的处理,只要把返回的输入流复制到当前请求的response的输出流中即可,代码如下:
(1) . HttpCilent
1 | /** |
(2) . URL
1 | /** |
打赏一个呗