Java 中的数据存储导出逻辑
Datastore export logic in Java
值得庆幸的是,Google 宣布了云数据存储的导出逻辑。我想在我的平台上设置时间表导出。然而,它不是 Python,而是 Java。所以我需要用cron.xml和Java的逻辑来设计这个逻辑。
在Java中是否有设计Datastore导出逻辑(cloud_datastore_admin.py)的参考?特别是,我需要在 Java
中转换这部分
app = webapp2.WSGIApplication(
[
('/cloud-datastore-export', Export),
], debug=True)
您显示的代码片段只是特定于第一代标准环境 python 应用程序的典型 GAE 应用程序框架的一部分。您可以在 main.py section of the python quickstart Hello World code review 中轻松识别它。
代码初始化 app
变量(来自 main
python 模块,即 main.py
文件),该变量在 app.yaml
处理程序中引用配置为 script: main.app
.
相应的 java 应用框架明显不同,请参阅 java 快速入门 Hello World code review。但不用担心,您不需要专门转换该代码片段,您只需要构建您的 java 应用程序框架并专注于应用程序处理程序实际执行的操作 - 向数据存储发出那些 POST
请求.抱歉,我不能提供更多帮助,但我不是 java 用户。
我真正意识到的是 app.yaml 就像 java 中的 Web.xml
而 cloud-datastore-export 是一个与 gae 通信以导出数据的 servlet,但我不能做更多
您可以通过following these instructions为App Egnine创建骨架。
一旦你有了骨架,添加这样的东西来处理导出请求:
CloudDatastoreExport.java
package com.google.example.datastore;
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import com.google.apphosting.api.ApiProxy;
import com.google.common.io.CharStreams;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Logger;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
@WebServlet(name = "CloudDatastoreExport", value = "/cloud-datastore-export")
public class CloudDatastoreExport extends HttpServlet {
private static final Logger log = Logger.getLogger(CloudDatastoreExport.class.getName());
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// Verify outputURL parameter
String outputUrlPrefix = request.getParameter("output_url_prefix");
if (outputUrlPrefix == null || !outputUrlPrefix.matches("^gs://.*")) {
response.setStatus(HttpServletResponse.SC_CONFLICT);
response.setContentType("text/plain");
response.getWriter().println("Error: Must provide a valid output_url_prefix.");
} else {
// Get project ID
String projectId = ApiProxy.getCurrentEnvironment().getAppId();
// Remove partition information to get plain app ID
String appId = projectId.replaceFirst("(.*~)", "");
// Get access token
ArrayList<String> scopes = new ArrayList<String>();
scopes.add("https://www.googleapis.com/auth/datastore");
final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
final AppIdentityService.GetAccessTokenResult accessToken =
appIdentity.getAccessToken(scopes);
// Read export parameters
// If output prefix does not end with slash, add a timestamp
if (!outputUrlPrefix.substring(outputUrlPrefix.length() - 1).contentEquals("/")) {
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
outputUrlPrefix = outputUrlPrefix + "/" + timeStamp + "/";
}
String[] namespaces = request.getParameterValues("namespace_id");
String[] kinds = request.getParameterValues("kind");
// Build export request
JSONObject exportRequest = new JSONObject();
exportRequest.put("output_url_prefix", outputUrlPrefix);
JSONObject entityFilter = new JSONObject();
if (kinds != null) {
JSONArray kindsJSON = new JSONArray(kinds);
entityFilter.put("kinds", kinds);
}
if (namespaces != null) {
JSONArray namespacesJSON = new JSONArray(namespaces);
entityFilter.put("namespaceIds", namespacesJSON);
}
exportRequest.put("entityFilter", entityFilter);
URL url = new URL("https://datastore.googleapis.com/v1/projects/" + appId + ":export");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
exportRequest.write(writer);
writer.close();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
JSONTokener exportResponseTokens = new JSONTokener(connection.getInputStream());
JSONObject exportResponse = new JSONObject(exportResponseTokens);
response.setContentType("text/plain");
response.getWriter().println("Export started:\n" + exportResponse.toString(4));
} else {
InputStream s = connection.getErrorStream();
InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8);
String errorMessage =
String.format(
"got error (%d) response %s from %s",
connection.getResponseCode(), CharStreams.toString(r), connection.toString());
log.warning(errorMessage);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("text/plain");
response.getWriter().println("Failed to initiate export.");
}
}
}
}
您可以使用文档中的相同 cron.yaml
:
cron:
- description: "Daily Cloud Datastore Export"
url: /cloud-datastore-export?namespace_id=&output_url_prefix=gs://BUCKET_NAME[/NAMESPACE_PATH]
target: cloud-datastore-admin
schedule: every 24 hours
使用 gcloud 部署 cron 作业:
gcloud app deploy cron.yaml
确保完成此部分以授予 GAE 导出和存储桶权限,否则
你会得到权限被拒绝的错误:
https://cloud.google.com/datastore/docs/schedule-export#before_you_begin
值得庆幸的是,Google 宣布了云数据存储的导出逻辑。我想在我的平台上设置时间表导出。然而,它不是 Python,而是 Java。所以我需要用cron.xml和Java的逻辑来设计这个逻辑。
在Java中是否有设计Datastore导出逻辑(cloud_datastore_admin.py)的参考?特别是,我需要在 Java
中转换这部分app = webapp2.WSGIApplication(
[
('/cloud-datastore-export', Export),
], debug=True)
您显示的代码片段只是特定于第一代标准环境 python 应用程序的典型 GAE 应用程序框架的一部分。您可以在 main.py section of the python quickstart Hello World code review 中轻松识别它。
代码初始化 app
变量(来自 main
python 模块,即 main.py
文件),该变量在 app.yaml
处理程序中引用配置为 script: main.app
.
相应的 java 应用框架明显不同,请参阅 java 快速入门 Hello World code review。但不用担心,您不需要专门转换该代码片段,您只需要构建您的 java 应用程序框架并专注于应用程序处理程序实际执行的操作 - 向数据存储发出那些 POST
请求.抱歉,我不能提供更多帮助,但我不是 java 用户。
我真正意识到的是 app.yaml 就像 java 中的 Web.xml 而 cloud-datastore-export 是一个与 gae 通信以导出数据的 servlet,但我不能做更多
您可以通过following these instructions为App Egnine创建骨架。
一旦你有了骨架,添加这样的东西来处理导出请求:
CloudDatastoreExport.java
package com.google.example.datastore;
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import com.google.apphosting.api.ApiProxy;
import com.google.common.io.CharStreams;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Logger;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
@WebServlet(name = "CloudDatastoreExport", value = "/cloud-datastore-export")
public class CloudDatastoreExport extends HttpServlet {
private static final Logger log = Logger.getLogger(CloudDatastoreExport.class.getName());
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// Verify outputURL parameter
String outputUrlPrefix = request.getParameter("output_url_prefix");
if (outputUrlPrefix == null || !outputUrlPrefix.matches("^gs://.*")) {
response.setStatus(HttpServletResponse.SC_CONFLICT);
response.setContentType("text/plain");
response.getWriter().println("Error: Must provide a valid output_url_prefix.");
} else {
// Get project ID
String projectId = ApiProxy.getCurrentEnvironment().getAppId();
// Remove partition information to get plain app ID
String appId = projectId.replaceFirst("(.*~)", "");
// Get access token
ArrayList<String> scopes = new ArrayList<String>();
scopes.add("https://www.googleapis.com/auth/datastore");
final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
final AppIdentityService.GetAccessTokenResult accessToken =
appIdentity.getAccessToken(scopes);
// Read export parameters
// If output prefix does not end with slash, add a timestamp
if (!outputUrlPrefix.substring(outputUrlPrefix.length() - 1).contentEquals("/")) {
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
outputUrlPrefix = outputUrlPrefix + "/" + timeStamp + "/";
}
String[] namespaces = request.getParameterValues("namespace_id");
String[] kinds = request.getParameterValues("kind");
// Build export request
JSONObject exportRequest = new JSONObject();
exportRequest.put("output_url_prefix", outputUrlPrefix);
JSONObject entityFilter = new JSONObject();
if (kinds != null) {
JSONArray kindsJSON = new JSONArray(kinds);
entityFilter.put("kinds", kinds);
}
if (namespaces != null) {
JSONArray namespacesJSON = new JSONArray(namespaces);
entityFilter.put("namespaceIds", namespacesJSON);
}
exportRequest.put("entityFilter", entityFilter);
URL url = new URL("https://datastore.googleapis.com/v1/projects/" + appId + ":export");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
exportRequest.write(writer);
writer.close();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
JSONTokener exportResponseTokens = new JSONTokener(connection.getInputStream());
JSONObject exportResponse = new JSONObject(exportResponseTokens);
response.setContentType("text/plain");
response.getWriter().println("Export started:\n" + exportResponse.toString(4));
} else {
InputStream s = connection.getErrorStream();
InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8);
String errorMessage =
String.format(
"got error (%d) response %s from %s",
connection.getResponseCode(), CharStreams.toString(r), connection.toString());
log.warning(errorMessage);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("text/plain");
response.getWriter().println("Failed to initiate export.");
}
}
}
}
您可以使用文档中的相同 cron.yaml
:
cron:
- description: "Daily Cloud Datastore Export"
url: /cloud-datastore-export?namespace_id=&output_url_prefix=gs://BUCKET_NAME[/NAMESPACE_PATH]
target: cloud-datastore-admin
schedule: every 24 hours
使用 gcloud 部署 cron 作业:
gcloud app deploy cron.yaml
确保完成此部分以授予 GAE 导出和存储桶权限,否则 你会得到权限被拒绝的错误:
https://cloud.google.com/datastore/docs/schedule-export#before_you_begin