本篇参考Trail教程:
有的时候我们需要在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等。
/*
* 使用salesforce通过REST方式作为webservice,需要以下几点:
* 1.类和方法需要global,方法需要静态
* 2.类需要通过RestResource(UrlMapping='/page/*')注解声明
* 3.@HttpGet和@HttpDelete不能有形参,可以通过URL?param或者URL/param方式传过来参数
*/
@RestResource(UrlMapping='/Goods/*')
global class GoodsRESTController {
global static final Integer PAGE_SIZE = 20;
@HttpGet
global static List<Goods__c> getGoodsByIdOrGoodsList() {
RestRequest request = RestContext.request;
// grab the goodsId from the end of the URL
String currentPage = request.params.get('currentPage') != null ? request.params.get('currentPage') : '0';
Integer offsetNumber = Integer.valueOf(currentPage) * PAGE_SIZE;
String goodsId = request.params.get('goodsId');
String fetchSql;
if(goodsId != null) {
fetchSql = 'SELECT CreatedById, CreatedDate, IsDeleted, Name,' +
' GoodsBrand__c, GoodsCostPrice__c, GoodsDescribe__c, GoodsName__c,' +
' GoodsPrice__c, GoodsProfit__c, LastActivityDate, LastModifiedById,' +
' LastModifiedDate, No__c, OwnerId, Id FROM Goods__c' +
' where Id = :goodsId';
} else {
fetchSql = 'SELECT CreatedById, CreatedDate, IsDeleted, Name,' +
' GoodsBrand__c, GoodsCostPrice__c, GoodsDescribe__c, GoodsName__c,' +
' GoodsPrice__c, GoodsProfit__c, LastActivityDate, LastModifiedById,' +
' LastModifiedDate, No__c, OwnerId, Id FROM Goods__c limit :PAGE_SIZE offset :offsetNumber';
}
List<Goods__c> goodsList = Database.query(fetchSql);
return goodsList;
} @HttpPost
global static Id insertGoods(String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
System.debug('---------goodsName-------------' + goodsName);
Goods__c goods = new Goods__c();
if(goodsPrice != null && goodsPrice.isNumeric()) {
goods.GoodsPrice__c = Double.valueOf(goodsPrice);
}
if(goodsCostPrice != null && goodsCostPrice.isNumeric()) {
goods.GoodsCostPrice__c = Double.valueOf(goodsCostPrice);
}
goods.GoodsName__c = goodsName;
goods.GoodsDescribe__c = goodsDescribe;
insert goods;
return goods.Id;
} @HttpDelete
global static void deleteGoods() {
RestRequest request = RestContext.request;
String goodsId = request.requestURI.substring(
request.requestURI.lastIndexOf('/')+1);
Goods__c needDeleteGoods = [select Id from Goods__c where Id = :goodsId];
if(needDeleteGoods != null) {
delete needDeleteGoods;
}
} @HttpPut
global static ID upsertGoods(String id,String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
Goods__c goods = new Goods__c();
goods.Id = id;
goods.GoodsName__c = goodsName;
goods.GoodsBrand__c = goodsBrand;
goods.GoodsDescribe__c = goodsDescribe;
if(goodsPrice != null && goodsPrice.isNumeric()) {
goods.GoodsPrice__c = Double.valueOf(goodsPrice);
}
if(goodsCostPrice != null && goodsCostPrice.isNumeric()) {
goods.GoodsCostPrice__c = Double.valueOf(goodsCostPrice);
}
upsert goods;
return goods.Id;
} @HttpPatch
global static ID updateGoods() {
RestRequest request = RestContext.request;
String goodsId = request.requestURI.substring(
request.requestURI.lastIndexOf('/')+1);
Goods__c goods = [select Id from Goods__c where Id= :goodsId];
// Deserialize the JSON string into name-value pairs
Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.tostring());
// Iterate through each parameter field and value
goods.GoodsName__c = String.valueOf(params.get('GoodsName__c'));
goods.GoodsPrice__c = Double.valueOf(params.get('GoodsPrice__c'));
goods.GoodsCostPrice__c = Double.valueOf(params.get('GoodsCostPrice__c'));
update goods;
return goods.Id;
} }
测试自己写的方法可以在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项目里,然后开始代码访问阶段。
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener; public class InvokeGoodsByRestViaSFDC { static final String USERNAME = "你的salesforce账号";
static final String PASSWORD = "你的salesforce密码+security token(如果有security token)";
static final String LOGINURL = "https://login.salesforce.com";
static final String GRANTSERVICE = "/services/oauth2/token?grant_type=password";
static final String CLIENTID = "3MVG9ZL0ppGP5UrBiKUS3jtHfmfz4eBCBEnuY0tIDByXVdtBJWeY6olTn1iLDNvP68EmfVtWE3IDzHOsMuDww";//上图中Consumer Key
static final String CLIENTSECRET = "723866328398987848";//上图中的Consumer Secret
private static String REST_ENDPOINT = "/services/apexrest" ;
private static String baseUri;
private static Header oauthHeader;
private static Header prettyPrintHeader = new BasicHeader("X-PrettyPrint", "1"); /**
* 判断是否可以访问sfdc
* return:可以访问sfdc的rest则返回true,否则返回false
* */
private static boolean isAccessable() {
HttpClient httpclient = HttpClientBuilder.create().build(); // Assemble the login request URL
String loginURL = LOGINURL +
GRANTSERVICE +
"&client_id=" + CLIENTID +
"&client_secret=" + CLIENTSECRET +
"&username=" + USERNAME +
"&password=" + PASSWORD; // Login requests must be POSTs
HttpPost httpPost = new HttpPost(loginURL);
HttpResponse response = null;
try {
// Execute the login POST request
response = httpclient.execute(httpPost);
} catch (ClientProtocolException cpException) {
cpException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
// verify response is HTTP OK
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
System.out.println("Error authenticating to Force.com: "+statusCode);
return false;
} String getResult = null;
try {
getResult = EntityUtils.toString(response.getEntity());
} catch (IOException ioException) {
ioException.printStackTrace();
} JSONObject jsonObject = null;
String loginAccessToken = null;
String loginInstanceUrl = null; try {
jsonObject = (JSONObject) new JSONTokener(getResult).nextValue();
loginAccessToken = jsonObject.getString("access_token");
loginInstanceUrl = jsonObject.getString("instance_url");
} catch (JSONException jsonException) {
jsonException.printStackTrace();
} baseUri = loginInstanceUrl + REST_ENDPOINT + "/Goods";
oauthHeader = new BasicHeader("Authorization", "OAuth " + loginAccessToken) ;
System.out.println("oauthHeader1: " + oauthHeader);
System.out.println(response.getStatusLine());
System.out.println("Successful login");
System.out.println("instance URL: "+loginInstanceUrl);
System.out.println("access token/session ID: "+loginAccessToken);
System.out.println("baseUri: "+ baseUri);
return true;
} public static void main(String[] args) {
createGoods("小米4","小米","2500","2000","测试商品描述信息:小米");
//deleteGoods("a052800000880mlAAA");
Goods getGoods = getGoodsById("a0528000008811qAAA");
if(getGoods != null) {
System.out.println("goods Name :" + getGoods.getGoodsName());
System.out.println("goods Price : " + getGoods.getGoodsPrice());
System.out.println("goods cost price :" +getGoods.getGoodsCostPrice());
System.out.println("goods brand : " + getGoods.getGoodsBrand());
}
List<Goods> goodsList = getGoodsList(0);
System.out.println(goodsList.toString()); Goods updateGoods = new Goods();
updateGoods.setGoodsId("a0528000008811qAAA");
updateGoods.setGoodsName("test goods Name");
updateGoods.setGoodsPrice("10000");
updateGoods.setGoodsCostPrice("8000");
updateGoods(updateGoods);
} // Create Goods using REST HttpPost
public static void createGoods(String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
try {
if(isAccessable()) {
String uri = baseUri + "/createGoods";
JSONObject goods = new JSONObject();
goods.put("goodsName", goodsName);
goods.put("goodsBrand", goodsBrand);
goods.put("goodsPrice", goodsPrice);
goods.put("goodsCostPrice",goodsCostPrice);
goods.put("goodsDescribe", goodsDescribe); System.out.println("JSON for goods record to be inserted:\n" + goods.toString(1));
//Construct the objects needed for the request
HttpClient httpClient = HttpClientBuilder.create().build();
System.out.println("oauthHeader" + oauthHeader);
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader(oauthHeader);
httpPost.addHeader(prettyPrintHeader);
httpPost.addHeader("encoding", "UTF-8");
// The message we are going to post
StringEntity body = new StringEntity(goods.toString(1));
body.setContentType("application/json");
httpPost.setEntity(body); //Make the request
HttpResponse response = httpClient.execute(httpPost);
System.out.print("response : " + response.toString());
//Process the results
int statusCode = response.getStatusLine().getStatusCode();
System.out.println("status code : " + statusCode);
if (statusCode == HttpStatus.SC_OK) {
String response_string = EntityUtils.toString(response.getEntity());
if(response_string != null ) {
System.out.println("New Goods id from response: " + response_string);
}
} else {
System.out.println("Insertion unsuccessful. Status code returned is " + statusCode);
}
httpPost.releaseConnection();
}
} catch (JSONException e) {
System.out.println("Issue creating JSON or processing results");
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
} public static void deleteGoods(String goodsId) {
try {
if(isAccessable()) {
String uri = baseUri + "/deleteGoods" + "/" + goodsId;
HttpClient httpClient = HttpClientBuilder.create().build(); HttpDelete httpDelete = new HttpDelete(uri);
httpDelete.addHeader(oauthHeader);
httpDelete.addHeader(prettyPrintHeader); //Make the request
HttpResponse response = httpClient.execute(httpDelete); //Process the response
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
System.out.println("Deleted the goods successfully.");
} else {
System.out.println("goods delete NOT successful. Status code is " + statusCode);
}
httpDelete.releaseConnection();
}
} catch (JSONException e) {
System.out.println("Issue creating JSON or processing results");
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
} public static List<Goods> getGoodsList(Integer pageNumber) {
try {
if(isAccessable()) {
String uri = baseUri + "/getGoodsByIdOrGoodsList" + "?currentPage=" + pageNumber;
HttpClient httpClient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(uri);
httpGet.addHeader(oauthHeader);
httpGet.addHeader(prettyPrintHeader);
//Make the request
HttpResponse response = httpClient.execute(httpGet);
//Process the response
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
List<Goods> goodsList = new ArrayList<Goods>();
String response_string = EntityUtils.toString(response.getEntity());
System.out.println("response_string : " + response_string);
JSONArray jsonArray = new JSONArray(response_string);
JSONObject jsonObject = null;
for(int i=0;i<jsonArray.length();i++) {
jsonObject = jsonArray.getJSONObject(i);
Goods goods = new Goods();
if(jsonObject != null) {
goods.setGoodsName(jsonObject.getString("GoodsName__c"));
goods.setGoodsPrice(String.valueOf(jsonObject.getDouble("GoodsPrice__c")));
goods.setGoodsCostPrice(String.valueOf(jsonObject.getDouble("GoodsCostPrice__c")));
goods.setGoodsDescribe(jsonObject.getString("GoodsDescribe__c"));
goodsList.add(goods);
}
}
return goodsList;
} else {
return null;
}
}
}catch (JSONException e) {
System.out.println("Issue creating JSON or processing results");
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
return null;
} public static Goods getGoodsById(String goodsId) {
try {
if(isAccessable()) {
String uri = baseUri + "/getGoodsByIdOrGoodsList" + "?goodsId=" + goodsId;
HttpClient httpClient = HttpClientBuilder.create().build(); HttpGet httpGet = new HttpGet(uri);
httpGet.addHeader(oauthHeader);
httpGet.addHeader(prettyPrintHeader); //Make the request
HttpResponse response = httpClient.execute(httpGet); //Process the response
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
String response_string = EntityUtils.toString(response.getEntity());
System.out.println("response_string : " + response_string);
JSONArray jsonArray = new JSONArray(response_string);
JSONObject jsonObject = null;
if(jsonArray.length() > 0) {
jsonObject = jsonArray.getJSONObject(0);
} Goods goods = new Goods();
if(jsonObject != null) {
goods.setGoodsName(jsonObject.getString("GoodsName__c"));
goods.setGoodsPrice(String.valueOf(jsonObject.getDouble("GoodsPrice__c")));
goods.setGoodsCostPrice(String.valueOf(jsonObject.getDouble("GoodsCostPrice__c")));
goods.setGoodsDescribe(jsonObject.getString("GoodsDescribe__c"));
}
//goods.setGoodsBrand(jsonObject.getString("GoodsBrand__c"));
return goods;
} else {
return null;
}
}
} catch (JSONException e) {
System.out.println("Issue creating JSON or processing results");
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
return null;
} public static void updateGoods(Goods updateGoods) {
try {
if(isAccessable()) {
String uri = baseUri + "/updateGoods/"+updateGoods.getGoodsId();
JSONObject goods = new JSONObject();
goods.put("GoodsName__c", updateGoods.getGoodsName());
goods.put("GoodsPrice__c", updateGoods.getGoodsPrice());
goods.put("GoodsCostPrice__c", updateGoods.getGoodsCostPrice());
org.apache.http.client.methods.HttpPatch httpPatch = new org.apache.http.client.methods.HttpPatch(uri);
HttpClient httpClient = HttpClientBuilder.create().build();
httpPatch.addHeader(oauthHeader);
httpPatch.addHeader(prettyPrintHeader);
StringEntity body = new StringEntity(goods.toString(1));
body.setContentType("application/json");
httpPatch.setEntity(body); //Make the request
HttpResponse response = httpClient.execute(httpPatch); //Process the response
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
System.out.println("Updated the goods successfully.");
} else {
System.out.println("Goods update NOT successfully. Status code is " + statusCode);
}
}
}catch (JSONException e) {
System.out.println("Issue creating JSON or processing results");
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
} }
我们只对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等方法存储到服务器会导致中文乱码现象,有需要的可以自行对数据进行编码解码处理。