如何使用 Spring 引导和 Java 库在 google 上创建操作
How to create actions on google using Spring Boot & Java Library
我正在尝试使用 Spring Boot & Dialogflow 在 google 上创建操作。我在其中尝试使用可用的 java 库 https://github.com/actions-on-google/actions-on-google-java
但无法理解我应该如何在我的 Spring 引导应用程序中实现这些注释。例如:@ForIntent
我已经尝试使用 App Engine 入口点的样板代码
https://github.com/actions-on-google/dialogflow-webhook-boilerplate-java
我能够 运行 这段代码,但无法理解它在 Spring 启动应用程序中的实现。
在Spring引导:
我们在应用程序中使用@RestController 来映射请求
但是在 google 上执行操作,将只有一个请求 link,我们可以提供作为 Fulfillment webhook。那么我应该在我的代码中的什么地方使用@ForIntent 来识别 Intent 并更改 Request body 和 Response body。
我不知道 Google 上的 Action 是如何工作的,但从更高的层次来看,在示例应用程序中,请求是通过 ActionServlet
处理的
ActionServlet.javaclass,扩展了称为 HttpServlet 的普通旧 java servlet,如果您查看 doPost() 方法:
private final App actionsApp = new MyActionsApp(); ----> Bullet Point - 1
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {
String body = req.getReader().lines().collect(Collectors.joining());
LOG.info("doPost, body = {}", body);
try {
String jsonResponse = actionsApp.handleRequest(body, getHeadersMap(req)).get(); ----> Bullet Point - 2
LOG.info("Generated json = {}", jsonResponse);
res.setContentType("application/json");
writeResponse(res, jsonResponse);
} catch (InterruptedException e) {
handleError(res, e);
} catch (ExecutionException e) {
handleError(res, e);
}
}
所以你的问题是如何在 Spring Boot. Spring 使用 DispatcherServlet 将传入请求映射到控制器,因此在内部 spring 使用类似的机制来映射传入请求。要回答您的问题,在 Spring 引导术语中,您想执行如下操作:
@RestController("/action")
public class ActionController{
@Autowired
private App actionsApp;
@PostMapping("/")
public void handleActions(){
// Similar method call like Bullet Point 2
// I assume handleRequest() method will call the @ForIntent method here ?? No idea
actionsApp.handleRequest(.....);
}
}
并配置 MyActionsApp.java
如下:
@Service
public class MyActionsApp extends DialogflowApp {
private static final Logger LOGGER = LoggerFactory.getLogger(MyActionsApp.class);
@ForIntent("Default Welcome Intent")
public ActionResponse welcome(ActionRequest request) {
LOGGER.info("Welcome intent start.");
ResponseBuilder responseBuilder = getResponseBuilder(request);
ResourceBundle rb = ResourceBundle.getBundle("resources");
User user = request.getUser();
if (user != null && user.getLastSeen() != null) {
responseBuilder.add(rb.getString("welcome_back"));
} else {
responseBuilder.add(rb.getString("welcome"));
}
LOGGER.info("Welcome intent end.");
return responseBuilder.build();
}
@ForIntent("bye")
public ActionResponse bye(ActionRequest request) {
LOGGER.info("Bye intent start.");
ResponseBuilder responseBuilder = getResponseBuilder(request);
ResourceBundle rb = ResourceBundle.getBundle("resources");
responseBuilder.add(rb.getString("bye")).endConversation();
LOGGER.info("Bye intent end.");
return responseBuilder.build();
}
}
PS:我假设 actionsApp.handleRequest(..) 方法将根据其他一些配置调用 @ForIntent。但是,如果您想将 ActionServlet 实现移植到 SpringBoot,这就是实现该操作的方法。
让我知道这是否有效。
我实际上曾经这样做过,并基于 Silly Name Maker 示例。我基于 Spring 引导规范示例之一,所以我不保证这是 'optimal',但它是一个非常干净的实现。
您可以保持 SillyNameMakerApp
不变,不加修改。您可以像这样创建 Spring 引导包装器,而不是 ActionsServlet:
@SpringBootApplication
public class HelloworldApplication {
private static final Logger LOG = LoggerFactory.getLogger(SillyNameMakerApp.class);
private final App actionsApp = new SillyNameMakerApp();
@Value("${TARGET:World}")
String message;
@RestController
class HelloworldController {
@GetMapping("/")
String serveAck() {
return "App is listening but requires valid POST request to respond with Action response.";
}
@RequestMapping(value = "/", method = RequestMethod.POST, produces = { "application/json" })
String serveAction(@RequestBody String body, @RequestHeader Map<String, String> headers) {
try {
return actionsApp.handleRequest(body, headers).get();
} catch (InterruptedException | ExecutionException e) {
return handleError(e);
}
}
private String handleError(Exception e) {
e.printStackTrace();
LOG.error("Error in App.handleRequest ", e);
return "Error handling the intent - " + e.getMessage();
}
}
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
我正在尝试使用 Spring Boot & Dialogflow 在 google 上创建操作。我在其中尝试使用可用的 java 库 https://github.com/actions-on-google/actions-on-google-java
但无法理解我应该如何在我的 Spring 引导应用程序中实现这些注释。例如:@ForIntent
我已经尝试使用 App Engine 入口点的样板代码 https://github.com/actions-on-google/dialogflow-webhook-boilerplate-java 我能够 运行 这段代码,但无法理解它在 Spring 启动应用程序中的实现。
在Spring引导: 我们在应用程序中使用@RestController 来映射请求
但是在 google 上执行操作,将只有一个请求 link,我们可以提供作为 Fulfillment webhook。那么我应该在我的代码中的什么地方使用@ForIntent 来识别 Intent 并更改 Request body 和 Response body。
我不知道 Google 上的 Action 是如何工作的,但从更高的层次来看,在示例应用程序中,请求是通过 ActionServlet
处理的ActionServlet.javaclass,扩展了称为 HttpServlet 的普通旧 java servlet,如果您查看 doPost() 方法:
private final App actionsApp = new MyActionsApp(); ----> Bullet Point - 1
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {
String body = req.getReader().lines().collect(Collectors.joining());
LOG.info("doPost, body = {}", body);
try {
String jsonResponse = actionsApp.handleRequest(body, getHeadersMap(req)).get(); ----> Bullet Point - 2
LOG.info("Generated json = {}", jsonResponse);
res.setContentType("application/json");
writeResponse(res, jsonResponse);
} catch (InterruptedException e) {
handleError(res, e);
} catch (ExecutionException e) {
handleError(res, e);
}
}
所以你的问题是如何在 Spring Boot. Spring 使用 DispatcherServlet 将传入请求映射到控制器,因此在内部 spring 使用类似的机制来映射传入请求。要回答您的问题,在 Spring 引导术语中,您想执行如下操作:
@RestController("/action")
public class ActionController{
@Autowired
private App actionsApp;
@PostMapping("/")
public void handleActions(){
// Similar method call like Bullet Point 2
// I assume handleRequest() method will call the @ForIntent method here ?? No idea
actionsApp.handleRequest(.....);
}
}
并配置 MyActionsApp.java
如下:
@Service
public class MyActionsApp extends DialogflowApp {
private static final Logger LOGGER = LoggerFactory.getLogger(MyActionsApp.class);
@ForIntent("Default Welcome Intent")
public ActionResponse welcome(ActionRequest request) {
LOGGER.info("Welcome intent start.");
ResponseBuilder responseBuilder = getResponseBuilder(request);
ResourceBundle rb = ResourceBundle.getBundle("resources");
User user = request.getUser();
if (user != null && user.getLastSeen() != null) {
responseBuilder.add(rb.getString("welcome_back"));
} else {
responseBuilder.add(rb.getString("welcome"));
}
LOGGER.info("Welcome intent end.");
return responseBuilder.build();
}
@ForIntent("bye")
public ActionResponse bye(ActionRequest request) {
LOGGER.info("Bye intent start.");
ResponseBuilder responseBuilder = getResponseBuilder(request);
ResourceBundle rb = ResourceBundle.getBundle("resources");
responseBuilder.add(rb.getString("bye")).endConversation();
LOGGER.info("Bye intent end.");
return responseBuilder.build();
}
}
PS:我假设 actionsApp.handleRequest(..) 方法将根据其他一些配置调用 @ForIntent。但是,如果您想将 ActionServlet 实现移植到 SpringBoot,这就是实现该操作的方法。
让我知道这是否有效。
我实际上曾经这样做过,并基于 Silly Name Maker 示例。我基于 Spring 引导规范示例之一,所以我不保证这是 'optimal',但它是一个非常干净的实现。
您可以保持 SillyNameMakerApp
不变,不加修改。您可以像这样创建 Spring 引导包装器,而不是 ActionsServlet:
@SpringBootApplication
public class HelloworldApplication {
private static final Logger LOG = LoggerFactory.getLogger(SillyNameMakerApp.class);
private final App actionsApp = new SillyNameMakerApp();
@Value("${TARGET:World}")
String message;
@RestController
class HelloworldController {
@GetMapping("/")
String serveAck() {
return "App is listening but requires valid POST request to respond with Action response.";
}
@RequestMapping(value = "/", method = RequestMethod.POST, produces = { "application/json" })
String serveAction(@RequestBody String body, @RequestHeader Map<String, String> headers) {
try {
return actionsApp.handleRequest(body, headers).get();
} catch (InterruptedException | ExecutionException e) {
return handleError(e);
}
}
private String handleError(Exception e) {
e.printStackTrace();
LOG.error("Error in App.handleRequest ", e);
return "Error handling the intent - " + e.getMessage();
}
}
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}