HttpClientUntils工具類的使用及註意事項(包括我改進的工具類和Controller端的註意事項【附 Json 工具類】)
HttpClient工具類(我改過):
package com.taotao.httpclient; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; public class HttpClientUtil { //帶參數的get請求 public static String doGet(String url, Map<String, String> param) { // 創建Httpclient對象 CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString= ""; CloseableHttpResponse response = null; try { // 創建uri URIBuilder builder = new URIBuilder(url); if (param != null) { for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build(); // 創建http GET請求 HttpGet httpGet = new HttpGet(uri); //註意,如果請求這裏設置了 Accept 的 header,那麽 服務層的 Controller 中的Mapping上就可以不用 produces屬性 httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); // 執行請求 response = httpclient.execute(httpGet); // 判斷返回狀態是否為200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (response != null) { response.close(); } httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } //無參數的get請求 public static String doGet(String url) { return doGet(url, null); } //帶參數的post請求 public static String doPost(String url, Map<String, String> param) { // 創建Httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 創建Http Post請求 HttpPost httpPost = new HttpPost(url); //註意,如果請求這裏設置了 Accept 的 header,那麽 服務層的 Controller 中的Mapping上就可以不用 produces屬性 httpPost.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); // 創建參數列表 if (param != null) { List<NameValuePair> paramList = new ArrayList<>(); for (String key : param.keySet()) { paramList.add(new BasicNameValuePair(key, param.get(key))); } // 模擬表單(後面是轉碼,發送utf8格式的中文) StringEntity entity = new UrlEncodedFormEntity(paramList,"utf-8"); httpPost.setEntity(entity); } // 執行http請求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } //不帶參數的post請求 public static String doPost(String url) { return doPost(url, null); } //帶參數的post請求,參數是 json串 public static String doPostJson(String url, String json) { // 創建Httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 創建Http Post請求 HttpPost httpPost = new HttpPost(url); // 創建請求內容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 執行http請求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return resultString; } }
工具類的使用測試代碼:
package com.taotao.httpclient; import java.util.HashMap; import org.junit.Test; import com.taotao.common.utils.JsonUtils; public class HTTPClientUtilsTest { //不帶參數的get請求 @Test public void doGet(){ String url = "http://localhost:8083/search/doGet/哈哈"; String doGetResult = HttpClientUtil.doGet(url); System.out.println("======結果值:"+doGetResult); } //帶參數的get請求 @Test public void doGetWithParam(){ String url = "http://localhost:8083/search/doGetWithParam"; HashMap<String, String> paramMap = new HashMap<String,String>(); paramMap.put("username", "花千骨"); paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doGet(url,paramMap); System.out.println("======結果值:"+doGetResult); } //不帶參數的 post 請求 @Test public void doPost(){ String url = "http://localhost:8083/search/doPost/哈哈"; String doGetResult = HttpClientUtil.doPost(url); System.out.println("======結果值:"+doGetResult); } //帶參數的post請求 @Test public void doPostWithParam(){ String url = "http://localhost:8083/search/doPostWithParam"; HashMap<String, String> paramMap = new HashMap<String,String>(); paramMap.put("username", "花千骨"); paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doPost(url,paramMap); System.out.println("======結果值:"+doGetResult); } //帶參數的post請求,返回對象【這個請求到服務器端會報錯,不能返回正確的類型】 @Test //錯錯錯錯錯 不要像此方法這樣用 public void doPostWithParamReturnUser(){ String url = "http://localhost:8083/search/doPostWithParamReturnUser"; HashMap<String, String> paramMap = new HashMap<String,String>(); paramMap.put("username", "花千骨"); paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doPost(url,paramMap); System.out.println("======結果值:"+doGetResult); } //帶參數的post請求,一定要返回String類型 @Test public void doPostWithParamReturnUser2(){ String url = "http://localhost:8083/search/doPostWithParamReturnUser2"; HashMap<String, String> paramMap = new HashMap<String,String>(); paramMap.put("username", "花千骨"); paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doPost(url,paramMap); System.out.println("======結果值:"+doGetResult); } //帶參數的post請求,參數是json對象,返回User對象 @Test public void doPostWithJsonParam(){ String url = "http://localhost:8083/search/doPostWithJsonParam"; HashMap<String, String> paramMap = new HashMap<String,String>(); User user = new User(); user.setUsername("花千骨"); user.setPassword("123"); //把對象轉為json串 String objectToJson = JsonUtils.objectToJson(user); //調用發送json對象的post方法 String doGetResult = HttpClientUtil.doPostJson(url,objectToJson); //======結果值:{"username":"花千骨","passord":"123"} System.out.println("======結果值:"+doGetResult); } //帶參數的post請求,參數是json對象,返回 String 類型 @Test public void doPostWithJsonParam2(){ String url = "http://localhost:8083/search/doPostWithJsonParam2"; HashMap<String, String> paramMap = new HashMap<String,String>(); User user = new User(); user.setUsername("花千骨"); user.setPassword("123"); //把對象轉為json串 String objectToJson = JsonUtils.objectToJson(user); //調用發送json對象的post方法 String doGetResult = HttpClientUtil.doPostJson(url,objectToJson); //如果Controller中的RequestMapping上沒有加上 // produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8" //就會有這個亂碼返回值: ======結果值:{"username":"???","password":"123"} //正確返回值:======結果值:{"username":"花千骨","passord":"123"} System.out.println("======結果值:"+doGetResult); } }
對應的 SpringMVC Controller 層的代碼:
package com.taotao.search.controller; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.taotao.common.utils.JsonUtils; import com.taotao.search.testpojo.User; @Controller public class HttpClientUtilsController { //無參數的get請求 /** * 請求方法為:HttpClientUtil.doGet(url) */ @RequestMapping(value="/doGet/{pid}") @ResponseBody public String doGet(@PathVariable String pid){ System.out.println("============== "+pid); //這裏不會亂碼 哈哈 String username = "張三"; String password = "123"; String result = "username: "+username+"\tpassword: "+password; return result; } //帶參數的get請求響應 /** * 請求方法為:HttpClientUtil.doGet(url,paramMap) */ @RequestMapping(value="/doGetWithParam") @ResponseBody public String doGetWithParam(String username,String password) throws Exception{ //====== username: è?±???éa¨password: 123 System.out.println("====== username: "+username +"password: "+password); //為了避免亂碼我們需要轉碼(帶參數的 get 請求,必須在這裏轉碼) username = new String(username.getBytes("iso8859-1"), "utf-8"); password = new String(password.getBytes("iso8859-1"), "utf-8"); //===轉碼後=== username: 花千骨password: 123 System.out.println("===轉碼後=== username: "+username +"password: "+password); String result = "username: "+username+"\tpassword: "+password; return result; } //不帶參數的 post請求 /** * 請求方法為:HttpClientUtil.doPost(url) */ @RequestMapping(value="/doPost/{pid}") @ResponseBody public String doPost(@PathVariable String pid){ System.out.println("============== "+pid); //哈哈 String username = "張三"; String password = "123"; String result = "username: "+username+"\tpassword: "+password; return result; } //帶參數的 post 請求 /** * 請求方法為:HttpClientUtil.doPost(url,paramMap) */ @RequestMapping(value="/doPostWithParam") @ResponseBody public String doPost(String username,String password){ //====== username: 張三password: 123 System.out.println("====== username: "+username +"password: "+password); String result = "username: "+username+"\tpassword: "+password; return result; } //帶參數的post請求,用對象接收,並返回對象的json串 /** * 註意,如果請求端 和上面的 請求一樣,用的 HttpClientUtil.doPost(url,paramMap)方法, * 則下面這種寫法是會報錯的 */ @RequestMapping(value="/doPostWithParamReturnUser") @ResponseBody public User doPostReturnUser(User user){ System.out.println("===u=== "+user); return user; //錯錯錯錯錯 } //帶參數的 post請求,用對象接收 /** * 請求方法為:HttpClientUtil.doPost(url,paramMap)) * 註意:用上面的方法發來的請求,在Controller這裏只能返回String類型, * 如果返回 User對象(即:doPostReturnUser的寫法)是會報錯的 */ @RequestMapping(value="/doPostWithParamReturnUser2") @ResponseBody public String doPostReturnUser2(User user){ System.out.println("===u=== "+user); //將user對象轉為json串 String result = JsonUtils.objectToJson(user); return result; } //帶參數的post請求,參數是個json對象 /** * 請求方法為:HttpClientUtil.doPostJson(url,objectToJson) */ @RequestMapping(value="/doPostWithJsonParam") @ResponseBody public User doPostWithJsonParam(@RequestBody User user){ System.out.println("===u=== "+user); return user; } //帶參數的post請求,參數是個json對象 /** * 註意:請求此方法的httpClient調用的是如下方法 * HttpClientUtil.doPostJson(url,objectToJson) * 這時,如果在Controller這裏方法的返回值不是User對象而是String類型 * 那麽必須在RequestMapping上加上 * produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8" * 否則調用者返回值中的中文會亂碼 * 而且,這種情況下,在請求方的HttpClientUtil.doPostJson方法中是不能設置 Accept的Header的 * 否則 用同樣的方法調用上面的 doPostWithJsonParam 時就會報錯,找不到匹配的返回值類型 */ @RequestMapping(value="/doPostWithJsonParam2", produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8") @ResponseBody public String doPostWithJsonParam2(@RequestBody User user){ System.out.println("===u=== "+user); //將user對象轉為json串 String result = JsonUtils.objectToJson(user); return result; } }
總結:
主要需要註意的就是下面兩點(也就是上面代碼中的兩塊註釋):
1、//帶參數的 post請求,用對象接收
/**
* 請求方法為:HttpClientUtil.doPost(url,paramMap))
* 註意:用上面的方法發來的請求,在Controller這裏只能返回String類型,
* 如果返回 User對象(即:doPostReturnUser的寫法)是會報錯的
*/
2、 //帶參數的post請求,參數是個json對象
/**
* 註意:請求此方法的httpClient調用的是如下方法
* HttpClientUtil.doPostJson(url,objectToJson)
* 這時,如果在Controller這裏方法的返回值不是User對象而是String類型
* 那麽必須在RequestMapping上加上
* produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"
* 否則調用者返回值中的中文會亂碼
* 而且,這種情況下,在請求方的HttpClientUtil.doPostJson方法中是不能設置 Accept的Header的
* 否則 用同樣的方法調用上面的 doPostWithJsonParam 時就會報錯,找不到匹配的返回值類型
*/
其他附件代碼:
只要保證 發送端 和 服務端 有同樣的 User 對象即可:
package com.taotao.search.testpojo; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [username=" + username + ", password=" + password + "]"; } }
代碼中用到的 Json 工具類:
package com.taotao.common.utils; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonUtils { // 定義jackson對象 private static final ObjectMapper MAPPER = new ObjectMapper(); /** * 將對象轉換成json字符串。 * <p>Title: pojoToJson</p> * <p>Description: </p> * @param data * @return */ public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } /** * 將json結果集轉化為對象 * * @param jsonData json數據 * @param clazz 對象中的object類型 * @return */ public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 將json數據轉換成pojo對象list * <p>Title: jsonToList</p> * <p>Description: </p> * @param jsonData * @param beanType * @return */ public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); try { List<T> list = MAPPER.readValue(jsonData, javaType); return list; } catch (Exception e) { e.printStackTrace(); } return null; } }
HttpClientUntils工具類的使用及註意事項(包括我改進的工具類和Controller端的註意事項【附 Json 工具類】)