我刚设法调用Google Drive API来启用文件的推送通知.
设置推送通知的代码如下所示:
public class SampleServlet extends AbstractAppEngineAuthorizationCodeServlet { private final static Logger logger = Logger.getLogger(SampleServlet.class.getName()); private static final long serialVersionUID = 1L; // Constants omitted @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { AuthorizationCodeFlow authFlow = initializeFlow(); Credential credential = authFlow.loadCredential(getUserId(req)); StringBuilder resultFromWatch = new StringBuilder(); Drive drive = new Drive.Builder(Utils.HTTP_TRANSPORT, Utils.JSON_FACTORY, credential).setApplicationName("t").build(); try { Optionalchannel = watchFile(drive, FILE_ID, CHANNEL_ID, "web_hook", "https://mydomain.appspot.com/drive"); String channelStringTmp; if (channel.isPresent()) { channelStringTmp = channel.get().toString(); } else { channelStringTmp = "null..."; } resultFromWatch.append(channelStringTmp); } catch (Exception e) { resultFromWatch.append(e.getMessage()); } final UserService userService = UserServiceFactory.getUserService(); final String thisUrl = req.getRequestURI(); // Send the results as the response PrintWriter respWriter = resp.getWriter(); resp.setStatus(200); resp.setContentType("text/html"); addLoginLogoutButtons(req, resp, resultFromWatch, userService, thisUrl, respWriter); } private static Optional watchFile(Drive service, String fileId, String channelId, String channelType, String channelAddress) throws IOException { final Channel returnValue; Channel channel = new Channel(); channel.setId(channelId); channel.setType(channelType); channel.setAddress(channelAddress); Drive.Files tmp = service.files(); returnValue = tmp.watch(fileId, channel).execute(); return Optional.fromNullable(returnValue); } @Override protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException { return Utils.initializeFlow(); } @Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { return Utils.getRedirectUri(req); } }
从我的浏览器调用servlet doGet并登录后我得到了这个响应:
{ "expiration": "1484565747000", "id": SAME_ID_AS_DEFINED_IN_SERVLET, "kind": "api#channel", "resourceId": A_NEW_ID, "resourceUri": "https:\/\/www.googleapis.com\/drive\/v3\/files\/FILE_ID?acknowledgeAbuse=false&alt=json" }
下一步是定义我的控制器,在修改文件时接收通知.看起来像这样:
@RestController @RequestMapping("/drive") public class ConcreteFileWatchController implements FileWatchController { private final static Logger logger = Logger.getLogger(ConcreteFileWatchController.class.getName()); @RequestMapping(method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { logger.info("Received watch call"); } }
最后,我尝试在部署应用程序之后修改文件(它部署在Google App Engine上),在查看GAE中的日志后,我可以看到有一个调用.但是,我的接收方法没有执行.我只在日志中看到一个附有大json的302.除了我没有注意到我的方法被调用之外,无法真正看到任何错误.该路径甚至在日志中看起来正确.我能做错什么?
有关错误的详情:
当我转到Google Cloud的日志页面时,我看到了这条302消息:
11:34:35.957 POST 302 0 B 22 ms APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html) /drive 10.72.94.97 - - [16/Jan/2017:11:34:35 +0100] "POST /drive HTTP/1.1" 302 - - "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)" "mydomain.appspot.com" ms=22 cpu_ms=0 cpm_usd=0 loading_request=0 instance=- app_engine_release=1.9.48 trace_id=d0e888dd3989e353344e40e41758fdf4
还有一个json看起来像这样:
{ protoPayload: { @ type: "type.googleapis.com/google.appengine.logging.v1.RequestLog" appId: "p~blabla" versionId: "201t113050" requestId: "587ca1bb00ff05706f727465726261636b656e640001323031373031313674313133303530000100" ip: "10.76.94.97" startTime: "2017-01-16T10:34:35.957904Z" endTime: "2017-01-16T10:34:35.980366Z" latency: "0.022462s" method: "POST" resource: "/drive" httpVersion: "HTTP/1.1" status: 302 userAgent: "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)" host: "blabla.appspot.com" instanceIndex: -1 finished: true appEngineRelease: "1.9.48" traceId: "d0e888dd390f41758fdf4" first: true } insertId: "587cf6df9ded23f7" httpRequest: { status: 302 } resource: { type: "gae_app" labels: {…} } timestamp: "2017-01-16T10:34:35.957904Z" labels: { appengine.googleapis.com/version_id: "2017013050" clone_id: "" appengine.googleapis.com/clone_id: "" appengine.googleapis.com/module_id: "default" version_id: "20170116t113050" request_id: "587ca1bb00ff0e9dd0f39f31350001707e6561737974696d657265706f721373031313674313133303530000100" appengine.googleapis.com/request_id: "587ca1bb00ff0e9dd0f39f31350001707e6561737974696d6572653674313133303530000100" module_id: "default" } logName: "projects/blabla/logs/appengine.googleapis.com%2Frequest_log" operation: { id: "587ca1bb00ff0e9dde640001323031373031313674313133303530000100" producer: "appengine.googleapis.com/request_id" first: true last: true } }
web.xml中:
contextConfigLocation /WEB-INF/mvc-dispatcher-servlet.xml CORS com.thetransactioncompany.cors.CORSFilter CORS /* org.springframework.web.context.ContextLoaderListener dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation 1 PlusBasicServlet packagename.PlusBasicServlet PlusBasicServlet /plusbasicservlet PlusSampleServlet packagename.PlusSampleServlet PlusSampleServlet /plussampleservlet FileWatchTestServlet packagename.ConcreteFileWatchController FileWatchTestServlet /drive PlusSampleAuthCallbackServlet packagename.PlusSampleAuthCallbackServlet PlusSampleAuthCallbackServlet /oauth2callback any /plussampleservlet *
日志截图: