当前位置: 首页 > 科技观察

面试官:请用Java实现一个HTTP请求

时间:2023-03-19 19:45:17 科技观察

大家好,我是北军。在最近的一次面试中,面试官居然提出了这样一个要求:请用Java实现一个HTTP请求!当然不能胆小!起来!!!今天我将介绍一种在Java中执行HTTP请求的方法——使用Java内置的HttpUrlConnection类实现。从JDK11开始,Java提供了一个新的用于执行HTTP请求的API,用于替代HttpUrlConnection,即HttpClientAPI。HttpUrlConnectionHttpUrlConnection类允许我们在不使用任何额外库的情况下执行基本的HTTP请求。我们需要的所有类都是java.net包的一部分。使用这种方法的缺点是代码可能比其他HTTP库更麻烦,并且它不提供更高级的功能,如用于添加标头或身份验证的专用方法。创建请求我们可以使用URL类的openConnection()方法来创建HttpUrlConnection实例。注意这个方法只是创建了一个连接对象,还没有建立连接。HttpUrlConnection类将requestMethod属性设置为get、post、head、options、put、delete、trace之一。让我们使用GET方法创建到给定URL的连接:URLurl=newURL("https://www.javanorth.cn");HttpURLConnectioncon=(HttpURLConnection)url.openConnection();con.setRequestMethod("GET");添加请求参数如果我们想给一个请求添加参数,就必须将doOutput属性设置为true,然后将param1=value&m2=value这样的字符串写入到HttpUrlConnection实例的OutputStream中。Mapparameters=newHashMap<>();parameters.put("param1","val");con.setDoOutput(true);DataOutputStreamout=newDataOutputStream(con.getOutputStream());输出。writeBytes(ParameterStringBuilder.getParamsString(parameters));out.flush();out.close();为了方便参数Map的转换,我们编写了一个名为ParameterStringBuilder的实用类,其中包含一个静态方法getParamsString(),可以将Map转换为所需格式的字符串。publicclassParameterStringBuilder{publicstaticStringgetParamsString(Mapparams)throwsUnsupportedEncodingException{StringBuilderresult=newStringBuilder();for(Map.Entryentry:params.entrySet()){result.append(URLEncoder.encode(entry.getKey(),"UTF-8"));结果追加(“=”);result.append(URLEncoder.encode(entry.getValue(),"UTF-8"));结果.追加(“&”);}字符串resultString=result.toString();返回resultString.length()>0?resultString.substring(0,resultString.length()-1):resultString;}}设置请求头信息通过使用setRequestProperty()方法,可以在请求中添加头信息。con.setRequestProperty("Content-Type","application/json");要从连接中读取标头值,我们可以使用getHeaderField()方法。StringcontentType=con.getHeaderField("Content-Type");配置超时HttpUrlConnection类允许设置连接和读取超时。这些值定义了等待与服务器建立连接或读取数据的时间间隔。为了设置超时值,我们可以使用setConnectTimeout()和setReadTimeout()方法。con.setConnectTimeout(5000);con.setReadTimeout(5000);在此示例中,我们将两个超时设置为5秒。处理Cookiejava.net包包含有助于处理cookie的类,例如CookieManager和HttpCookie。首先,要从响应中读取cookie,我们可以检索Set-Cookie标头的值并将其解析为HttpCookie对象列表。StringcookiesHeader=con.getHeaderField("Set-Cookie");Listcookies=HttpCookie.parse(cookiesHeader);接下来,我们将向cookieStore添加cookie。cookies.forEach(cookie->cookieManager.getCookieStore().add(null,cookie));让我们检查是否有一个名为username的cookie,如果没有,我们将把它添加到cookieStore中,值为“javanorth”。可选usernameCookie=cookies.stream().findAny().filter(cookie->cookie.getName().equals("username"));if(usernameCookie==null){cookieManager.getCookieStore().add(null,newHttpCookie("username","javanorth"));}最后,为了在请求中包含cookie,我们需要在关闭并重新打开连接后设置Cookie标头。con.disconnect();con=(HttpURLConnection)url.openConnection();con.setRequestProperty("Cookie",StringUtils.join(cookieManager.getCookieStore().getCookies(),";"));要处理重定向,我们可以通过使用setInstanceFollowRedirects()方法为true或false启用或禁用特定连接的自动跟随重定向。con.setInstanceFollowRedirects(false);还可以为所有连接启用或禁用自动重定向。HttpUrlConnection.setFollowRedirects(false);默认情况下,启用此行为。当请求返回状态代码301或302时,表示重定向,我们可以检索Location标头并创建对新URL的新请求。如果(状态==HttpURLConnection.HTTP_MOVED_TEMP||状态==HttpURLConnection.HTTP_MOVED_PERM){字符串位置=con.getHeaderField(“位置”);URLnewUrl=新URL(location);con=(HttpURLConnection)newUrl.openConnection();}读取响应读取对请求的响应可以通过解析HttpUrlConnection实例的InputStream来完成。要执行请求,我们可以使用getResponseCode()、connect()、getInputStream()或getOutputStream()方法。intstatus=con.getResponseCode();最后,让我们读取请求的响应并将其放入内容字符串中。BufferedReaderin=newBufferedReader(newInputStreamReader(con.getInputStream()));StringinputLine;StringBuffercontent=newStringBuffer();while((inputLine=in.readLine())!=null){content.append(inputLine);}附寄();要关闭连接,我们可以使用disconnect()方法。con.disconnect();读取失败请求中的响应如果请求失败,我们无法从HttpUrlConnection实例的InputStream中读取数据。我们可以从HttpUrlConnection.getErrorStream()提供的流中读取。我们可以通过比较HTTP状态代码来决定使用哪个InputStream。intstatus=con.getResponseCode();ReaderstreamReader=null;if(status>299){streamReader=newInputStreamReader(con.getErrorStream());}else{streamReader=newInputStreamReader(con.getInputStream());}最后,我们可以像上一节一样读取streamReader。总结在本文中,我们展示了如何使用HttpUrlConnection类来执行HTTP请求。