前言

对于url的请求两种需求,一种是程序调用接口后返回数据; 二是调用第三方openApi接口。



基于URLConnection的返回值获取

使用java.net包下面原生的URLConnection对象,使用IO流进行数据提交和请求获取,比如说:获取返回结果。

若只是向服务器请求数据,则为HTTP请求方法为GET。

若需要向服务器提交数据,必须在先调用setDoOutput(true)。当doOutput属性为true时,请求方法将由GET变为POST。

使用getInputStream()方法输出的内容只有响应体,不包含响应的首部。



public class WeblistenerTask {
	
	static String flinkURL = "https://api.apiopen.top/getJoke?page=1&count=2&type=video";
	
	//@Scheduled(cron = "00 00 00 * * ?")
	public static void weblistener() throws IOException {
		
		StringBuffer result = new StringBuffer();
		result.append("niko");
		
		URL url = new URL("https://api.apiopen.top/getJoke?page=1&count=2&type=video");
		URLConnection connection = url.openConnection();
		
		BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		String line;  
		   while ((line = in.readLine())!= null)  
		   {  
		    result.append(line);
		   }  
		   in.close();  
		 System.err.println(result.toString());
		 
		 System.err.println( result.toString().contains("running") );
		 
	}
	
	public static void main(String[] args) throws IOException {
		weblistener();
	}
}



使用java.net.URLConnection的子类HttpURLConnection,可以更好的遍历操作http请求,比如说

void setRequestMethod(String method)

基于HttpClient的api请求

依赖引入

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.70</version>
    </dependency>
    <!--    三方接口解析-->
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.10</version>
    </dependency>



消息体的类型

涉及后端的参数注解和请求的Content-Type。

服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码。所以post提交数据应该包括消息头的Content-Type + entity-body(消息主题)。

java url传递参数怎么获取 java调用url接口_java



而对于消息主题常见有四种,不同的Content-Type在后端需要进行不同的入参处理

  1. application/x-www-form-urlencoded:HTTP中默认的提交数据的方式。http://127.0.0.1:9010/test/test2?name=cbry&age=26,对于spring中设置@RequestParam
  2. multipart/form-data:@RequestPart(“file”) MultipartFile file;
  3. application/json:@RequestBody,@RequestBody 也可以处理 application/xml;
  4. text/xml:类似的有text/html( HTML格式)、text/plain (纯文本格式)等。

PS:对应的我们想到@RequestMapping(post\get均接受),以及@ResponseBody返回json数据,如上面截图的响应标头。注意restcontroller是集合responsebody。



举个栗子:当后端用的@GetMapping的时候进行post请求就会:

java url传递参数怎么获取 java调用url接口_HttpClient_02



当使用表单:strEntity.setContentType("application/x-www-form-urlencoded");,提交JSON数据:

这里主要原因还是因为用的StringEntity,这里后面会提及:

java url传递参数怎么获取 java调用url接口_第三方api_03



HttpPost对象中才有Entity,如果修改成下面代码,则可以进行类似于:http://127.0.0.1:9010/test/test2?name=cbry&age=26的请求:

//发送json数据需要设置contentType
            strEntity.setContentType("application/x-www-form-urlencoded");
            List nvps = new ArrayList();
            nvps.add(new BasicNameValuePair("name", "cbry"));
            nvps.add(new BasicNameValuePair("age", "26"));
            post.setEntity(new UrlEncodedFormEntity(nvps));

java url传递参数怎么获取 java调用url接口_java_04



不同的HttpEntity

具体看接口实现类,列举常用的三个

//StringEntity
StringEntity stringEntity = new StringEntity(param);
stringEntity.setContentType("application/x-www-form-urlencoded");  

//UrlEncodedFormEntity
List nvps = new ArrayList();  
nvps.add(new BasicNameValuePair("name", "cbry"));  
nvps.add(new BasicNameValuePair("age", "26"));  
httpPost.setEntity(new UrlEncodedFormEntity(nvps)); //param参数,可以为"name=cbry&age=26"的格式参数请求

//MultipartEntity
MultipartEntity entity = new MultipartEntity();
entity.addPart(“param1″, new StringBody(“李四”, Charset.forName(“UTF-8″)));
entity.addPart(“param2″, new StringBody(“男”, Charset.forName(“UTF-8″)));
entity.addPart(“param3″, new FileBody(new File(“C:\\test.txt”)));
HttpClient client = new DefaultHttpClient();
HttpPost postrequest = new HttpPost(url);



HttpClient工具类

分别是带参数的POST/GET请求类方法jsonPostReq,和带JSON的POST请求paramsReq。

package com.cbry.bds.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.buf.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author cbry
 * @version 1.0.0
 * @ClassName HttpClientUtil 
 * @createTime 2022年05月17日 14:58:00
 */
@Slf4j
public class HttpClientUtil {

    private static RequestConfig requestConfig = null;

    static {

        //设置http的状态参数 , old: 5000
        requestConfig = RequestConfig.custom()
                .setSocketTimeout(60000)
                .setConnectTimeout(60000)
                .setConnectionRequestTimeout(60000)
                .build();
    }

    public static String jsonPostReq(String url , String token, JSONObject jsonObject){
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String result = null;

        try {
            //请求发起客户端
            httpclient = HttpClients.createDefault();

            //参数集合
            String paramsStr = jsonObject.toString();

            //通过post方式访问
            HttpPost post = new HttpPost(url);
            post.addHeader("token", token);
            post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");

            //设置请求参数
            //HttpEntity paramEntity = new UrlEncodedFormEntity(paramsStr,"UTF-8");
            StringEntity strEntity = new StringEntity(paramsStr);
            strEntity.setContentEncoding("UTF-8");

            //发送json数据需要设置contentType
            strEntity.setContentType("application/json");
            post.setEntity(strEntity);
            log.info("请求地址:" + post.getURI().toString());
            log.info("请求参数:" + EntityUtils.toString(post.getEntity()));

            //执行请求
            response = httpclient.execute(post);

            //返回结果
            HttpEntity valueEntity = response.getEntity();
            result = EntityUtils.toString(valueEntity);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(httpclient != null){
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    public static String paramsReq(String url,Map<String, String> paramsMap,String reqMethod) throws IOException {

        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        HttpUriRequest req = null;

        //设置参数解析
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        for (String key : paramsMap.keySet()) {
            String value = paramsMap.get(key);
            NameValuePair pair = new BasicNameValuePair(key, value);
            params.add(pair);
        }

        //设置请求类型
        if (reqMethod.toLowerCase().equals("post")){
            req = RequestBuilder.post().setUri(url)
                    .addParameters(params.toArray(new BasicNameValuePair[params.size()]))
                    .setConfig(requestConfig).build();
        }else{
            req = RequestBuilder.get().setUri(url)
                    .addParameters(params.toArray(new BasicNameValuePair[params.size()]))
                    .setConfig(requestConfig).build();
        }

        //设置头
        req.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");

        response = httpclient.execute(req);

        String result = null;
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(httpclient != null){
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        Map<String,String> params = new HashMap<>();
        params.put("name","cnry");
        params.put("age","26");
        System.err.println(paramsReq("http://127.0.0.1:9010/test/test2" ,params , "GET"));
    }

//    public static void main(String[] args) {
//        JSONObject jo= new JSONObject();
//        //page=1&count=2&type=video
//        jo.put("name",1);
//        jo.put("age",2);
//        //https://api.apiopen.top/api/getHaoKanVideo
//        JSONObject jsonObject = JSONObject.parseObject(jsonPostReq("http://127.0.0.1:9010/test/test" , ""  , jo));
//        System.out.println( jsonObject );
//    }


}



测试的controller方法:

request用来debug中查看paramsMap中的传参。

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @RequestMapping("/test")
    public User test(HttpServletRequest request,@RequestBody User user){
        return user;
    }

    @RequestMapping("/test2")
    public User test2(HttpServletRequest request, User user){
        return user;
    }
}



补充

使用hutool工具包,可快捷实现,无须重复轮子:

<dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>${hutool.version}</version>
    </dependency>

比如说:

HttpRequest.post("http://127.0.0.1:8088/bonc/api/taskspec")
                    .body(params.toString())
                    .execute().body();

base模板的baseService中有个dao返回值的缘故是:dao继承的类的方法可以不用重复写service方法,减少冗余。

鸣谢

peakchao免费开放接口API

application/json 四种常见的 POST 提交数据方式