如果想透彻了解什么是REST,这里有Roy Fielding博士最原始的文档:http://yun.baidu.com/share/link?shareid=3150451374&uk=170352852;
用到的主要工具包:
1.Apache httpclient 4.4.1 网址:http://hc.apache.org/
2.jackson-annotations-2.5.0,jackson-core-2.5.0,jackson-databind-2.5.0 网址:http://wiki.fasterxml.com/JacksonDownload
首先来个流程图,便于理解整个功能实现
1.JAVA客户端:
1.1 主函数文件
这是客户端的主函数文件,try...catch{}语句分别调用四种HTTP方法,需要注意的是各个方法是否幂等,GET,PUT,DELETE方法是幂等的,但是POST不是,
所以有的时候不能图省事就只用POST或者其他方法也用POST。
Invoker.java
1 package superman.jackson.qianzhilan; 2 import org.json.JSONObject; 3 import entity.jackson.qianzhilan.Student; 4 5 public class Invoker { 6 7 /* the address of services */ 8 private static String HOST="http://ip address"; 9 private static String BAREHOST="ip address"; 10 private static String SERVICE_ADD="/wcf/MyService.svc/stuRegister"; 11 private static String SERVICE_SELECT="/wcf/MyService.svc/SelStuInfo"; 12 private static String SERVICE_UPDATE="/wcf/MyService.svc/updStudent"; 13 private static String SERVICE_DELETE="/wcf/MyService.svc/delStudent"; 14 15 public static void main(String args[]) 16 { 17 String result=""; 18 WebClient client=new WebClient(); 19 JSONObject json = new JSONObject(); 20 21 /** 22 * HttpClient Put method 23 * 24 */ 25 try { 26 27 Student stu = new Student(); 28 stu.setS_id(90010); 29 stu.setSname("90010"); 30 stu.setBirthplace(""); 31 stu.setEducation(""); 32 stu.setE_mail(""); 33 stu.setId_card_no(""); 34 stu.setPwd(""); 35 stu.setSalary(0); 36 stu.setSex(""); 37 stu.setWork_place(""); 38 39 result = client.doInsert(HOST+SERVICE_ADD, stu,"application/json"); 40 41 } catch (Exception e) { 42 // TODO Auto-generated catch block 43 e.printStackTrace(); 44 } 45 46 /** 47 * HttpClient GET method 48 * input params:id 49 * out params:DataTable 50 */ 51 try { 52 int s_id=90015; 53 String reString; 54 reString= client.doSelect(BAREHOST,SERVICE_SELECT,s_id); 55 56 if(reString==null) 57 System.err.println("select failure!"); 58 59 } catch (Exception e) { 60 // TODO: handle exception 61 e.printStackTrace(); 62 } 63 64 65 66 /** 67 * HttpClient POST (update) method 68 * 69 */ 70 71 try { 72 73 Student stu = new Student(); 74 stu.setS_id(90015); 75 stu.setSname("90015"); 76 stu.setBirthplace("山东省"); 77 stu.setEducation("本科"); 78 stu.setE_mail("[email protected]"); 79 stu.setId_card_no(""); 80 stu.setPwd(""); 81 stu.setSalary(10000); 82 stu.setSex("男"); 83 stu.setWork_place(""); 84 85 result = client.doUpdate(HOST+SERVICE_UPDATE, stu,"application/json"); 86 87 } catch (Exception e) { 88 // TODO Auto-generated catch block 89 e.printStackTrace(); 90 } 91 92 /** 93 * HttpClient Delete method 94 * 95 */ 96 97 try { 98 99 100 client.doDelete(BAREHOST,SERVICE_DELETE,103); 101 102 103 } catch (Exception e) { 104 // TODO Auto-generated catch block 105 e.printStackTrace(); 106 } 107 } 108 109 110 }
1.2 调用函数实现文件
要特别注意doSelect和doDelete方法与其他两个方法实现的不同,好像HTTP1.1并不推荐在消息中携带body,因此只有在Uri添加比较简单的参数。
之前看到网上有些人是重写了自己的HttpGet和HttpDelete方法实现其携带body的方法,但是这不符合HTTP1.1的规范。
WebClient.java
1 package superman.jackson.qianzhilan; 2 3 import java.io.IOException; 4 import java.net.HttpURLConnection; 5 import java.net.URI; 6 7 import org.apache.http.HttpResponse; 8 import org.apache.http.client.ClientProtocolException; 9 import org.apache.http.client.HttpClient; 10 import org.apache.http.client.methods.HttpDelete; 11 import org.apache.http.client.methods.HttpGet; 12 13 import org.apache.http.client.methods.HttpPost; 14 import org.apache.http.client.methods.HttpPut; 15 import org.apache.http.client.utils.URIBuilder; 16 import org.apache.http.entity.StringEntity; 17 import org.apache.http.impl.client.HttpClients; 18 import org.apache.http.util.EntityUtils; 19 20 import org.json.JSONStringer; 21 22 23 import com.fasterxml.jackson.databind.ObjectMapper; 24 25 import entity.jackson.qianzhilan.Student; 26 27 public class WebClient { 28 29 public WebClient() { 30 31 } 32 33 /** 34 * @param url 35 * @param Student 36 * @param contentType 37 * @return json string 38 */ 39 public String doInsert(String url, Student stu, String contentType) { 40 41 String strResp = ""; 42 HttpPut request = new HttpPut(url); 43 request.setHeader("Accept", contentType); 44 request.setHeader("Content-type", contentType); 45 46 /* method one:user org.json jar to generate the data of json format */ 47 JSONStringer jStr; 48 /* method one:user jackson jars to generate the data of json format */ 49 String jsonStr; 50 ObjectMapper mapper=new ObjectMapper(); 51 try { 52 53 /* method one:user org.json jar to generate the data of json format */ 54 // jStr = (JSONStringer)(new JSONStringer() 55 // .object().key("stu") 56 // .object() 57 // .key("s_id").value(stu.getS_id()) 58 // .key("sname").value(stu.getSname()) 59 // .key("sex").value(stu.getSex()) 60 // .key("id_card_no").value(stu.getId_card_no()) 61 // .key("education").value(stu.getEducation()) 62 // .key("work_place").value(stu.getWork_place()) 63 // .key("salary").value(stu.getSalary()) 64 // .key("birthplace").value(stu.getBirthplace()) 65 // .key("pwd").value(stu.getPwd()) 66 // .key("e_mail").value(stu.getE_mail()) 67 // .endObject() 68 // .endObject()); 69 70 jsonStr=mapper.writeValueAsString(stu); 71 StringEntity entity = new StringEntity(jsonStr); 72 request.setEntity(entity); 73 System.out.printf("send the content:"+jsonStr+"\n"); 74 // create the httpclient 75 HttpClient httpClient = HttpClients.createDefault(); 76 77 // httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,30000); 78 HttpResponse response = httpClient.execute(request); 79 // judge the response status 80 if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) 81 { 82 String tmpString; 83 tmpString = EntityUtils.toString(response.getEntity()); 84 System.out.println("the result:"+tmpString ); 85 } 86 87 System.out.printf("server reply: " 88 +response.getEntity().getContent()+ 89 response.getFirstHeader("Content-type")+ 90 response.getStatusLine().toString()+"\n"); 91 } catch (Exception e) { 92 // TODO Auto-generated catch block 93 e.printStackTrace(); 94 } 95 96 // Reload plate numbers 97 98 return strResp; 99 100 } 101 public String doSelect(String host,String servUri,int s_id) throws Exception { 102 103 String strResp=null; 104 // JSONObject json = new JSONObject(); 105 // json.put("s_id", s_id); 106 URI uri = new URIBuilder() 107 .setScheme("http") 108 .setHost(host) 109 .setPath(servUri) 110 .setParameter("s_id", String.valueOf(s_id)) 111 .build(); 112 HttpGet httpGet = new HttpGet(uri); 113 // StringEntity entity = new StringEntity(json.toString(),"UTF-8"); 114 // entity.setContentType(contentType); 115 116 // httpGet.setEntity(entity); 117 HttpClient client2 = HttpClients.createDefault(); 118 HttpResponse resp; 119 try { 120 resp = client2.execute(httpGet); 121 122 if (resp.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) 123 { 124 strResp = EntityUtils.toString(resp.getEntity()); 125 System.out.println("the select result:"+strResp); 126 127 } else System.out.println("Error select Response:" 128 + resp.getStatusLine().toString()); 129 } catch (ClientProtocolException e) { 130 // TODO Auto-generated catch block 131 e.printStackTrace(); 132 } catch (IOException e) { 133 // TODO Auto-generated catch block 134 e.printStackTrace(); 135 } 136 137 return strResp; 138 } 139 public String doUpdate(String url,Student stu,String contentType) 140 { 141 142 String tmpString=null; 143 HttpPost request=new HttpPost(url); 144 request.setHeader("Accept", contentType); 145 request.setHeader("Content-type", contentType); 146 147 ObjectMapper mapper=new ObjectMapper(); 148 String jsonString; 149 150 try { 151 jsonString=mapper.writeValueAsString(stu); 152 StringEntity entity=new StringEntity(jsonString,"UTF-8"); 153 request.setEntity(entity); 154 155 HttpClient client=HttpClients.createDefault(); 156 HttpResponse response=client.execute(request); 157 // judge the response status 158 if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) 159 { 160 tmpString= EntityUtils.toString(response.getEntity()); 161 System.out.println("the update result:"+tmpString); 162 } else System.out.println("the update failure"); 163 } catch (ClientProtocolException e) { 164 // TODO Auto-generated catch block 165 e.printStackTrace(); 166 } catch (IOException e) { 167 // TODO Auto-generated catch block 168 e.printStackTrace(); 169 } 170 return tmpString; 171 } 172 173 public String doDelete(String host,String servUri,int s_id) throws Exception { 174 // JSONStringer jStr; 175 // jStr = (JSONStringer)(new JSONStringer() 176 // .object().key("s_id").value(90012) 177 // .endObject()); 178 String tmpString=null; 179 // HttpPost request=new HttpPost(url); 180 // request.setHeader("Accept", contentType); 181 // request.setHeader("Content-type", contentType); 182 HttpDelete delete=new HttpDelete(); 183 // 184 try { 185 186 // System.out.println(jStr.toString()); 187 // StringEntity entity=new StringEntity(jStr.toString()); 188 // entity.setContentType(contentType); 189 // request.setEntity(entity); 190 // /* method of delete */ 191 URI uri = new URIBuilder() 192 .setScheme("http") 193 .setHost(host) 194 .setPath(servUri) 195 .setParameter("s_id",s_id) 196 .build(); 197 delete.setURI(uri); 198 HttpClient client=HttpClients.createDefault(); 199 HttpResponse response=client.execute(delete); 200 // judge the response status 201 if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) 202 { 203 tmpString= EntityUtils.toString(response.getEntity()); 204 System.out.println("the delete result:" + tmpString); 205 } else System.out.println("the delete failure"+response.getStatusLine().toString()); 206 } catch (ClientProtocolException e) { 207 // TODO Auto-generated catch block 208 e.printStackTrace(); 209 } catch (IOException e) { 210 // TODO Auto-generated catch block 211 e.printStackTrace(); 212 } 213 return tmpString; 214 } 215 216 }
2.服务器端 [ Rest WCF ]
2.1 配置文件
Web.config
1 xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 4 <appSettings> 5 <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 6 appSettings> 7 <system.web> 8 <compilation debug="true" targetFramework="4.5" /> 9 <httpRuntime targetFramework="4.5"/> 10 system.web> 11 12 <system.serviceModel> 13 <behaviors> 14 <serviceBehaviors> 15 <behavior> 16 17 <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 18 19 <serviceDebug includeExceptionDetailInFaults="true"/> 20 21 behavior> 22 serviceBehaviors> 23 24 <endpointBehaviors> 25 <behavior name="json"> 26 <webHttp helpEnabled="true" /> 27 behavior> 28 endpointBehaviors> 29 behaviors> 30 <protocolMapping> 31 <add binding="basicHttpsBinding" scheme="https" /> 32 protocolMapping> 33 34 <services> 35 <service name="SuperWCF.MyService"> 36 <endpoint address="" binding="webHttpBinding" contract="SuperWCF.IHello" behaviorConfiguration="json"> 37 38 endpoint> 39 40 <endpoint address="localhost" binding="basicHttpBinding" contract="SuperWCF.IHello" /> 41 service> 42 services> 43 44 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 45 46 system.serviceModel> 47 <system.webServer> 48 <modules runAllManagedModulesForAllRequests="true"> 49 53 <remove name="WebDAVModule" /> 54 modules> 55 <handlers> 56 <remove name="WebDAV" /> 57 handlers> 58 <directoryBrowse enabled="true"/> 59 system.webServer> 60 61 configuration>
注意:
(1)34-42行的代码的总结点的配置,从中可以看出其中有两个总结点,line36:是配置http调用服务的终结点,line42是提供win form调用的终结点。
(2)system.webServer节点的配置,这将允许你调用wcf服务提供的DELETE方法。如果你发现了调用后的status code为 405,估计这个时候你就需要它了
2.2 接口文件
IHello.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Serialization; 5 using System.ServiceModel; 6 using System.ServiceModel.Web; 7 using System.Text; 8 using System.Data; 9 using Npgsql; 10 using NpgsqlTypes; 11 12 namespace SuperWCF 13 { 14 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。 15 [DataContract] 16 public class Student 17 { 18 [DataMember(Name = "s_id")] 19 public int s_id { get; set; } 20 [DataMember(Name="sname")] 21 public string sname { get; set; } 22 [DataMember(Name="sex")] 23 public string sex { get; set; } 24 [DataMember(Name="id_card_no")] 25 public string id_card_no { get; set; } 26 [DataMember(Name = "education")] 27 public string education { get; set; } 28 [DataMember(Name = "work_place")] 29 public string work_place { get; set; } 30 [DataMember(Name = "salary")] 31 public int salary { get; set; } 32 33 [DataMember(Name = "birthplace")] 34 public string birthplace { get; set; } 35 [DataMember(Name = "pwd")] 36 public string pwd { get; set; } 37 [DataMember(Name = "e_mail")] 38 public string e_mail { get; set; } 39 40 }; 41 [ServiceContract] 42 public interface IHello 43 { 44 // TODO: 在此添加您的服务操作 45 [OperationContract] 46 [WebInvoke( 47 Method="PUT", 48 BodyStyle = WebMessageBodyStyle.Bare, 49 ResponseFormat = WebMessageFormat.Json, 50 RequestFormat = WebMessageFormat.Json)] 51 String stuRegister(Student stu); 52 53 [OperationContract] 54 [WebInvoke( 55 Method="GET", 56 BodyStyle = WebMessageBodyStyle.Bare, 57 ResponseFormat = WebMessageFormat.Json)] 58 DataSet SelStuInfo(string s_id); 59 60 [OperationContract] 61 [WebInvoke( 62 Method = "POST", 63 BodyStyle = WebMessageBodyStyle.Bare, 64 ResponseFormat = WebMessageFormat.Json, 65 RequestFormat = WebMessageFormat.Json)] 66 int updStudent(Student stu); 67 [OperationContract] 68 [WebInvoke( 69 Method = "DELETE",UriTemplate = "/delStudent?s_id={s_id}", 70 BodyStyle = WebMessageBodyStyle.Bare, 71 RequestFormat = WebMessageFormat.Json)] 72 int delStudent(string s_id); 73 74 } 75 }
2.3 服务接口实现
MyService.svc.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Serialization; 5 using System.ServiceModel; 6 using System.ServiceModel.Web; 7 using System.Text; 8 using System.Data; 9 using Npgsql; 10 using NpgsqlTypes; 11 12 namespace SuperWCF 13 { 14 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。 15 // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。 16 17 18 public class MyService : IHello 19 { 20 const string constr = "host=localhost;port=1991;uid=postgres;pwd=database password;database=database name;"; 21 public String stuRegister(Student stu) 22 { 23 string sql = "insert into \"InfoSystem\".\"Student\"(s_id,sname, sex, id_card_no, education, work_place, salary,brithplace,pwd,email) values(@s_id,@sname,@sex,@id_card_no,@education,@work_place,@salary,@birthplace,md5(@pwd),@email)"; 24 25 NpgsqlConnection mycon = new NpgsqlConnection(constr); 26 mycon.Open(); 27 NpgsqlCommand myad = new NpgsqlCommand(sql, mycon); 28 myad.Parameters.Add("@s_id", NpgsqlDbType.Integer).Value = stu.s_id; 29 myad.Parameters.Add("@sname", NpgsqlDbType.Char, 20).Value = stu.sname; 30 myad.Parameters.Add("@sex", NpgsqlDbType.Char, 1).Value = stu.sex; 31 myad.Parameters.Add("@id_card_no", NpgsqlDbType.Char, 100).Value = stu.id_card_no; 32 myad.Parameters.Add("@education", NpgsqlDbType.Char, 10).Value = stu.education; 33 myad.Parameters.Add("@work_place", NpgsqlDbType.Char, 40).Value = stu.work_place; 34 myad.Parameters.Add("@salary", NpgsqlDbType.Integer).Value = stu.salary; 35 myad.Parameters.Add("@birthplace", NpgsqlDbType.Char, 50).Value = stu.birthplace; 36 myad.Parameters.Add("@pwd", NpgsqlDbType.Char, 100).Value = stu.pwd; 37 myad.Parameters.Add("@email", NpgsqlDbType.Char, 50).Value = stu.e_mail; 38 39 if (myad.ExecuteNonQuery() > 0) 40 { 41 mycon.Close(); 42 return "true"; 43 44 } 45 else 46 { 47 mycon.Close(); 48 return "false"; 49 } 50 51 } 52 53 54 public DataSet SelStuInfo(String s_id) 55 { 56 string sql = "select * from \"InfoSystem\".\"Student\" where s_id=@s_id"; 57 DataSet dt = new DataSet(); 58 59 NpgsqlConnection mycon = new NpgsqlConnection(constr); 60 61 mycon.Open(); 62 NpgsqlDataAdapter myad = new NpgsqlDataAdapter(sql, mycon); 63 myad.SelectCommand.Parameters.Add("@s_id", NpgsqlDbType.Integer).Value = s_id; 64 myad.Fill(dt); 65 return dt; 66 } 67 public int updStudent(Student stu) 68 { 69 string sql = "UPDATE \"InfoSystem\".\"Student\" SET sname=@sname,sex=@sex,id_card_no=@id_card_no,education=@education,work_place=@work_place,salary=@salary,brithplace=@brithplace,email=@email where s_id=@s_id"; 70 71 NpgsqlConnection mycon = new NpgsqlConnection(constr); 72 mycon.Open(); 73 NpgsqlCommand myad = new NpgsqlCommand(sql, mycon); 74 75 myad.Parameters.Add("@sname", NpgsqlDbType.Char, 20).Value = stu.sname; 76 myad.Parameters.Add("@sex", NpgsqlDbType.Char, 1).Value = stu.sex; 77 myad.Parameters.Add("@id_card_no", NpgsqlDbType.Char, 18).Value = stu.id_card_no; 78 myad.Parameters.Add("@education", NpgsqlDbType.Char, 10).Value = stu.education; 79 myad.Parameters.Add("@work_place", NpgsqlDbType.Char, 40).Value = stu.work_place; 80 myad.Parameters.Add("@salary", NpgsqlDbType.Integer).Value = stu.salary; 81 myad.Parameters.Add("@brithplace", NpgsqlDbType.Char, 50).Value = stu.birthplace; 82 myad.Parameters.Add("@email", NpgsqlDbType.Char, 50).Value = stu.e_mail; 83 myad.Parameters.Add("@s_id", NpgsqlDbType.Integer).Value = stu.s_id; 84 85 int res = myad.ExecuteNonQuery(); 86 if (res > 0) 87 { 88 mycon.Close(); 89 return 1; 90 91 } 92 else 93 { 94 mycon.Close(); 95 return 0; 96 } 97 } 98 public int delStudent(string s_id) 99 { 100 string sql = "delete from \"InfoSystem\".\"Student\" where s_id=@s_id"; 101 102 NpgsqlConnection mycon = new NpgsqlConnection(constr); 103 mycon.Open(); 104 NpgsqlCommand myad = new NpgsqlCommand(sql, mycon); 105 myad.Parameters.Add("@s_id", NpgsqlDbType.Integer).Value =Convert.ToInt32(s_id); 106 if (myad.ExecuteNonQuery() > 0) 107 { 108 mycon.Close(); 109 return 1; 110 111 } 112 else 113 { 114 mycon.Close(); 115 return 0; 116 } 117 118 } 119 } 120 }
有问题欢迎提问!