java net 请求发送
我们日常对接第三方接口会有很多的便利的方式,如httpclient,等等的工具,不过底层的通过java原生的形式还是需要记录一下的。
环境介绍:
京东万象:京东旗下的一个服务接口集合有很多的服务:https://wx.jdcloud.com/api
这里的都是提供了API,通过请求API可以获得信息。
我们这里选择全国天气预报看到接口为:
我们分析一下接口,这里面提供了url要我们提供自己账号的appkey,这样才能提供服务。参数里面有三个不过可以任选其一。我们这里就查询西安和青岛的天气。
我们先查询一下青岛获得响应:
Response:
Status Code: 200
Time:166ms
Date:Fri 18 Jun 2021 12:12:48 GMT
Body:
{
"code": "10000",
"charge": false,
"msg": "查询成功",
"result": {
"status": 0,
"msg": "ok",
"result": {
"city": "青岛",
"cityid": 283,
"citycode": "101120201",
"date": "2021-06-18",
"week": "星期五",
"weather": "晴",
"temp": "23",
"temphigh": "28",
"templow": "21",
"img": "0",
"humidity": "70",
"pressure": "992",
"windspeed": "4.1",
"winddirect": "南风",
"windpower": "2级",
"updatetime": "2021-06-18 19:50:00",
"index": [
{
"iname": "空调指数",
"ivalue": "较少开启",
"detail": "您将感到很舒适,一般不需要开启空调。"
},
。。。
],
"aqi": {
"so2": "8",
"so224": "8",
"no2": "38",
"no224": "40",
"co": "0.720",
"co24": "0.660",
"o3": "149",
"o38": "154",
"o324": "154",
"pm10": "81",
"pm1024": "47",
"pm2_5": "37",
"pm2_524": "25",
"iso2": "3",
"ino2": "20",
"ico": "8",
"io3": "51",
"io38": "96",
"ipm10": "62",
"ipm2_5": "51",
"aqi": "96",
"primarypollutant": "O3",
"quality": "良",
"timepoint": "2021-06-18 19:00:00",
"aqiinfo": {
"level": "二级",
"color": "#FFFF00",
"affect": "空气质量可接受,但某些污染物可能对极少数异常敏感人群健康有较弱影响",
"measure": "极少数异常敏感人群应减少户外活动"
}
},
"daily": [
{
"date": "2021-06-18",
"week": "星期五",
"sunrise": "04:41",
"sunset": "19:18",
"night": {
"weather": "晴",
"templow": "21",
"img": "0",
"winddirect": "西南风",
"windpower": "3-5级"
},
"day": {
"weather": "晴",
"temphigh": "28",
"img": "0",
"winddirect": "北风",
"windpower": "3-5级"
}
},
{
"date": "2021-06-19",
"week": "星期六",
"sunrise": "04:41",
"sunset": "19:18",
"night": {
"weather": "晴",
"templow": "21",
"img": "0",
"winddirect": "西南风",
"windpower": "3-5级"
},
"day": {
"weather": "晴",
"temphigh": "29",
"img": "0",
"winddirect": "西南风",
"windpower": "3-5级"
}
}。。。
],
"hourly": [
{
"time": "19:00",
"weather": "晴",
"temp": "25",
"img": "0"
},
。。。。
]
}
},
"requestId": "dc199bef986d43229d422e4bb0468bf3"
}
这些东西和我们日常看的天气信息无异。
ps通过citycode我们可以知道,这里可以获得城市和编号的表,如果有牵扯到地方的业务使用这个统一的表会方面一些。
private static final String APPKEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private static final String URL="http://way.jd.com/jisuapi/weather";
private static final String PARAMETER_CITY="city";
public static void main(String[] args) throws Exception {
// 地址转为url
java.net.URL url = new URL(URL);
// 建立连接
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
// 这里是设置属性 即 设置了头部并不是参数
//connection.addRequestProperty("city","青岛");
//connection.addRequestProperty("appkey",APPKEY);
//String s1 = StreamUtils.copyToString(connection.getInputStream(), Charset.forName("UTF-8"));
//System.out.println(s1);
connection.setDoOutput(true);
connection.setRequestMethod("GET");
// 加入参数信息
StringBuffer stringBuffer = new StringBuffer();
StringBuffer parameter = stringBuffer.append("city=").append("青岛").append("&appkey=").append(APPKEY);
//参数加入连接还是通过流的形式
connection.getOutputStream().write(parameter.toString().getBytes());
//connection.connect(); 发现这一行注销掉依然可以请求请求
String s = StreamUtils.copyToString(connection.getInputStream(), Charset.forName("UTF-8"));
System.out.println(s);
}
对于java net发送的总结
1.URL建立连接,只是获取了连接的对象并不是真正的连接,http是无状态的短连接,如果在连接以后设置发送参数如方法等会报错:重复连接错误
对应的源码为:
public void setDoOutput(boolean dooutput) {
if (connected)
throw new IllegalStateException("Already connected");
doOutput = dooutput;
}
这个connected是URLConnection的属性默认为false
/**
* If {@code false}, this connection object has not created a
* communications link to the specified URL. If {@code true},
* the communications link has been established.
*/
protected boolean connected = false;
2.明明没有连接为什么执行某一些方法的时候显示已经连接了?
我们测试getContentLength()
方法,这个方法是获取相应的长度的。
这里打出长度为117,紧接着就出现了重复连接的问题。结合上面的connected,应该是某一些牵扯到响应参数的时候进行了发送。
跟踪源码我们发现HttpURLConnection(URLConnection的子类)的getInputStream()
、getOutputStream()
、connect()
,三个方法都会修改connected的状态造成第重复连接。
在getContentLength()
的第一句就是调用了getInputStream();
public int getContentLength() {
try {
this.getInputStream();
} catch (Exception var4) {
return -1;
}...
}
--------------------------------
public synchronized InputStream getInputStream() throws IOException {
this.connecting = true;
这也就说明了在使用这几个参数的时候会修改URLConnection的状态。在通过debug深挖下去能看到发送的connect方法。
同时在调用某些方法的时候会检测这个标示为是否为true 如果是就出现我们看到的哪个异常了。