近期在对接项目时用到http方式与第三方交互数据,由于中间沟通不足导致走了不少弯路,至此特意花了点时间总结服务端与客户端数据交互的方式,本地搭建两个项目一个作为服务端,一个作为客户端。post可以有两种方式:一种与get一样,将请求参数拼接在url后面,这种服务端就以request.getParameter获取内容;另一种以流的方式写入到http链接中,服务端再从流中读取数据,在HttpURlConnection中分别用到了GET、POST请求方式,HttpClient以及commons-httpClient均以POST请求为例。
服务端代码:
package com.lutongnet.server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class Server_ccy */ @WebServlet("/Server_ccy") public class Server_ccy extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public Server_ccy() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setContentType("text/html;charset=utf-8"); request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); System.out.println("server-------doGet..start."); String name = request.getParameter("name"); String password = request.getParameter("password"); System.out.println("server-------params:"+name+":"+password); System.out.println("server-------doGet..end."); PrintWriter out = response.getWriter(); out.print("{\"姓名\":\"陈昌圆\"}"); out.flush(); out.close(); //response.getWriter().append("server_get_info:").append("Served at: ").append(request.getContextPath()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //doGet(request, response); response.setContentType("application/json;charset=utf-8"); request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); System.out.println("server-------doPost..start."); System.out.println("ContentType---->"+response.getContentType()); System.out.println("queryString---->"+request.getQueryString()); String name = request.getParameter("name"); System.out.println("name---->"+name); //String password = request.getParameter("password"); //System.out.println("server-------params:"+name+":"+password); StringBuffer sb = new StringBuffer(""); String str; BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream())); if((str = br.readLine()) != null){ sb.append(str); } System.out.println("从客户端获取的参数:"+sb); System.out.println("server-------doPost..end."); PrintWriter out = response.getWriter(); out.print("{\"姓名\":\"陈昌圆\"}"); out.flush(); out.close(); } }
客户端代码:
1.HttpURLConnection:主要详细分析GET与POST两种请求方式,我们项目中的api就是用的这种
package com.lutongnet.HttpURLConnection; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; public class HttpURLConnectionTest { public static void main(String[] args) { String url = "http://localhost:7373/ccy_server/ccy"; //String params = "name=ccy&password=123"; String params = "{\"name\":\"陈昌圆\",\"password\":\"123\"}"; try { String result = httpGetOrPost("POST", url, params); System.out.println("client---result:"+result); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static String httpGetOrPost(String type, String url, String params) throws Exception{ //get请求通过url传参(post可以通过url传参也可以将参数写在http正文传参) if("GET".equals(type)){ if(url.contains("?")){ url += "&" + params; }else{ url += "?" + params; } } System.out.println("请求地址:" + url); System.out.println("请求参数:" + params); URL u = new URL(url); /* * 查看URL API 发现 openConnection方法返回为URLConnection * HttpURLConnection为URLConnection的子类,有其更多的实现方法, * 通常将其转型为HttpURLConnection * */ HttpURLConnection httpConn = (HttpURLConnection) u.openConnection(); //设置请求方式 默认是GET httpConn.setRequestMethod(type); //写 默认均为false,GET不需要向HttpURLConnection进行写操作 if("POST".equals(type)){ httpConn.setDoOutput(true); } httpConn.setDoInput(true);//读 默认均为true,HttpURLConnection主要是用来获取服务器端数据 肯定要能读 httpConn.setAllowUserInteraction(true);//设置是否允许用户交互 默认为false httpConn.setUseCaches(false);//设置是否缓存 httpConn.setConnectTimeout(5000);//设置连接超时时间 单位毫秒 ms httpConn.setReadTimeout(5000);//设置访问超时时间 //setRequestProperty主要设置http请求头里面的相关属性 httpConn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31"); httpConn.setRequestProperty("accept", "*/*"); httpConn.setRequestProperty("Content-Type", "application/json"); //开启连接 httpConn.connect(); //post方式在建立连接后把头文件内容从连接的输出流中写入 if("POST".equals(type)){ //在调用getInputStream()方法中会检查连接是否已经建立,如果没有建立,则会调用connect() OutputStreamWriter out = new OutputStreamWriter(httpConn.getOutputStream(), "utf-8"); out.write(params);//将数据写入缓冲流 out.flush();//将缓冲区数据发送到接收方 out.close(); } System.out.println("httpcode:"+httpConn.getResponseCode()); //读取响应,现在开始可以读取服务器反馈的数据 BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "utf-8")); StringBuffer sb = new StringBuffer(""); String str; while((str = br.readLine()) != null){ sb.append(str); } System.out.println(new Date()+"---响应:"+sb); br.close(); httpConn.disconnect(); return sb.toString(); } }
get请求运行结果
客户端:
服务端:
post请求运行结果
客户端:
服务端:
2.DefaultHttpClient:需要导入三个包,httpclient-4.1.jar,httpcode-4.1.jar,commons-logging-1.1.1.jar,doPost方法是直接可以请求https,doPost2为的http方式,日后若有需要对接第三方接口需要https协议可以参考doPost方法
package com.lutongnet.HttpClient; import java.security.cert.CertificateException; public class HttpClientDemo { public static void main(String[] args) { HttpClientDemo hct = new HttpClientDemo(); String url = "http://localhost:7373/ccy_server/ccy"; Map<String, String> map = new HashMap<String, String>(); map.put("name", "ccy"); map.put("password", "123"); String charset = "utf-8"; String result = hct.doPost(url, map, charset); System.out.println("1.获取服务器端数据为:"+result); String params = "{\"name\":\"陈昌圆\",\"password\":\"123\"}"; String result2 = hct.doPost2(url, params); System.out.println("2.获取服务器端数据为:"+result2); } public String doPost2(String url, String content) { System.out.println("请求地址:" + url); System.out.println("请求参数:" + content); String charsetName = "utf-8"; DefaultHttpClient httpclient = null; HttpPost post = null; try { httpclient = new DefaultHttpClient(); post = new HttpPost(url); post.setHeader("Content-Type", "application/json;charset=" + charsetName); post.setEntity(new StringEntity(content, charsetName)); HttpResponse response = httpclient.execute(post); HttpEntity entity = response.getEntity(); String rsp = EntityUtils.toString(entity, charsetName); System.out.println("返回参数: "+rsp); return rsp; } catch (Exception e) { throw new RuntimeException(e); } finally { try { httpclient.getConnectionManager().shutdown(); } catch (Exception ignore) {} } } public String doPost(String url,Map<String,String> map,String charset){ HttpClient httpClient = null; HttpPost httpPost = null; String result = null; try{ httpClient = new SSLClient(); httpPost = new HttpPost(url); //设置参数 List<NameValuePair> list = new ArrayList<NameValuePair>(); Iterator iterator = map.entrySet().iterator(); while(iterator.hasNext()){ Entry<String,String> elem = (Entry<String, String>) iterator.next(); list.add(new BasicNameValuePair(elem.getKey(),elem.getValue())); } if(list.size() > 0){ UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset); httpPost.setEntity(entity); } HttpResponse response = httpClient.execute(httpPost); if(response != null){ HttpEntity resEntity = response.getEntity(); if(resEntity != null){ result = EntityUtils.toString(resEntity,charset); } } }catch(Exception ex){ ex.printStackTrace(); } return result; } class SSLClient extends DefaultHttpClient{ public SSLClient() throws Exception{ super(); SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; ctx.init(null, new TrustManager[]{tm}, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = this.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", 443, (SchemeSocketFactory) ssf)); } } }
post请求运行结果
客户端:
服务端:
3.commons-httpclient:需要导入两个包,commons-httpclient-3.0.jar,commons-codec-1.7.jar,这种方式是最简洁的,前后不到10行代码就解决了,不过需要注意的是设置正文编码,5种方式都可行,这种将参数拼接在http正文中,在服务端可以利用request.getParameter()方法获取参数,也可以用request.getInputStream()流的方式获取参数(这种方式如果参数中有中文的话,暂时没有找到解决乱码的方法)
package com.lutongnet.commonHttpclient; import java.util.ArrayList; import java.util.List; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.params.HttpMethodParams; public class CommonHttpClient { public static void main(String[] args) { String url = "http://localhost:7373/ccy_server/ccy"; List<String> params = new ArrayList<String>(); params.add("陳昌圓"); params.add("123"); CommonHttpClient chc = new CommonHttpClient(); String result = chc.getPostMethod(url, params); System.out.println("commonHttpClient---->从服务端获取的数据:" + result); } private String getPostMethod(String url, List<String> params) { String result = null; HttpClient httpClient = new HttpClient(); PostMethod postMethod = new PostMethod(url); //httpClient.getParams().setContentCharset("utf-8"); //httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8"); //postMethod.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8"); //postMethod.addRequestHeader("Content-Type", PostMethod.FORM_URL_ENCODED_CONTENT_TYPE // + "; charset=utf-8"); postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8"); postMethod.addParameter("name", params.get(0)); postMethod.addParameter("password", params.get(1)); try { httpClient.executeMethod(postMethod); result = postMethod.getResponseBodyAsString(); System.out.println("result:" + result); } catch (Exception e) { e.printStackTrace(); } return result; } /*class ccyPostMethod extends PostMethod { public ccyPostMethod(String url) { super(url); } @Override public String getRequestCharSet() { return "utf-8"; } }*/ }
post请求运行结果
客户端:
服务端: