Java 語言指南

重要事項:這份文件的撰寫時間是 2012 年。本文所述的驗證選項 (OAuth 1.0、AuthSub 和 ClientLogin) 已於 2012 年 4 月 20 日正式淘汰,並且全面停用。建議您盡快遷移至 OAuth 2.0

Google Sites Data API 可讓用戶端應用程式存取、發布及修改 Google 網站中的內容。您的用戶端應用程式也可以要求最近活動清單、擷取修訂版本記錄,以及下載附件。

除了針對 Sites Data API 功能提供一些背景說明外,本指南還提供了使用 Java 用戶端程式庫與 API 互動的範例。如需設定用戶端程式庫的相關說明,請參閱「開始使用 Google Data Java 用戶端程式庫」一文。如要進一步瞭解 Java 用戶端程式庫使用的基礎通訊協定與傳統版協作平台 API 互動,請參閱通訊協定指南

適用對象

本文件可協助開發人員使用 Google Data Java 用戶端程式庫編寫與 Google 協作平台互動的用戶端應用程式。

開始使用

Google 協作平台會使用 Google 帳戶或 G Suite 帳戶進行驗證。如果您已有帳戶,就表示一切就緒。 或者,您也可以建立新帳戶

安裝程式庫

如需設定和安裝用戶端程式庫的相關說明,請參閱開始使用 Google Data Java 用戶端程式庫。如果您使用的是 Eclipse,該文章也會說明如何使用 Google Data API Eclipse 外掛程式設定專案。事前準備如下:

  1. 安裝 Java 1.5 以上版本
  2. 下載用戶端程式庫 (最新版本的 gdata-src.java.zip)
  3. 下載依附元件清單
  4. 下載範例應用程式 (最新版 gdata-samples.java.zip)

安裝 .jar 後,您需要在專案中加入以下內容:

  1. java/lib/gdata-sites-2.0.jar - 此處 2.0 版適用於 Classic Sites API 1.4 版。
  2. java/lib/gdata-core-1.0.jar
  3. java/lib/gdata-client-1.0.jar
  4. java/lib/gdata-spreadsheet-3.0.jar (適用於清單頁面 / 清單項目)

此外,請務必加入依附元件 jar (gdata-media-1.0.jarmail.jargoogle-collect....jar)。

執行範例應用程式

完整範例應用程式位於 gdata-samples.java.zip 下載的 /java/sample/sites 子目錄中。您也可以在 SVN 存放區的 /trunk/java/sample/sites/ 中找到從「來源」分頁存取的原始碼。SitesDemo.java 可讓使用者執行多項作業,示範如何使用傳統版協作平台 API。

請注意,您需要加入 java/sample/util/lib/sample-util.jar 才能執行範例。

啟動自己的專案

提示:請參閱搭配使用 Eclipse 與 Google Data API 一文,瞭解如何使用我們的 Eclipse 外掛程式快速設定。

視應用程式需求而定,您會需要多次匯入內容。建議您從下列匯入項目著手:

import com.google.gdata.client.*;
import com.google.gdata.client.sites.*;
import com.google.gdata.data.*;
import com.google.gdata.data.acl.*;
import com.google.gdata.data.media.*;
import com.google.gdata.data.sites.*;
import com.google.gdata.data.spreadsheet.*;  // If working with listpages / listitems
import com.google.gdata.util.*;

接下來,您還需要設定 SitesService 物件,代表與傳統版協作平台 API 的用戶端連線:

SitesService client = new SitesService("yourCo-yourAppName-v1");

applicationName 引數應遵循下列格式:company-applicationname-version。此參數用於記錄。

注意:本指南的其餘部分假設您已在 client 變數中建立 SitesService

驗證傳統版協作平台網站 API

Java 用戶端程式庫可用於公開或私人動態饋給。Sites Data API 可讓您存取私人和公開動態饋給,實際情況視協作平台權限和您要執行的作業而定。舉例來說,您可以讀取公開網站的內容動態饋給,但無法對其進行更新,便需要通過驗證的用戶端。這可以透過 ClientLogin 使用者名稱/密碼驗證、AuthSubOAuth 來完成。

如要進一步瞭解 AuthSub、OAuth 和 ClientLogin,請參閱 Google Data API 驗證總覽

提示:API 支援安全資料傳輸層 (HTTPS)。如果您使用的是 AuthSub/OAuth,請務必指定 https://sites.google.com/feeds/ 的範圍,才能透過 SSL 要求動態饋給。另請注意,若為 G Suite 網域,API 會遵循管理控制台中的「需要 SSL」設定。您可以呼叫 client.useSsl();,強制所有 API 要求一律透過 HTTPS 傳送。

網頁應用程式的 AuthSub

用戶端應用程式應使用網路應用程式的 AuthSub 驗證,而需要驗證使用者以進入 Google 帳戶。營運商不需要存取 Google 協作平台使用者的使用者名稱和密碼,只需要 AuthSub 權杖。

查看將 AuthSub 整合至網頁應用程式的操作說明

要求單次使用權杖

使用者首次造訪應用程式時,必須進行驗證。一般而言,開發人員會列印一些文字及一個連結,將使用者導向至 AuthSub 核准頁面,以驗證使用者並要求存取其文件。Google Data Java 用戶端程式庫提供可產生這個網址的函式。下列程式碼會設定 AuthSubRequest 頁面的連結。

import com.google.gdata.client.*;

String nextUrl = "http://www.example.com/welcome.jsp";
String scope = "https://sites.google.com/feeds/";
boolean secure = true;
boolean session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);

如果您要在 G Suite 代管網域中驗證使用者:

import com.google.gdata.client.*;

String hostedDomain = "example.com";
String nextUrl = "http://www.example.com/welcome.jsp";
String scope = "https://sites.google.com/feeds/";  // SSL is also supported
boolean secure = true;
boolean session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);

getRequestUrl() 方法使用多個參數 (對應 AuthSubRequest 處理常式使用的查詢參數):

  • next 網址:使用者登入帳戶並授予存取權後,Google 將重新導向的網址;上例中的 http://www.example.com/welcome.jsp
  • 範圍 - https://sites.google.com/feeds/
  • 指出符記是否將用於註冊模式的布林值,如上例中的 false
  • 第二個布林值,表示權杖稍後是否交換工作階段權杖;在上例中為 true

升級為工作階段符記

請參閱搭配 Google Data API 用戶端程式庫使用 AuthSub

擷取工作階段憑證的相關資訊

請參閱搭配 Google Data API 用戶端程式庫使用 AuthSub

撤銷工作階段符記

請參閱搭配 Google Data API 用戶端程式庫使用 AuthSub

用於網頁或已安裝/行動應用程式的 OAuth

OAuth 可做為 AuthSub 的替代方案,適用於網頁應用程式。OAuth 與 AuthSub 的安全註冊模式類似,兩者的資料要求都必須經過數位簽署,且您必須註冊網域。

查看操作說明,瞭解如何將 OAuth 整合至安裝的應用程式

已安裝/行動應用程式的 ClientLogin

ClientLogin 應用於已安裝或需要向 Google 帳戶驗證使用者的應用程式。首次執行時,應用程式會提示使用者輸入使用者名稱/密碼。在後續要求中,系統會參照驗證權杖。

查看將 ClientLogin 整合到已安裝的應用程式中的操作說明

如要使用 ClientLogin,請叫用 SitesService 物件的 setUserCredentials() 方法,該物件沿用自 GoogleService。指定您的用戶端發出要求的使用者電子郵件地址和密碼。例如:

SitesService client = new SitesService("yourCo-yourAppName-v1");
client.setUserCredentials("example@gmail.com", "pa$$word");

提示:應用程式第一次成功驗證使用者後,請將驗證權杖儲存在資料庫中,以便之後使用。不必在每次執行應用程式時要求使用者輸入密碼。 詳情請參閱「撤銷驗證權杖」。

若要進一步瞭解如何在 Java 應用程式中使用 ClientLogin,請參閱搭配 Google Data API 用戶端程式庫使用 ClientLogin

返回頁首

網站動態消息

此外,網站動態消息可用來列出使用者擁有的 Google 協作平台,或是具備檢視權限。 也可以用來修改現有網站的名稱。如為 G Suite 網域,叢集也可用來建立及/或複製整個網站。

列出網站

如要查詢網站動態饋給,請將 HTTP GET 傳送至網站動態饋給網址:

https://sites.google.com/feeds/site/site/

在 Java 用戶端中,您可以使用 SiteFeedSiteEntry 類別來搭配網站動態饋給:

public String getSiteFeedUrl() {
  String domain = "site";  // OR if the Site is hosted on G Suite, your domain (e.g. example.com)
  return "https://sites.google.com/feeds/site/" + domain + "/";
}

public void getSiteFeed() throws IOException, ServiceException {
  SiteFeed siteFeed = client.getFeed(new URL(getSiteFeedUrl()), SiteFeed.class);
  for (SiteEntry entry : siteFeed.getEntries()){
    System.out.println("title: " + entry.getTitle().getPlainText());
    System.out.println("site name: " + entry.getSiteName().getValue());
    System.out.println("theme: " + entry.getTheme().getValue());
    System.out.println("");
  }
}

上方的程式碼片段會顯示網站的標題、網站名稱和主題。其他 getter 可用來存取動態饋給中的其他屬性。

建立新網站

注意:這項功能僅適用於 G Suite 網域。

您可以建立新的 SiteEntry,並在網站動態饋給中呼叫用戶端的 insert() 方法,即可佈建新網站。

本例會建立全新的網站,以主題為主題 (選用設定),並提供網站名稱 (必填) 和說明 (選填):

public String getSiteFeedUrl() {
  String domain = "example.com";
  return "https://sites.google.com/feeds/site/" + domain + "/";
}

public SiteEntry createSite(String title, String summary, String theme, String tag)
    throws MalformedURLException, IOException, ServiceException {
  SiteEntry entry = new SiteEntry();
  entry.setTitle(new PlainTextConstruct(title));
  entry.setSummary(new PlainTextConstruct(summary));

  Theme tt = new Theme();
  tt.setValue(theme);
  entry.setTheme(tt);

  entry.getCategories().add(new Category(TagCategory.Scheme.TAG, tag, null));

  return client.insert(new URL(getSiteFeedUrl()), entry);
}

SiteEntry newSiteEntry = createSite("My Site Title", "summary for site", "slate", "tag");

上述要求會在 G Suite 網域 example.com 下建立新網站。 因此,網站網址會是 https://sites.google.com/a/example.com/my-site-title。

網站成功建立後,伺服器會回應一個 SiteEntry 物件,並填入伺服器加入的元素:網站連結、網站 acl 動態饋給的連結、網站名稱、標題、摘要等。

複製網站

注意:這項功能僅適用於 G Suite 網域。

複製網站的做法與建立新的網站類似,不同之處在於您必須在新的 SiteEntry 上設定連結,並在其中加入要複製的自我連結。以下舉例說明如何複製在「建立新網站」部分中所建立的網站:

public SiteEntry copySite(String title, String summary, String sourceHref)
    throws MalformedURLException, IOException, ServiceException {
  SiteEntry entry = new SiteEntry();
  entry.setTitle(new PlainTextConstruct(title));
  entry.setSummary(new PlainTextConstruct(summary));
  entry.addLink(SitesLink.Rel.SOURCE, Link.Type.ATOM, sourceHref);

  return client.insert(new URL(getSiteFeedUrl()), entry);
}

String sourceHref = newSiteEntry.getLink(SitesLink.Rel.SOURCE, Link.Type.ATOM).getHref();
SiteEntry myTwin = copySite("Duplicate Site", "A copy", sourceHref);

重要事項:

  • 您只能複製已驗證使用者擁有的網站和網站範本。
  • 您也可以複製網站範本。如果 Google 協作平台設定頁面中的「將這個網站發布為範本」設定處於勾選狀態,即視為範本。
  • 你可以從其他網域複製網站,對方待你在來源網站上列為擁有者。

更新網站中繼資料

如要重新命名網站、變更主題、類別標記或摘要,您必須先擷取包含該網站的 SiteEntry、修改一或多個屬性,然後呼叫 SiteEntryupdate() 方法。以下範例修改了前一個網站的主題,並重新命名網站:

myTwin.setTitle(new PlainTextConstruct("better-title"));

Theme theme = myTwin.getTheme();
theme.setValue('iceberg');
myTwin.setTheme(theme);

myTwin.getCategories().add(new Category(TagCategory.Scheme.TAG, "newTag", null));

SiteEntry updatedSiteEntry = myTwin.update();

System.out.println(updatedSiteEntry.getTitle().getPlainText();

網址對應

網址對應可讓協作平台使用者將自己的網域對應至 Google 協作平台。例如,您可以使用 http://www.mydomainsite.com 取代 http://sites.google.com/a/domain.com/mysite。視網站的代管位置而定,您可以手動修改網站的網址對應。詳情請參閱我們的說明中心文章。

擷取網站的網址對應

如要傳回網站的網址對應,請使用 with-mappings=true 參數擷取網站項目/動態饋給:

SiteQuery query = new SiteQuery(new URL("https://sites.google.com/feeds/site/siteName"));
query.setWithMappings(true);

SiteFeed feed = service.getFeed(query, SiteFeed.class);
for (SiteEntry entry : feed.getEntries()) {
  System.out.println("Mappings for '" + entry.getSiteName().getValue() + "':");
  for (Link link : entry.getWebAddressMappingLinks()) {
    System.out.println("  " + link.getHref());
  }
}

現有的對應關係會顯示為 link,當中包含 rel='webAddressMapping'。舉例來說,在上述範例中,有三個 webAddressMapping 指向網站 http://sites.google.com/site/myOtherTestSite

修改網址對應

注意:所有 GET/POST/PUT 作業都應該在使用網址對應時指定 with-mappings=true 參數。如果缺少這項參數,系統就不會在網站項目 (GET) 中傳回 webAddressMapping,也不會在更新/移除項目 (PUT) 對應時考量這些項目。

如要新增、更新或刪除對應關係,只要在建立新網站更新網站中繼資料時指定、變更或移除這類連結即可。網站動態饋給 URI 必須包含 with-mappings=true 參數。注意:您必須是網站管理員或網域管理員 (使用 G Suite 代管網站),才能更新地址對應。

例如,下方要求會將 http://www.mysitemapping.com 對應更新為 http://www.my-new-sitemapping.com,而將 http://www.mysitemapping2.com 從項目中移出,藉此移除 http://www.mysitemapping2.com

SiteEntry entry = client.getEntry(new URL("https://sites.google.com/feeds/site/site/siteName?with-mappings=true"), SiteEntry.class);

// Modify mappings (remove all mappings, add some of them again, add modified mappings)
entry.removeLinks(SitesLink.Rel.WEBADDRESSMAPPING, Link.Type.HTML);
entry.addLink(SitesLink.Rel.WEBADDRESSMAPPING, Link.Type.HTML, "http://www.my-new-sitemapping.com");

// Update the entry with the mappings.
entry.update();

請注意,您也可以在建立/複製網站時指定網址對應。

返回頁首

活動動態消息

您可以擷取活動動態消息,擷取網站的近期活動 (變更)。活動動態饋給中的每個項目都包含對網站所做的變更資訊。

如要查詢活動動態消息,請將 HTTP GET 傳送至活動動態消息網址:

https://sites.google.com/feeds/activity/site/siteName

在 Java 用戶端中,使用 ActivityFeed 類別傳回 ActivityEntry 物件:

public String buildActivityFeedUrl() {
  String domain = "site";  // OR if the Site is hosted on G Suite, your domain (e.g. example.com)
  String siteName = "mySite";
  return "https://sites.google.com/feeds/activity/" + domain + "/" + siteName + "/";
}

public void getActivityFeed() throws IOException, ServiceException {
  ActivityFeed activityFeed = client.getFeed(new URL(buildActivityFeedUrl()), ActivityFeed.class);
  for (BaseActivityEntry<?> entry : activityFeed.getEntries()){
    System.out.println(entry.getSummary().getPlainText());
    System.out.println(" revisions link: " + entry.getRevisionLink().getHref());
  }
}

注意:你必須是網站的協作者或擁有者,才能存取這個動態饋給。 您的用戶端必須使用 AuthSub、OAuth 或 ClientLogin 權杖進行驗證。請參閱驗證協作平台服務

返回頁首

修訂版本動態饋給

如要擷取任何內容項目的修訂版本記錄,請將 HTTP GET 傳送至該項目的修訂版本連結:

https://sites.google.com/feeds/revision/site/siteName/CONTENT_ENTRY_ID

以下範例會查詢內容動態饋給,然後擷取第一個內容項目的修訂版本動態饋給:

ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl()), ContentFeed.class);
URL revisionFeedUrl = new URL(contentFeed.getEntries().get(0).getRevisionLink().getHref()); // use first entry

public void getRevisionFeed(String revisionFeedUrl) throws IOException, ServiceException {
  RevisionFeed revisionFeed = client.getFeed(revisionFeedUrl, RevisionFeed.class);
  for (BaseContentEntry<?> entry : revisionFeed.getEntries()){
    System.out.println(entry.getTitle().getPlainText());
    System.out.println(" updated: " + entry.getUpdated().toUiString() + " by " +
        entry.getAuthors().get(0).getEmail());
    System.out.println(" revision #: " + entry.getRevision().getValue());
  }
}

注意:你必須是網站的協作者或擁有者,才能存取這個動態饋給。 您的用戶端必須使用 AuthSub、OAuth 或 ClientLogin 權杖進行驗證。請參閱驗證協作平台服務

返回頁首

內容動態消息

擷取內容動態饋給

內容資訊提供會列出網站的最新內容。將 HTTP GET 傳送至內容動態消息網址即可存取:

https://sites.google.com/feeds/content/site/siteName
動態饋給參數說明
sitesite」或您 G Suite 代管網域的網域 (例如 example.com)。
siteName網站的網頁空間名稱,您可以在網站的網址中找到 (例如 mySite)。

擷取內容動態饋給的範例:

public String buildContentFeedUrl() {
  String domain = "site";  // OR if the Site is hosted on G Suite, your domain (e.g. example.com)
  String siteName = "mySite";
  return "https://sites.google.com/feeds/content/" + domain + "/" + siteName + "/";
}

ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl()), ContentFeed.class);

產生的 contentFeedContentFeed 物件,其中包含伺服器的回應。contentFeed 的每個項目都代表使用者網站中的不同網頁或項目。ContentFeed 會包含不同類型的物件,所有物件都繼承自 BaseContentEntryListItemEntryListPageEntryAttachmentEntryWebAttachmentEntryFileCabinetPageEntryAnnouncementsPageEntryAnnouncementEntryWebPageEntryCommentEntry

以下是在 ContentFeed 中列出不同類型項目的範例。每種類型的項目都包含不同的屬性,但這裡並未列出所有屬性。

public String getContentBlob(BaseContentEntry<?> entry) {
 return ((XhtmlTextConstruct) entry.getTextContent().getContent()).getXhtml().getBlob();
}

// Extracts an entry's numeric ID.
private String getEntryId(String selfLink) {
  return selfLink.substring(selfLink.lastIndexOf("/") + 1);
}

public void printContentEntries(ContentFeed contentFeed) {
  System.out.println("Listing all WebPageEntry:");
  for (WebPageEntry entry : contentFeed.getEntries(WebPageEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    if (entry.getParentLink() != null) {
      System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref()));
    }
    System.out.println(" author: " + entry.getAuthors().get(0).getEmail());
    System.out.println(" content: " + getContentBlob(entry));
  }

  System.out.println("Listing all ListPageEntry:");
  for (ListPageEntry entry : contentFeed.getEntries(ListPageEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    for (Column col : entry.getData().getColumns()) {
      System.out.print(" [" + col.getIndex() + "] " + col.getName() + "\t");
    }
  }

  for (ListItemEntry entry : contentFeed.getEntries(ListItemEntry.class)) {
    for (Field field : entry.getFields()) {
      System.out.print(" [" + field.getIndex() + "] " + field.getValue() + "\t");
    }
    System.out.println("\n");
  }

  System.out.println("Listing all FileCabinetPageEntry:");
  for (FileCabinetPageEntry entry : contentFeed.getEntries(FileCabinetPageEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    System.out.println(" content: " + getContentBlob(entry));
  }

  System.out.println("Listing all CommentEntry:");
  for (CommentEntry entry : contentFeed.getEntries(CommentEntry.class)) {
    System.out.println(" in-reply-to: " + entry.getInReplyTo().toString());
    System.out.println(" content: " + getContentBlob(entry));
  }

  System.out.println("Listing all AnnouncementsPageEntry:");
  for (AnnouncementsPageEntry entry : contentFeed.getEntries(AnnouncementsPageEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    System.out.println(" content: " + getContentBlob(entry));
  }

  System.out.println("Listing all AnnouncementEntry:");
  for (AnnouncementEntry entry : contentFeed.getEntries(AnnouncementEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    if (entry.getParentLink() != null) {
      System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref()));
    }
    System.out.println(" draft?: " + entry.isDraft());
    System.out.println(" content: " + getContentBlob(entry));
  }

  System.out.println("Listing all AttachmentEntry:");
  for (AttachmentEntry entry : contentFeed.getEntries(AttachmentEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    if (entry.getParentLink() != null) {
      System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref()));
    }
    if (entry.getSummary() != null) {
      System.out.println(" description: " + entry.getSummary().getPlainText());
    }
    System.out.println(" revision: " + entry.getRevision().getValue());
    MediaContent content = (MediaContent) entry.getContent();
    System.out.println(" src: " + content.getUri());
    System.out.println(" content type: " + content.getMimeType().getMediaType());
  }

  System.out.println("Listing all WebAttachmentEntry:");
  for (WebAttachmentEntry entry : contentFeed.getEntries(WebAttachmentEntry.class)) {
    System.out.println(" title: " + entry.getTitle().getPlainText());
    System.out.println(" id: " + getEntryId(entry));
    if (entry.getParentLink() != null) {
      System.out.println(" parent id: " + getEntryId(entry.getParentLink().getHref()));
    }
    if (entry.getSummary() != null) {
      System.out.println(" description: " + entry.getSummary().getPlainText());
    }
    System.out.println(" src: " + ((MediaContent) entry.getContent()).getUri());
  }
}

注意:依網站的共用權限而定,這則動態饋給不一定需要驗證。 如果是非公開網站,您的用戶端必須使用 AuthSub、OAuth 或 ClientLogin 權杖進行驗證。請參閱驗證協作平台服務一文。

內容動態饋給查詢範例

您可以使用部分標準 Google Data API 查詢參數和傳統版 Sites API,來搜尋內容動態饋給。如要瞭解詳情及完整的支援參數清單,請參閱參考指南

注意:本節中的範例使用「擷取內容動態饋給」中的 buildContentFeedUrl() 方法。

擷取特定項目種類

如果只要擷取特定類型的項目,請使用 kind 參數。這個範例只會傳回 attachment 個項目:

ContentQuery query = new ContentQuery(new URL(buildContentFeedUrl()));
query.setKind("webpage");
ContentFeed contentFeed = client.getFeed(query, ContentFeed.class);
for (AttachmentEntry entry : contentFeed.getEntries(AttachmentEntry.class)) {
  System.out.println(entry.getTitle().getPlainText());
}

如要傳回多個項目類型,請使用「,」分隔每個 kind。這個範例會傳回 filecabinetlistpage 項目:

URL url = new URL(buildContentFeedUrl() + "?kind=filecabinet,listpage");
ContentFeed contentFeed = client.getFeed(url, ContentFeed.class);
for (FileCabinetPageEntry entry : contentFeed.getEntries(FileCabinetPageEntry.class)) {
  System.out.println(" title: " + entry.getTitle().getPlainText());
}
for (ListPageEntry entry : contentFeed.getEntries(ListPageEntry.class)) {
  System.out.println(" title: " + entry.getTitle().getPlainText());
}

依路徑擷取頁面

如果您知道 Google 網站內網頁的相對路徑,可以使用 path 參數擷取該網頁。 以下範例會傳回位於 http://sites.google.com/site/siteName/path/to/the/page 的網頁:

ContentQuery query = new ContentQuery(new URL(buildContentFeedUrl()));
query.setPath("/path/to/the/page");
ContentFeed contentFeed = client.getFeed(query, ContentFeed.class);
for (BaseContentEntry<?> entry : contentFeed.getEntries()) {
  System.out.println(" title: " + entry.getTitle().getPlainText());
}

擷取上層頁面下的所有項目

如果您知道網頁的內容項目 ID (例如以下範例中的「1234567890」),可以使用 parent 參數擷取其所有子項項目 (如果有的話):

ContentQuery query = new ContentQuery(new URL(buildContentFeedUrl()));
query.setParent("1234567890");
ContentFeed contentFeed = client.getFeed(query, ContentFeed.class);

如需其他參數,請參閱參考指南

返回頁首



建立內容

注意:製作網站內容之前,請務必先在用戶端中設定網站。
client.site = "siteName";

您可將 HTTP POST 傳送至內容動態饋給,藉此建立新的內容 (網頁、清單頁面、檔案櫃頁面、公告頁面等):

https://sites.google.com/feeds/content/site/siteName

如需支援節點類型的清單,請參閱參考指南中的 kind 參數。

建立新項目 / 頁面

以下範例會在 Site 的頂層中建立新的 webpage、包括網頁內文的 XHTML,並將標題標題設為「New WebPage Title」:

private void setContentBlob(BaseContentEntry<?> entry, String pageContent) {
  XmlBlob xml = new XmlBlob();
  xml.setBlob(pageContent);
  entry.setContent(new XhtmlTextConstruct(xml));
}

public WebPageEntry createWebPage(String title, String content)
    throws MalformedURLException, IOException, ServiceException {
  WebPageEntry entry = new WebPageEntry();
  entry.setTitle(new PlainTextConstruct(title));

  setContentBlob(entry, content); // Entry's HTML content

  return client.insert(new URL(buildContentFeedUrl()), entry);
}

WebPageEntry createdEntry = createWebPage("New Webpage Title", "<b>HTML content</b>");
System.out.println("Created! View at " + createdEntry.getHtmlLink().getHref());

如果要求成功,createdEntry 會包含在伺服器上建立的項目副本。

在「自訂網址路徑」中建立項目/網頁

根據預設,先前的範例會在 http://sites.google.com/site/siteName/new-webpage-title 網址下建立,並將頁面標題設為「New Web Title」(新網頁標題)。也就是說,網址的 <atom:title> 會正規化為 new-webpage-title。如要自訂網頁網址路徑,請設定 <sites:pageName> 元素。

本例會建立一個標題為「File Storage」(檔案儲存空間) 的新 filecabinet 頁面,但透過指定 <sites:pageName> 元素,在網址 http://sites.google.com/site/siteName/files (而非 http://sites.google.com/site/siteName/file-storage) 下建立頁面。

public FileCabinetPageEntry createFileCabinetPage(String title, String content, String customPageName)
    throws MalformedURLException, IOException, ServiceException {
  FileCabinetPageEntry entry = new FileCabinetPageEntry();
  entry.setTitle(new PlainTextConstruct(title));

  setContentBlob(entry, content); // Entry's HTML content

  entry.setPageName(new PageName(customPageName)); // Upload to a custom page path

  return client.insert(new URL(buildContentFeedUrl()), entry);
}

FileCabinetPageEntry createdEntry = createFileCabinetPage("File Storage", "<b>HTML content</b>", "files");
System.out.println("Created! View at " + createdEntry.getHtmlLink().getHref());

伺服器會使用下列優先順序規則為網頁的網址路徑命名:

  1. <sites:pageName> (如果有的話)。必須符合 a-z, A-Z, 0-9, -, _ 的規定。
  2. <atom:title>,如果 pageName 不存在,則不得為空值。正規化會將空白字元截斷至「-」,並移除不符合 a-z, A-Z, 0-9, -, _ 的字元。

建立子頁面

如要在上層頁面下建立子頁面 (子項),您必須在項目中設定上層連結。連結的 href 屬性指向父項節點的自我連結。

public AnnouncementEntry postAnnouncement(String title, String content, AnnouncementsPageEntry parentPage)
    throws MalformedURLException, IOException, ServiceException {
  AnnouncementEntry entry = new AnnouncementEntry();
  entry.setTitle(new PlainTextConstruct(title));

  setContentBlob(entry, content); // Entry's HTML content

  // Set the entry's parent link to create the announcement under that page.
  entry.addLink(SitesLink.Rel.PARENT, Link.Type.ATOM, parentPage.getSelfLink().getHref());

  return client.insert(new URL(buildContentFeedUrl()), entry);
}

ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl() + "?kind=announcementspage"), ContentFeed.class);

AnnouncementEntry createdEntry = postAnnouncement("Party!!", "My place, this weekend", contentFeed.getEntries().get(0));
System.out.println("New post by " + createdEntry.getAuthors().get(0).getName());

上述範例會在使用者內容動態消息中的第一個公告頁面下方建立新的 announcement。公告的標題設為「派對!」,內容則設為「我的地點,本週末」。

頁面範本

建立頁面範本

建立頁面範本的程序與建立新項目/網頁建立子頁面相同,差別在於 category 會新增字詞,並將字詞和標籤設為「http://schemas.google.com/g/2005#template」和「template」。

本範例會建立新的 webpage 範本。

// The template webpage entry.
WebPageEntry entry = new WebPageEntry();

// Set title and content.
entry.setTitle(new PlainTextConstruct("Page template title"));
XmlBlob xml = new XmlBlob();
xml.setBlob("Content for page template");
entry.setContent(new XhtmlTextConstruct(xml));

// Set the template category
Category TEMPLATE_CATEGORY = new Category(TemplateCategory.Scheme.LABELS,
    TemplateCategory.Term.TEMPLATE, TemplateCategory.Label.TEMPLATE);
entry.getCategories().add(TEMPLATE_CATEGORY);

// Insert the template webpage entry.
WebPageEntry createdEntry = client.insert(new URL("https://sites.google.com/feeds/content/site/siteName"), entry);

使用範本建立頁面

與建立頁面範本類似,您可以加入 <link>,並在其中加入指向頁面範本自我連結的 rel='http://schemas.google.com/sites/2008#template',透過範本將新頁面執行個體化。

這個範例會建立新的 filecabinet 範本,然後將該範本的新 filecabinet 頁面執行個體化。

URL feedUrl = new URL("https://sites.google.com/feeds/content/site/siteName");

// 1. Create file cabinet page template
FileCabinetPageEntry inputTemplateEntry = new FileCabinetPageEntry();
inputTemplateEntry.setTitle(new PlainTextConstruct("File cabinet page template title"));
XmlBlob xml = new XmlBlob();
xml.setBlob("Content for page template");
inputTemplateEntry.setContent(new XhtmlTextConstruct(xml));

// Set the template category
Category TEMPLATE_CATEGORY = new Category(TemplateCategory.Scheme.LABELS,
    TemplateCategory.Term.TEMPLATE, TemplateCategory.Label.TEMPLATE);
inputTemplateEntry.getCategories().add(TEMPLATE_CATEGORY);

// 2. Create file cabinet page template instance
FileCabinetPageEntry templateEntry = client.insert(feedUrl, inputTemplateEntry);

// Specify link to the page template
FileCabinetPageEntry templateInstanceEntry = new FileCabinetPageEntry();
templateInstanceEntry.setTitle(new PlainTextConstruct("File cabinet template instance"));
templateInstanceEntry.addLink(new Link(SitesLink.Rel.TEMPLATE, Link.Type.ATOM, templateEntry.getSelfLink().getHref()));

FileCabinetPageEntry createdFileCabinetFromTemplate =  client.insert(feedUrl, templateInstanceEntry);

注意:儘管範本會定義 <category>,但您仍需要在項目中加入一個範本。此外,如果您納入 <content> 元素,伺服器會拒絕該元素。

正在上傳檔案

如同 Google 協作平台,這個 API 支援將附件上傳至檔案櫃頁面或上層頁面。

如要上傳附件給父項,請傳送 HTTP POST 要求至內容動態饋給網址:

https://sites.google.com/feeds/content/site/siteName

所有附件類型都必須上傳至上層頁面。因此,您會在您要上傳的 AttachmentEntryWebAttachmentEntry 物件上設定上層連結。詳情請參閱「建立子頁面」。

正在上傳附件

這個範例會將 PDF 檔案上傳到使用者內容動態饋給中第一個找到的 FileCabinetPageEntry。此附件會使用「開始使用」標題和說明 (選填) 說明「HR 封包」。

MimetypesFileTypeMap mediaTypes = new MimetypesFileTypeMap();
mediaTypes.addMimeTypes("application/msword doc");
mediaTypes.addMimeTypes("application/vnd.ms-excel xls");
mediaTypes.addMimeTypes("application/pdf pdf");
mediaTypes.addMimeTypes("text/richtext rtx");
// ... See a more complete list of mime types in the SitesHelper.java

public AttachmentEntry uploadAttachment(File file, BasePageEntry<?> parentPage,
    String title, String description) throws IOException, ServiceException {
  AttachmentEntry newAttachment = new AttachmentEntry();
  newAttachment.setMediaSource(new MediaFileSource(file, mediaTypes.getContentType(file)));
  newAttachment.setTitle(new PlainTextConstruct(title));
  newAttachment.setSummary(new PlainTextConstruct(description));
  newAttachment.addLink(SitesLink.Rel.PARENT, Link.Type.ATOM, parentPage.getSelfLink().getHref());

  return client.insert(new URL(buildContentFeedUrl()), newAttachment);
}

ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl() + "?kind=filecabinet"), ContentFeed.class);
FileCabinetPageEntry parentPage = contentFeed.getEntries(FileCabinetPageEntry.class).get(0);

AttachmentEntry attachment = uploadAttachment(
    new File("/path/to/your/file.pdf"), parentPage, "Getting Started", "HR packet");
System.out.println("Uploaded!");

如果上傳成功,attachment 會包含已建立附件項目的副本。

將附件上傳至資料夾

如要將附件上傳至 FileCabinetPageEntry 中現有的資料夾,請加入類別,並將「term」屬性設為資料夾名稱。例如,在 uploadAttachment() 中新增這一行:

newAttachment.getCategories().add(new Category("http://schemas.google.com/sites/2008#folder", "FolderName"));

網路附件

網路附件是一種特殊的附件。基本上,這些檔案會連結至網路上的其他檔案,方便您新增至檔案櫃清單。這項功能類似於 Google 協作平台使用者介面中的「透過網址新增檔案」上傳方法。

注意:網路附件只能在檔案櫃頁面中建立。無法上傳至其他類型的頁面。

這個範例會在使用者內容動態饋給中的第一個 FileCabinetPageEntry 下方建立 WebAttachmentEntry。其標題和 (選用) 說明分別設為「GoogleLogo」和「精美顏色」。

public WebAttachmentEntry uploadWebAttachment(String contentUrl, FileCabinetPageEntry filecabinet,
    String title, String description) throws MalformedURLException, IOException, ServiceException {
  MediaContent content = new MediaContent();
  content.setUri(contentUrl);

  WebAttachmentEntry webAttachment = new WebAttachmentEntry();
  webAttachment.setTitle(new PlainTextConstruct(title));
  webAttachment.setSummary(new PlainTextConstruct(description));
  webAttachment.setContent(content);
  webAttachment.addLink(SitesLink.Rel.PARENT, Link.Type.ATOM,
      filecabinet.getSelfLink().getHref());

  return client.insert(new URL(buildContentFeedUrl()), webAttachment);
}

ContentFeed contentFeed = client.getFeed(new URL(buildContentFeedUrl() + "?kind=filecabinet"), ContentFeed.class);
FileCabinetPageEntry parentPage = contentFeed.getEntries(FileCabinetPageEntry.class).get(0);

WebAttachmentEntry webAttachment =
    uploadWebAttachment("http://www.google.com/images/logo.gif", parentPage, "Google's Logo", "nice colors");
System.out.println("Web attachment created!");

POST 會在使用者的檔案櫃中建立指向圖片「http://www.google.com/images/logo.gif」的連結。

返回頁首



更新內容

更新網頁的中繼資料和/或 HTML 內容

您可使用項目的 update() 方法編輯任何 BaseContentEntry 類型的中繼資料 (標題、pageName 等) 和網頁內容。系統會將 HTTP PUT 要求傳送至該項目的 edit 連結。

以下範例說明如何更新 ListPageEntry,進行下列變更:

  • 標題已修改為「更新標題」
  • 網頁的 HTML 內容已更新為「<p>新版 HTML 內容</p>」
  • 清單的第一個欄標題已變更為「擁有者」
ContentFeed contentFeed = client.getFeed(
    new URL(buildContentFeedUrl() + "?kind=listpage"), ContentFeed.class);
ListPageEntry listPage = contentFeed.getEntries(ListPageEntry.class).get(0); // Update first list page found

// Update title
listPage.setTitle(new PlainTextConstruct("Updated Title"));

// Update HTML content
XmlBlob xml = new XmlBlob();
xml.setBlob("<p>Updated HTML Content</p>");
listPage.setContent(new XhtmlTextConstruct(xml));

// Change first column's heading
listPage.getData().getColumns().get(0).setName("Owner");

// listPage.setPageName(new PageName("new-page-path"));  // You can also change the page's URL path

ListPageEntry updatedEntry = listPage.update();

System.out.println("ListPage updated!");

正在更新附件檔案內容

針對 AttachmentEntry,您也可以設定項目的 MediaSource,然後使用該項目的 updateMedia(boolean) 方法,來更新內容。

本例會更新現有附件的內容:

public AttachmentEntry updateFile(AttachmentEntry entry, File newFile)
    throws IOException, ServiceException {
  // See Uploading Attachments for the definition of mediaTypes.
  entry.setMediaSource(new MediaFileSource(newFile, mediaTypes.getContentType(newFile)));
  return entry.updateMedia(false);
}

這個範例會將 HTTP PUT 要求傳送至該項目的 edit-media 連結。傳回的 AttachmentEntry 將包含更新後的內容。

更新附件中繼資料和內容

您可以使用 updateMedia() 方法,在同一呼叫中更新附件的中繼資料及其內容。如果您可以只更新檔案內容、中繼資料,或同時更新兩者,

本例會將附件的標題變更為「新標題」並更新說明,並以新的 .zip 檔案取代檔案內容。由於要求包含新的檔案內容,因此會使用 AttachmentEntryupdateMedia()

public AttachmentEntry updateAttachment(AttachmentEntry entry, File newFile, String newTitle, String newDescription)
    throws IOException, ServiceException  {
  // See Uploading Attachments for the definition of mediaTypes.
  entry.setMediaSource(new MediaFileSource(newFile, mediaTypes.getContentType(newFile)));
  entry.setTitle(new PlainTextConstruct(newTitle));
  entry.setSummary(new PlainTextConstruct(newDescription));

  return entry.updateMedia(true);
}

ContentFeed contentFeed = client.getFeed(
    new URL(buildContentFeedUrl() + "?kind=attachment&max-results=1"), ContentFeed.class);
AttachmentEntry attachment = contentFeed.getEntries(AttachmentEntry.class).get(0); // Update first attachment found

AttachmentEntry updatedAttachment = updateAttachment(attachment, new File("/path/to/file.zip"), "New Title", "better stuff");

返回頁首



正在刪除內容

如要從 Google 網站移除網頁或項目,請先擷取內容項目,然後呼叫該項目的 delete()

entry.delete();

您也可以傳遞項目的 edit 連結和 ETag 值,來使用服務類別的 delete() 方法:

client.delete(entry.getEditLink().getHref(), "*"); // Note: using "*" may overwrite another client's changes.

如果該項目已成功刪除,伺服器會回應 HTTP 200 OK

返回頁首



正在下載附件

如要下載 AttachmentEntry,請傳送 HTTP GET 要求至該項目的內容 src 連結。

以下範例會將使用者在內容動態饋給中找到的第一個 AttachmentEntry 下載至「/path/to/save/file/」目錄:

private void downloadFile(String downloadUrl, String fullFilePath) throws IOException, ServiceException {
  System.out.println("Downloading file from: " + downloadUrl);

  MediaContent mc = new MediaContent();
  mc.setUri(downloadUrl);
  MediaSource ms = service.getMedia(mc);

  InputStream inStream = null;
  FileOutputStream outStream = null;

  try {
    inStream = ms.getInputStream();
    outStream = new FileOutputStream(fullFilePath);

    int c;
    while ((c = inStream.read()) != -1) {
      outStream.write(c);
    }
  } finally {
    if (inStream != null) {
      inStream.close();
    }
    if (outStream != null) {
      outStream.flush();
      outStream.close();
    }
  }
}

public void downloadAttachment(AttachmentEntry entry, String directory) throws IOException, ServiceException {
  String url = ((OutOfLineContent) entry.getContent()).getUri();
  downloadFile(url, directory + entry.getTitle().getPlainText()); // Use entry's title for the save filename
}

ContentFeed contentFeed = client.getFeed(
    new URL(buildContentFeedUrl() + "?kind=attachment&max-results=1"), ContentFeed.class);

downloadAttachment(contentFeed.getEntries(AttachmentEntry.class).get(0), "/path/to/save/file/");
System.out.println("Downloaded.");

返回頁首

ACL 資訊提供

共用權限 (ACL) 總覽

ACL 動態饋給中的每個 ACL 項目都代表特定實體的存取權角色,可以是使用者、使用者群組、網域或預設存取權 (公開網站)。只有明確取得存取權的實體會顯示項目;Google 協作平台 UI 的共用畫面中的「具有存取權的使用者」面板中,每個電子郵件地址會顯示一個項目。因此,系統不會顯示網域管理員,即使他們擁有網站的隱含存取權也一樣。

角色

角色元素代表實體可擁有的存取層級。gAcl:role 元素有四種可能的值:

  • Reader — 檢視者 (相當於唯讀存取權)。
  • writer:協作者 (具備讀取/寫入權限)。
  • owner:通常是網站管理員 (具備讀取/寫入權限)。

範圍

範圍元素代表具備此存取層級的實體。gAcl:scope 元素有四種類型:

  • user:電子郵件地址值,例如「user@gmail.com」。
  • group - Google 網路論壇電子郵件地址,例如「group@domain.com」。
  • domain:G Suite 網域名稱,例如「domain.com」。
  • default - 「default」類型只有一個可能的範圍,且該範圍沒有值 (例如 <gAcl:scope type="default">)。這個特定範圍可控管任何使用者在公開網站上根據預設具備的存取權。

注意:網域不能將 gAcl:role 值設為「owner」(擁有者),只能是讀取者或寫入者。

擷取 ACL 資訊提供

AclFeedAclEntry 類別可用來控制網站的共用權限,且可使用服務類別的 getFeed() 方法擷取。

以下範例會擷取指定網站的 ACL 動態饋給,並列印每個 AclEntry 的權限:

public String getAclFeedUrl(String siteName) {
  String domain = "site";  // OR if the Site is hosted on G Suite, your domain (e.g. example.com)
  return "https://sites.google.com/feeds/acl/site/" + domain + "/" + siteName + "/";
}

public void getAclFeed(String siteName) throws IOException, ServiceException {
  AclFeed aclFeed = client.getFeed(new URL(getAclFeedUrl(siteName)), AclFeed.class);
  for (AclEntry entry : aclFeed.getEntries()) {
    System.out.println(entry.getScope().getValue() + " (" + entry.getScope().getType() + ") : " +
                       entry.getRole().getValue());
  }
}

getAclFeed('my-site-name');

如果使用 SiteFeed 中的項目,每個 SiteEntry 都包含其 ACL 動態饋給的連結。 例如,下列程式碼片段會擷取 SiteEntry 的 acl 動態饋給:

String aclLink = siteEntry.getLink(SitesAclFeedLink.Rel.ACCESS_CONTROL_LIST, Link.Type.ATOM).getHref();
AclFeed aclFeed = client.getFeed(new URL(aclLink), AclFeed.class);

共用網站

注意:某些共用 ACL 可能只有在網域設為允許這類權限時 (例如啟用 G Suite 網域外部共用設定等) 才有可能執行。

如要使用 API 共用 Google 網站,您的用戶端必須建立新的 AclEntry,並將其 POST 至伺服器。

以下範例會將「user@example.com」新增為網站中的 reader

AclRole role = new AclRole("reader");
AclScope scope = new AclScope(AclScope.Type.USER, "user@example.com");
AclEntry aclEntry = addAclRole(role, scope, entry);

public AclEntry addAclRole(AclRole role, AclScope scope, SiteEntry siteEntry)
    throws IOException, MalformedURLException, ServiceException  {
  AclEntry aclEntry = new AclEntry();
  aclEntry.setRole(role);
  aclEntry.setScope(scope);

  Link aclLink = siteEntry.getLink(SitesAclFeedLink.Rel.ACCESS_CONTROL_LIST, Link.Type.ATOM);
  return client.insert(new URL(aclLink.getHref()), aclEntry);
}

如要瞭解可能的 AclScopeAclRoles 值,請參閱 ACL 動態饋給總覽一節。

群組與網域層級共用

與單一使用者共用網站類似,您可以在 Google 群組或 G Suite 網域中共用網站。

與群組電子郵件地址分享:

AclScope scope = new AclScope(AclScope.Type.GROUP, "group_name@example.com");

與整個網域共用:

AclScope scope = new AclScope(AclScope.Type.DOMAIN, "example.com");

網域層級共用功能僅適用於 G Suite 網域,且僅適用於代管網站的網域。 舉例來說,http://sites.google.com/a/domain1.com/siteA 只能與 <網域>1.com 共用整個協作平台,而無法與 <網域>2.com 共用。如果協作平台未是由 G Suite 網域 (例如 http://sites.google.com/site/siteB) 代管,就無法邀請網域。

修改共用權限

如要在網站上現有的共用權限,請先擷取有問題的 AclEntry,視需要修改權限,然後呼叫 AclEntryupdate() 方法,修改伺服器上的 ACL。

本範例將「共用網站」範例中的aclEntry範例更新為 (協作者),也就是將「user@example.com」更新為 writer (協作者):

aclEntry.setRole(new AclRole("writer"));
AclEntry updatedAclEntry = aclEntry.update();

// Could also use the client's update method
// client.update(new URL(aclEntry.getEditLink().getHref()), aclEntry);

如要進一步瞭解 ETag,請參閱 Google Data API 參考指南

正在移除共用權限

如要移除共用權限,請先擷取 AclEntry,然後呼叫其 delete() 方法:

aclEntry.delete();

// Could also use the client's delete method
// client.delete(new URL(aclEntry.getEditLink().getHref()), aclEntry);

如要進一步瞭解 ETag,請參閱 Google Data API 參考指南

返回頁首

特殊主題

再次擷取動態饋給或項目

如要擷取先前擷取的動態饋給或項目,如要提高效率,您可以指示伺服器傳送清單或項目,前提是該清單或項目自上次擷取後有所變更。

如要進行這類條件式擷取,getFeed()getEntry() 方法都會提供額外引數,用於接受 ETag 值,或為 If-Modified-Since 標頭接受 DateTime 物件。您可以透過 entry.getEtag() 存取項目的 Etag。

以下範例會對內容網頁項目進行條件式擷取:

String feedUrl = "https://sites.google.com/feeds/content/site/siteName/123456789";
WebPageEntry entry = client.getEntry(new URL(feedUrl), WebPageEntry.class, "\"GVQHSARDQyp7ImBq\"");

伺服器收到這項要求時,會檢查您要求的項目是否與您指定的 ETag 相同。如果 ETag 相符,則該項目並未變更,且伺服器會傳回 HTTP 304 NotModifiedException 例外狀況。

如果 ETag 不符,表示項目自您上次要求後已修改,且伺服器會傳回商品。

如要進一步瞭解 ETag,請參閱 Google Data API 參考指南

返回頁首