Google 推送通知 java 处理程序

Google push notifications java handler

我已订阅我的应用程序以收听 Google 推送通知。频道详细信息已保留。我可以从 google 接收通知到我的端点。

@PostMapping("/google/calendars/")
public void watch(HttpServletRequest request,
  @RequestHeader(value = "X-Goog-Channel-ID", required = false) String googleChannelId,
  @RequestHeader(value = "X-Goog-Channel-Token", required = false) String googleChannelToken,
  @RequestHeader(value = "X-Goog-Channel-Expiration", required = false) String googleChannelExpiration,
  @RequestHeader(value = "X-Goog-Resource-ID", required = false) String googleResourceId,
  @RequestHeader(value = "X-Goog-Resource-URI", required = false) String googleResourceUri,
  @RequestHeader(value = "X-Goog-Resource-State", required = false) String googleResourceState,
  @RequestHeader(value = "X-Goog-Message-Number", required = false) String googleMessageNumber,

使用收到的信息我可以打开client到google服务。但是我不知道怎么修改。

googleChannelId=354a78aa-0cc0-4b5b-96c5-e54e03a51e68
googleChannelToken=<null>
googleChannelExpiration=Sat, 18 Mar 2017 17:01:56 GMT
googleResourceId=eVHbdUeaWhfQPpvJPU7VZRxYzUs
googleResourceUri=https://www.googleapis.com/calendar/v3/calendars/sergii_vlasiuk@ukr.net/events?maxResults=250&alt=json
googleResourceState=exists
googleMessageNumber=403802722

exists 表示 googleResourceId 已更改。

使用 googleChannelId 我加载我的频道详细信息并打开客户端。


  1. 如何在我的拉取更改请求中使用 googleResourceId(可能是请求示例)?
  2. 是否理解正确: not_exists表示资源被删除; exists 表示资源已创建或编辑?

添加详细信息

我试过了

client.events().get(originalCalendarId, googleResourceId).execute()

其中:

  1. clientcom.google.api.services.calendar.Calendar object 并且标记正确。
  2. ginalCalendarId - 众所周知 google 日历 ID,其中一个用于订阅。
  3. googleResourceId - 来自 header 消息 X-Goog-Resource-ID 值。 ->

    404 未找到 { "code" : 404, "errors":[{ "domain" : "global", "message" : "Not Found", "reason" : "notFound" } ], "message" : "Not Found" }

But I do not know how to get changes.

Google 日历 API 提供推送通知,让您可以关注资源的变化。您可以使用此功能来提高应用程序的性能。它允许您消除轮询资源以确定它们是否已更改所涉及的额外网络和计算成本。每当监视的资源发生变化时,Google 日历 API 会通知您的应用程序

一旦您正确设置了手表,您的应用程序就会在发生变化时收到通知。你不需要检查它。

例子

POST https://www.googleapis.com/calendar/v3/calendars/my_calendar@gmail.com/events/watch
Authorization: Bearer auth_token_for_current_user
Content-Type: application/json

{
  "id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
  "type": "web_hook",
  "address": "https://example.com/notifications", // Your receiving URL.
  ...
  "token": "target=myApp-myCalendarChannelDest", // (Optional) Your channel token.
  "expiration": 1426325213000 // (Optional) Your requested channel expiration time.
  }
}

文档中有一篇关于如何设置它的完整文章Push Notifications

注:

此语句无效,因为 Events.get 需要 event Id 作为第二个参数,而不是您的 GoogleResourceId

 client.events().get(originalCalendarId, googleResourceId).execute()

手表的工作原理:

  1. 您决定要监视用户事件的变化。你创建了一个watch on the events。 Google returns 给你 resourceId 这个标识手表。
  2. 已进行更改 google 以 HTTP Post 的形式向您发送 notification。它包含您手表的资源 ID。
  3. 您知道具有此资源 ID 的手表在某个用户事件中被点赞。您使用刷新令牌来访问用户帐户。您执行 events list 并扫描每个事件以查找发生变化的事件。

资源 ID 不能用于请求事件。手表不会告诉您具体更改了什么或何时更改。您必须查询 API 才能找到答案。

如果 Google 没有方便的方法来区分哪些实体已更新,我想我们应该考虑一个解决方法。在我看来,通过遍历和重写所有数据来获取所有事件并更新数据库状态会导致一些性能问题。

为了解决这个问题,我会选择使用每个事件具有的 "etag" 值。每次更新事件时,ETag 都会更改(适用于 CalDav 协议)

http://cdn.nsoftware.com/help/IP9/cs/CalDAV_p_ETag.htm

如果您将 etag 与您的事件一起保存到数据库中,那么一旦您从 Google 获得事件列表,您就可以只检查 etag 值并仅更新真正更改的元素。当您更新条目时,必须优化该部分。

Google 支持etag。 你可以在这里找到它:

https://developers.google.com/google-apps/calendar/v3/reference/events/list

{
  "kind": "calendar#events",
  "etag": etag,
  "summary": string,
  "description": string,
  "updated": datetime,
  "timeZone": string,
  "accessRole": string,
  "defaultReminders": [
    {
      "method": string,
      "minutes": integer
    }
  ],
  "nextPageToken": string,
  "nextSyncToken": string,
  "items": [
    events Resource
  ]
}

更新:

有一种更方便的同步方式。 您可以使用增量同步方法。增量同步允许您检索自上次同步请求以来已修改的所有资源。

https://developers.google.com/google-apps/calendar/v3/sync#initial_full_sync

您只需在每次更新数据时保存同步令牌,并在请求中使用它来获取新数据。在这种情况下,您将仅获得修改过的数据。

Calendar.Events.List request = client.events().list("primary");
request.setSyncToken(syncToken);

如果你打电话的话:

events = request.execute();
List<Event> items = events.getItems();

您只会获得更新后的数据。