likes
comments
collection
share

【Java HTTP】http-request库使用

作者站长头像
站长
· 阅读数 47

0. 前言

在弄钉钉机器人时需要在java程序中发起http请求,以前只在前端发起过http请求。所以就 总结下java是如何发送http请求的。

现在对java io还不是很熟,先使用第三方库。常见的有Spring家族,Apache家族的,还有OKHTTP。然后我在搜索第三方库的时候发现了一篇文章JAVA http请求工具类http-request。这篇文章推荐http-request这个库,可它的内容可真是劝退使用这个库 。

http-request库最后一次更新是2015年

1. http-request

1. 不携带任何参数的GET请求

服务端

@GetMapping("doGetByNull")
public String doGetByNull() {
  return "这是不携带参数的【GET】请求";
}

工具类【HttpUtils】

public static void doGetByNull(String url) {
  String body = HttpRequest.get(url, true).body();
  log.info("doGetByNull:" + body);
}

测试类

@Test
void doGetByNull() {
  HttpUtils.doGetByNull(URL + "doGetByNull");
}

结果

doGetByNull:这是不携带参数的【GET】请求

2. URL带参的GET请求

服务端

@GetMapping("doGetByUrl/{param}")
public String doGetByUrl(@PathVariable("param") String param) {
  return "这是【URL带参】的【GET】请求,参数是【" + param + "】";
}

工具类【HttpUtils】

和上面用的是用的是同一个方法。

测试类

@Test
void doGetByUrl() {
  HttpUtils.doGetByNull(URL + "doGetByUrl/苹果派");
}

结果

doGetByNull:这是【URL带参】的【GET】请求,参数是【苹果派】

这里是在get(url, true)true这个参数才成功的。如果只是get(url)则会出现

doGetByNull:<!doctype html><html lang="en"><head><title>HTTP Status 400 – Bad Request</tit...

这是因为url上有中文的话,没有true参数的话不会解码,想更了解的话可以看看源码。

我一开始也不知道,而且还去issue上找了下,发现同样有老哥问issue#154,我又去看了下开头说的那片推荐文,但是没有介绍如何用url传参,更别说url上传中文出现错误的了。

可以看下请求是怎么样的。

【Java HTTP】http-request库使用

可以看的出【苹果派】是没有被解析到url上的。

恰巧看到IDEA方法的参数提示有encode,问题便解决了。

源码

public static HttpRequest get(CharSequence baseUrl, boolean encode, Object... params) {
  String url = append(baseUrl, params);
  return get((CharSequence)(encode ? encode(url) : url));
}

3. 携带Query参数的GET请求

服务端

@GetMapping("doGetByQuery")
public String doGetByQuery(String query1, String query2) {
  return "这是携带【Query】参数的【GET】请求,参数是【" + query1 + "】和【" + query2 + "】";
}

工具类【HttpUtils】

public static void doGetByQuery(String url, Map data) {
  String body = HttpRequest.get(url, data, true).body();
  log.info("doGetByQuery:" + body);
}

测试类

@Test
void doGetByQuery() {
  HashMap<String, String> data = new HashMap();
  data.put("query1", "淡茶");
  data.put("query2", "月亮");
  HttpUtils.doGetByQuery(URL + "doGetByQuery", data);
}

结果

doGetByQuery:这是携带【Query】参数的【GET】请求,参数是【淡茶】和【月亮】

如何封装一个不确定query参数的GET请求,我一开始并不知道有get(CharSequence baseUrl, Map<?, ?> params, boolean encode)这个方法,我就去看开头那片文章,告诉用form这个方法,然而是失败的。失败数据就不放出来,就看生成的URL是怎么样的吧。

【Java HTTP】http-request库使用

是一个POST请求,我不明白写这篇推荐文章的作者是否有实际操作过。

值得吐槽的是这个库的作者为什么重载不弄得有规律点。

get(CharSequence baseUrl, boolean encode, Object... params);
get(CharSequence baseUrl, Map<?, ?> params, boolean encode)

我知道有一个可以传不定参数的方法,但是这样没法对它二次封装。我想这个库的作者应该会有提供一个方法可以用Map之类传参。所以我直接将 Object 换成了 Map,但是失败了。后面看下源码才知道。

4. 携带Query参数的POST请求

服务端

@PostMapping("doPostByQuery")
public String doPostByQuery(String query1, String query2) {
  return "这是携带【Query】参数的【POST】请求,参数是【" + query1 + "】和【" + query2 + "】";
}

工具类【HttpUtils】

public static void doPostByQuery(String url, Map data) {
  String body = HttpRequest.post(url).form(data).body();
  log.info("doPostByQuery:" + body);
}

测试类

@Test
void doPostByQuery() {
  HashMap<String, String> data = new HashMap();
  data.put("query1", "fight");
  data.put("query2", "喵~");
  HttpUtils.doPostByQuery(URL + "doPostByQuery", data);
}

结果

doPostByQuery:这是携带【Query】参数的【POST】请求,参数是【fight】和【喵~】

这个倒是没什么问题,form参数和query参数都可以通过这个方式请求。

5. 携带Json参数的POST请求

服务端

@PostMapping("doPostByJson")
public String doPostByJson(@RequestBody TestDto testDto) {
  return "这是携带【Json】参数的【POST】请求,参数是【" + testDto.toString() + "】";
}

工具类【HttpUtils】

public static void doPostByJson(String url, Object data) {
  String json = JSON.toJSONString(data);
  String body = HttpRequest.post(url)
    .header(HttpRequest.HEADER_CONTENT_TYPE, HttpRequest.CONTENT_TYPE_JSON)
    .send(json).body();
  log.info("doPostByJson:" + body);
}

测试类

@Test
void doPostByJson() {
  TestDto testDto = new TestDto("前辈", "好呀");
  HttpUtils.doPostByJson(URL + "doPostByJson", testDto);
}

结果

doPostByJson:这是携带【Json】参数的【POST】请求,参数是【TestDto(field1=前辈, field2=好呀)】

携带JSON的POST请求,推荐这个库的作者没有介绍,官网也没介绍,去翻了下issue#110找到了。

6. 上传文件

服务端

@PostMapping("doPostByFile")
public String doPostByFile(@RequestParam("file") MultipartFile file) {
  String filePath = "D:/file/";
  String[] OriginalFilenameSplit = file.getOriginalFilename().split("\\.");
  String fileName = UUID.randomUUID().toString().replace("-", "")
    + "."
    + OriginalFilenameSplit[OriginalFilenameSplit.length - 1];
  File dest = new File(filePath + fileName);
  if (!dest.getParentFile().exists()) {
    dest.getParentFile().mkdirs();
  }
  try {
    file.transferTo(dest);
    return "上传成功";
  } catch (IOException e) {
    e.printStackTrace();
  }
  return "上传失败";
}

工具类【HttpU tils】

public static void doPostByFile(String url, Map<String, File> fileMap) {
  HttpRequest request = HttpRequest.post(url);
  for (String key : fileMap.keySet()) {
    request.part(key, fileMap.get(key).getName(), fileMap.get(key));
  }
  log.info("doPostByFile:" + request.body());
}

测试类

@Test
void doPostByFile() {
  File file = new File("C:\\Users\\Kzc19\\Desktop\\default.jpg");
  Map<String, File> map = new HashMap();
  map.put("file", file);
  HttpUtils.doPostByFile(URL + "doPostByFile", map);
}

结果

doPostByFile:上传成功

这个地方按照官方例子是不行的,至少我是如此,且我在issue#73也发现有人通过官方例子失败的。但他们也给出了解决方法,用官方使用的那个方法的一个重载方法。

2. 结束

http-request这个库最后一次更新是在2015年,应该是已经没有维护了,在issue上的提问也没有回答,所以还是别使用这个库了。但是我觉得这个库就一个HttpRequest.java文件,非常的小巧,如果是学习java io,这个是一个很不错的学习 项目。

上面的源码上传到gitee上了。如有错误,请多指教。

转载自:https://juejin.cn/post/7045868668395192333
评论
请登录