Salesforce新手指南:使用REST接口获取外部数据和Java调用Salesforce的REST API方法(第33期)
本篇参考Trail教程:
https://developer.salesforce.com/trailhead/force_com_dev_intermediate/apex_integration_services/apex_integration_rest_callouts
有的时候我们需要在salesforce中引入外部的方法或者数据,这样就需要访问外部的Services,目前常用的访问方式有两种:
1.SOAP方式:Web Service通过XML方式调用SOAP Web服务器;
2.REST方式:Http通过JSON使用REST方式调用服务器。
这两种Callouts使用原理类似,简单的可以理解像服务器发送一个请求,然后服务器返回一个响应。基于WSDL的callouts适用于SOAP方式,HTTP方式可以使用任何的HTTP service,SOAP或者REST都可以。
这两种方式能选择Http方式尽量选择Http方式。
下面来了解一下REST方式获取外部Service数据以及其他Service访问Salesforce数据操作。
一.REST方式获取外部Service数据
REST方式主要原理如下图所示。使用REST方式主要步骤如下:
salesforce通过REST方式访问外界站点步骤如下:
1.将Web Service的授权端点地址添加到Remote Site中:setup->Administer->Security Site Settings->Remote Site Settings。
salesforce提供了两个测试URL,将两个测试的URL添加到Remote Site中。两个URL分别为:
http:https://ap2.salesforce.com/0rp28000000TSqv
soap:https://ap2.salesforce.com/0rp28000000TSr0
2.代码进行访问
通过HTTP方式可以使用以下方法进行相关操作的访问
https://th-apex-http-callout.herokuapp.com/animals远程站点JSON内容如下{"animals":["majestic badger","fluffy bunny","scary bear","chicken"]}在Eclipse中使用匿名块编写代码实现访问:window->show view->Other->Execute Anonymous即可打开匿名块。
GET方式获取数据:
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
request.setMethod('GET');
HttpResponse response = http.send(request);
// If the request is successful, parse the JSON response.
if (response.getStatusCode() == 200) {
// Deserialize the JSON string into collections of primitive data types.
Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
// Cast the values in the 'animals' key as a list
List<Object> animals = (List<Object>) results.get('animals');
System.debug('Received the following animals:');
for (Object animal: animals) {
System.debug(animal);
}
}
输出的结果如下:
其他方式自行测试。
二.Salesforce作为REST Service供java访问(可以供其它语言访问,这里只对java展示,因为我只会java)
有的时候我们需要在其他平台上获取sfdc端的数据,比如做android项目需要访问sfdc数据,那样就需要Salesforce作为Service,java端通过http获取并对数据进行相关操作。步骤如下:
1)新建一个App,然后创建Connected App:
setup->Build->Create->Apps.先new一个app,正常new完以后new一个Connected App,设置Enable OAuth Settings为true,截图如下所示:
java访问sfdc 的Service的时候需要用到Consumer Key以及Consumer Secret这两项。
2)sfdc端rest service构建:这里我们以Goods__c进行操作,主要方法有添加一条Goods,通过Id获取Goods,通过PageNumber获取指定条数开始的Goods数据,修改一条Goods以及删除一条Goods。
这里对常用的注解进行解释:
1.@RestResource:曝光此类作为REST资源;
2.@HttpGet:曝光方法作为REST资源,当有Http get请求发送时,此注解对应的方法会被执行;
3.@HttpPost:Http post 请求发送时,此注解对应的方法会被执行;
4.@HttpDelete:当有Http delete请求发送时,此注解对应的方法会被执行;
5.@HttpPut:当有Http put请求发送时,此注解对应的方法会被执行;
6.@HttpPatch:当有Http patch请求发送时,此注解对应的方法会被执行。
因为http有请求时按照请求方式来对应相关方法,所以一个类中上述标签只能存在一个,即不能存在两个方法标注@HttpRequest等。
1 /*
2 * 使用salesforce通过REST方式作为webservice,需要以下几点:
3 * 1.类和方法需要global,方法需要静态
4 * 2.类需要通过RestResource(UrlMapping='/page/*')注解声明
5 * 3.@HttpGet和@HttpDelete不能有形参,可以通过URL?param或者URL/param方式传过来参数
6 */
7 @RestResource(UrlMapping='/Goods/*')
8 global class GoodsRESTController {
9 global static final Integer PAGE_SIZE = 20;
10 @HttpGet
11 global static List<Goods__c> getGoodsByIdOrGoodsList() {
12 RestRequest request = RestContext.request;
13 // grab the goodsId from the end of the URL
14 String currentPage = request.params.get('currentPage') != null ? request.params.get('currentPage') : '0';
15 Integer offsetNumber = Integer.valueOf(currentPage) * PAGE_SIZE;
16 String goodsId = request.params.get('goodsId');
17 String fetchSql;
18 if(goodsId != null) {
19 fetchSql = 'SELECT CreatedById, CreatedDate, IsDeleted, Name,' +
20 ' GoodsBrand__c, GoodsCostPrice__c, GoodsDescribe__c, GoodsName__c,' +
21 ' GoodsPrice__c, GoodsProfit__c, LastActivityDate, LastModifiedById,' +
22 ' LastModifiedDate, No__c, OwnerId, Id FROM Goods__c' +
23 ' where Id = :goodsId';
24 } else {
25 fetchSql = 'SELECT CreatedById, CreatedDate, IsDeleted, Name,' +
26 ' GoodsBrand__c, GoodsCostPrice__c, GoodsDescribe__c, GoodsName__c,' +
27 ' GoodsPrice__c, GoodsProfit__c, LastActivityDate, LastModifiedById,' +
28 ' LastModifiedDate, No__c, OwnerId, Id FROM Goods__c limit :PAGE_SIZE offset :offsetNumber';
29 }
30 List<Goods__c> goodsList = Database.query(fetchSql);
31 return goodsList;
32 }
33
34
35 @HttpPost
36 global static Id insertGoods(String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
37 System.debug('---------goodsName-------------' + goodsName);
38 Goods__c goods = new Goods__c();
39 if(goodsPrice != null && goodsPrice.isNumeric()) {
40 goods.GoodsPrice__c = Double.valueOf(goodsPrice);
41 }
42 if(goodsCostPrice != null && goodsCostPrice.isNumeric()) {
43 goods.GoodsCostPrice__c = Double.valueOf(goodsCostPrice);
44 }
45 goods.GoodsName__c = goodsName;
46 goods.GoodsDescribe__c = goodsDescribe;
47 insert goods;
48 return goods.Id;
49 }
50
51 @HttpDelete
52 global static void deleteGoods() {
53 RestRequest request = RestContext.request;
54 String goodsId = request.requestURI.substring(
55 request.requestURI.lastIndexOf('/')+1);
56 Goods__c needDeleteGoods = [select Id from Goods__c where Id = :goodsId];
57 if(needDeleteGoods != null) {
58 delete needDeleteGoods;
59 }
60 }
61
62 @HttpPut
63 global static ID upsertGoods(String id,String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
64 Goods__c goods = new Goods__c();
65 goods.Id = id;
66 goods.GoodsName__c = goodsName;
67 goods.GoodsBrand__c = goodsBrand;
68 goods.GoodsDescribe__c = goodsDescribe;
69 if(goodsPrice != null && goodsPrice.isNumeric()) {
70 goods.GoodsPrice__c = Double.valueOf(goodsPrice);
71 }
72 if(goodsCostPrice != null && goodsCostPrice.isNumeric()) {
73 goods.GoodsCostPrice__c = Double.valueOf(goodsCostPrice);
74 }
75 upsert goods;
76 return goods.Id;
77 }
78
79 @HttpPatch
80 global static ID updateGoods() {
81 RestRequest request = RestContext.request;
82 String goodsId = request.requestURI.substring(
83 request.requestURI.lastIndexOf('/')+1);
84 Goods__c goods = [select Id from Goods__c where Id= :goodsId];
85 // Deserialize the JSON string into name-value pairs
86 Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.tostring());
87 // Iterate through each parameter field and value
88 goods.GoodsName__c = String.valueOf(params.get('GoodsName__c'));
89 goods.GoodsPrice__c = Double.valueOf(params.get('GoodsPrice__c'));
90 goods.GoodsCostPrice__c = Double.valueOf(params.get('GoodsCostPrice__c'));
91 update goods;
92 return goods.Id;
93 }
94
95
96
97 }
测试自己写的方法可以在workbench中查看,使用salesforce账号登录workbench,https://workbench.developerforce.com/login.php.在这里可以测试一下getGoodsByIdOrGoodsList方法,想要测试其他方法可以参看最上面的链接自行测试。如下图所示:
3)java端访问sfdc的REST Service
java端访问sfdc的REST Service之前需要做两部分,第一部分是下载Http client的jar包,第二部分是下载json的jar包。
1.Http client jar包下载:访问http://hc.apache.org/downloads.cgi 选择最新的jar包进行下载,下载后解压,在lib目录下位所需要的http client的jar包。
2.下载json的jar包:http://mvnrepository.com/artifact/org.json/json。可以选择下载最新的json下载后将json的jar和http client的jar放在一个文件夹下,比如我们现在放在桌面的jars文件夹下。
接下来打开eclipse,jars目录下的jar包全都放在java项目里,然后开始代码访问阶段。
1
2 import java.io.IOException;
3 import java.util.ArrayList;
4 import java.util.List;
5 import org.apache.http.Header;
6 import org.apache.http.HttpResponse;
7 import org.apache.http.HttpStatus;
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 import org.apache.http.client.methods.HttpPost;
13 import org.apache.http.entity.StringEntity;
14 import org.apache.http.impl.client.HttpClientBuilder;
15 import org.apache.http.message.BasicHeader;
16 import org.apache.http.util.EntityUtils;
17 import org.json.JSONArray;
18 import org.json.JSONException;
19 import org.json.JSONObject;
20 import org.json.JSONTokener;
21
22 public class InvokeGoodsByRestViaSFDC {
23
24 static final String USERNAME = "你的salesforce账号";
25 static final String PASSWORD = "你的salesforce密码+security token(如果有security token)";
26 static final String LOGINURL = "https://login.salesforce.com";
27 static final String GRANTSERVICE = "/services/oauth2/token?grant_type=password";
28 static final String CLIENTID = "3MVG9ZL0ppGP5UrBiKUS3jtHfmfz4eBCBEnuY0tIDByXVdtBJWeY6olTn1iLDNvP68EmfVtWE3IDzHOsMuDww";//上图中Consumer Key
29 static final String CLIENTSECRET = "723866328398987848";//上图中的Consumer Secret
30 private static String REST_ENDPOINT = "/services/apexrest" ;
31 private static String baseUri;
32 private static Header oauthHeader;
33 private static Header prettyPrintHeader = new BasicHeader("X-PrettyPrint", "1");
34
35 /**
36 * 判断是否可以访问sfdc
37 * return:可以访问sfdc的rest则返回true,否则返回false
38 * */
39 private static boolean isAccessable() {
40 HttpClient httpclient = HttpClientBuilder.create().build();
41
42 // Assemble the login request URL
43 String loginURL = LOGINURL +
44 GRANTSERVICE +
45 "&client_id=" + CLIENTID +
46 "&client_secret=" + CLIENTSECRET +
47 "&username=" + USERNAME +
48 "&password=" + PASSWORD;
49
50 // Login requests must be POSTs
51 HttpPost httpPost = new HttpPost(loginURL);
52 HttpResponse response = null;
53 try {
54 // Execute the login POST request
55 response = httpclient.execute(httpPost);
56 } catch (ClientProtocolException cpException) {
57 cpException.printStackTrace();
58 } catch (IOException ioException) {
59 ioException.printStackTrace();
60 }
61 // verify response is HTTP OK
62 final int statusCode = response.getStatusLine().getStatusCode();
63 if (statusCode != HttpStatus.SC_OK) {
64 System.out.println("Error authenticating to Force.com: "+statusCode);
65 return false;
66 }
67
68 String getResult = null;
69 try {
70 getResult = EntityUtils.toString(response.getEntity());
71 } catch (IOException ioException) {
72 ioException.printStackTrace();
73 }
74
75 JSONObject jsonObject = null;
76 String loginAccessToken = null;
77 String loginInstanceUrl = null;
78
79 try {
80 jsonObject = (JSONObject) new JSONTokener(getResult).nextValue();
81 loginAccessToken = jsonObject.getString("access_token");
82 loginInstanceUrl = jsonObject.getString("instance_url");
83 } catch (JSONException jsonException) {
84 jsonException.printStackTrace();
85 }
86
87 baseUri = loginInstanceUrl + REST_ENDPOINT + "/Goods";
88 oauthHeader = new BasicHeader("Authorization", "OAuth " + loginAccessToken) ;
89 System.out.println("oauthHeader1: " + oauthHeader);
90 System.out.println(response.getStatusLine());
91 System.out.println("Successful login");
92 System.out.println("instance URL: "+loginInstanceUrl);
93 System.out.println("access token/session ID: "+loginAccessToken);
94 System.out.println("baseUri: "+ baseUri);
95 return true;
96 }
97
98
99 public static void main(String[] args) {
100 createGoods("小米4","小米","2500","2000","测试商品描述信息:小米");
101 //deleteGoods("a052800000880mlAAA");
102 Goods getGoods = getGoodsById("a0528000008811qAAA");
103 if(getGoods != null) {
104 System.out.println("goods Name :" + getGoods.getGoodsName());
105 System.out.println("goods Price : " + getGoods.getGoodsPrice());
106 System.out.println("goods cost price :" +getGoods.getGoodsCostPrice());
107 System.out.println("goods brand : " + getGoods.getGoodsBrand());
108 }
109 List<Goods> goodsList = getGoodsList(0);
110 System.out.println(goodsList.toString());
111
112 Goods updateGoods = new Goods();
113 updateGoods.setGoodsId("a0528000008811qAAA");
114 updateGoods.setGoodsName("test goods Name");
115 updateGoods.setGoodsPrice("10000");
116 updateGoods.setGoodsCostPrice("8000");
117 updateGoods(updateGoods);
118 }
119
120
121
122
123 // Create Goods using REST HttpPost
124 public static void createGoods(String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
125 try {
126 if(isAccessable()) {
127 String uri = baseUri + "/createGoods";
128 JSONObject goods = new JSONObject();
129 goods.put("goodsName", goodsName);
130 goods.put("goodsBrand", goodsBrand);
131 goods.put("goodsPrice", goodsPrice);
132 goods.put("goodsCostPrice",goodsCostPrice);
133 goods.put("goodsDescribe", goodsDescribe);
134
135 System.out.println("JSON for goods record to be inserted:\n" + goods.toString(1));
136 //Construct the objects needed for the request
137 HttpClient httpClient = HttpClientBuilder.create().build();
138 System.out.println("oauthHeader" + oauthHeader);
139 HttpPost httpPost = new HttpPost(uri);
140 httpPost.addHeader(oauthHeader);
141 httpPost.addHeader(prettyPrintHeader);
142 httpPost.addHeader("encoding", "UTF-8");
143 // The message we are going to post
144 StringEntity body = new StringEntity(goods.toString(1));
145 body.setContentType("application/json");
146 httpPost.setEntity(body);
147
148 //Make the request
149 HttpResponse response = httpClient.execute(httpPost);
150 System.out.print("response : " + response.toString());
151 //Process the results
152 int statusCode = response.getStatusLine().getStatusCode();
153 System.out.println("status code : " + statusCode);
154 if (statusCode == HttpStatus.SC_OK) {
155 String response_string = EntityUtils.toString(response.getEntity());
156 if(response_string != null ) {
157 System.out.println("New Goods id from response: " + response_string);
158 }
159 } else {
160 System.out.println("Insertion unsuccessful. Status code returned is " + statusCode);
161 }
162 httpPost.releaseConnection();
163 }
164 } catch (JSONException e) {
165 System.out.println("Issue creating JSON or processing results");
166 e.printStackTrace();
167 } catch (IOException ioe) {
168 ioe.printStackTrace();
169 } catch (NullPointerException npe) {
170 npe.printStackTrace();
171 }
172 }
173
174 public static void deleteGoods(String goodsId) {
175 try {
176 if(isAccessable()) {
177 String uri = baseUri + "/deleteGoods" + "/" + goodsId;
178 HttpClient httpClient = HttpClientBuilder.create().build();
179
180 HttpDelete httpDelete = new HttpDelete(uri);
181 httpDelete.addHeader(oauthHeader);
182 httpDelete.addHeader(prettyPrintHeader);
183
184 //Make the request
185 HttpResponse response = httpClient.execute(httpDelete);
186
187 //Process the response
188 int statusCode = response.getStatusLine().getStatusCode();
189 if (statusCode == HttpStatus.SC_OK) {
190 System.out.println("Deleted the goods successfully.");
191 } else {
192 System.out.println("goods delete NOT successful. Status code is " + statusCode);
193 }
194 httpDelete.releaseConnection();
195 }
196 } catch (JSONException e) {
197 System.out.println("Issue creating JSON or processing results");
198 e.printStackTrace();
199 } catch (IOException ioe) {
200 ioe.printStackTrace();
201 } catch (NullPointerException npe) {
202 npe.printStackTrace();
203 }
204 }
205
206 public static List<Goods> getGoodsList(Integer pageNumber) {
207 try {
208 if(isAccessable()) {
209 String uri = baseUri + "/getGoodsByIdOrGoodsList" + "?currentPage=" + pageNumber;
210 HttpClient httpClient = HttpClientBuilder.create().build();
211 HttpGet httpGet = new HttpGet(uri);
212 httpGet.addHeader(oauthHeader);
213 httpGet.addHeader(prettyPrintHeader);
214 //Make the request
215 HttpResponse response = httpClient.execute(httpGet);
216 //Process the response
217 int statusCode = response.getStatusLine().getStatusCode();
218 if (statusCode == HttpStatus.SC_OK) {
219 List<Goods> goodsList = new ArrayList<Goods>();
220 String response_string = EntityUtils.toString(response.getEntity());
221 System.out.println("response_string : " + response_string);
222 JSONArray jsonArray = new JSONArray(response_string);
223 JSONObject jsonObject = null;
224 for(int i=0;i<jsonArray.length();i++) {
225 jsonObject = jsonArray.getJSONObject(i);
226 Goods goods = new Goods();
227 if(jsonObject != null) {
228 goods.setGoodsName(jsonObject.getString("GoodsName__c"));
229 goods.setGoodsPrice(String.valueOf(jsonObject.getDouble("GoodsPrice__c")));
230 goods.setGoodsCostPrice(String.valueOf(jsonObject.getDouble("GoodsCostPrice__c")));
231 goods.setGoodsDescribe(jsonObject.getString("GoodsDescribe__c"));
232 goodsList.add(goods);
233 }
234 }
235 return goodsList;
236 } else {
237 return null;
238 }
239 }
240 }catch (JSONException e) {
241 System.out.println("Issue creating JSON or processing results");
242 e.printStackTrace();
243 } catch (IOException ioe) {
244 ioe.printStackTrace();
245 } catch (NullPointerException npe) {
246 npe.printStackTrace();
247 }
248 return null;
249 }
250
251 public static Goods getGoodsById(String goodsId) {
252 try {
253 if(isAccessable()) {
254 String uri = baseUri + "/getGoodsByIdOrGoodsList" + "?goodsId=" + goodsId;
255 HttpClient httpClient = HttpClientBuilder.create().build();
256
257 HttpGet httpGet = new HttpGet(uri);
258 httpGet.addHeader(oauthHeader);
259 httpGet.addHeader(prettyPrintHeader);
260
261 //Make the request
262 HttpResponse response = httpClient.execute(httpGet);
263
264 //Process the response
265 int statusCode = response.getStatusLine().getStatusCode();
266 if (statusCode == HttpStatus.SC_OK) {
267 String response_string = EntityUtils.toString(response.getEntity());
268 System.out.println("response_string : " + response_string);
269 JSONArray jsonArray = new JSONArray(response_string);
270 JSONObject jsonObject = null;
271 if(jsonArray.length() > 0) {
272 jsonObject = jsonArray.getJSONObject(0);
273 }
274
275 Goods goods = new Goods();
276 if(jsonObject != null) {
277 goods.setGoodsName(jsonObject.getString("GoodsName__c"));
278 goods.setGoodsPrice(String.valueOf(jsonObject.getDouble("GoodsPrice__c")));
279 goods.setGoodsCostPrice(String.valueOf(jsonObject.getDouble("GoodsCostPrice__c")));
280 goods.setGoodsDescribe(jsonObject.getString("GoodsDescribe__c"));
281 }
282 //goods.setGoodsBrand(jsonObject.getString("GoodsBrand__c"));
283 return goods;
284 } else {
285 return null;
286 }
287 }
288 } catch (JSONException e) {
289 System.out.println("Issue creating JSON or processing results");
290 e.printStackTrace();
291 } catch (IOException ioe) {
292 ioe.printStackTrace();
293 } catch (NullPointerException npe) {
294 npe.printStackTrace();
295 }
296 return null;
297 }
298
299 public static void updateGoods(Goods updateGoods) {
300 try {
301 if(isAccessable()) {
302 String uri = baseUri + "/updateGoods/"+updateGoods.getGoodsId();
303 JSONObject goods = new JSONObject();
304 goods.put("GoodsName__c", updateGoods.getGoodsName());
305 goods.put("GoodsPrice__c", updateGoods.getGoodsPrice());
306 goods.put("GoodsCostPrice__c", updateGoods.getGoodsCostPrice());
307 org.apache.http.client.methods.HttpPatch httpPatch = new org.apache.http.client.methods.HttpPatch(uri);
308 HttpClient httpClient = HttpClientBuilder.create().build();
309 httpPatch.addHeader(oauthHeader);
310 httpPatch.addHeader(prettyPrintHeader);
311 StringEntity body = new StringEntity(goods.toString(1));
312 body.setContentType("application/json");
313 httpPatch.setEntity(body);
314
315 //Make the request
316 HttpResponse response = httpClient.execute(httpPatch);
317
318 //Process the response
319 int statusCode = response.getStatusLine().getStatusCode();
320 if (statusCode == HttpStatus.SC_OK) {
321 System.out.println("Updated the goods successfully.");
322 } else {
323 System.out.println("Goods update NOT successfully. Status code is " + statusCode);
324 }
325 }
326 }catch (JSONException e) {
327 System.out.println("Issue creating JSON or processing results");
328 e.printStackTrace();
329 } catch (IOException ioe) {
330 ioe.printStackTrace();
331 } catch (NullPointerException npe) {
332 npe.printStackTrace();
333 }
334 }
335
336
337 }
我们只对getGoodsById方法进行测试,下图为显示结果。
java访问sfdc的rest service需要OAuth身份认证,通过用户名密码,以及custom key 和custom password以及访问的apexrest链接即可以访问相应的rest service资源。
总结:本篇描述的主要是sfdc如何通过rest方式获取外部平台的资源以及sfdc如何作为rest service供外部平台调用,每个人的账号密码,以及custom key 和custom password不相同,copy代码后修改这几处地方,如果restResource以及相应注解对应的方法不同,也需要修改相应的方法。此篇文章的缺点为没有考虑中文内容的问题,通过insert等方法存储到服务器会导致中文乱码现象,有需要的可以自行对数据进行编码解码处理。