by Rafael Fiol

通过拉斐尔·菲奥尔(Rafael Fiol)

如何通过Spring Boot实施Alexa技能 (How to implement an Alexa Skill with Spring Boot)

以及为什么要这样做 (And why you would do such a thing)

There are two ways to implement custom skills for Alexa.

有两种方法可以实现Alexa的自定义技能 。

The first is the most common and is the Amazon-recommended way. Use AWS Lambda, a server-less computer service. There is no shortage of articles and tutorials on the topic. This is not one of them.

第一种是最常见的,也是亚马逊推荐的方式。 使用AWS Lambda (无服务器计算机服务)。 不乏有关该主题的文章和教程。 这不是其中的一个。

The second way is far less common. This is hosting an endpoint using a HTTPS web service that you manage. It is a bit more difficult to find good examples of this approach. This article will attempt to do just that, and will use Spring Boot as the basis for the implementation.

第二种方法远不那么普遍。 这使用您管理的HTTPS Web服务托管端点。 很难找到这种方法的好例子。 本文将尝试做到这一点,并将使用Spring Boot作为实现的基础。

But before we jump into the how, let’s talk about the why:

但在此之前,我们跳进如何 ,让我们来谈谈为什么

  • Why would you not use AWS Lambda?为什么不使用AWS Lambda?
  • Why ignore an Amazon recommendation?为什么忽略亚马逊的建议?

These questions are important. You’ll find reams of great examples and documentation on building Skills with Lambda, and not so much for the alternative. It’s also important if you buy into the premise — which I do — that the world is going server-less. This is a great article on that topic by James Beswick. Going the HTTPS route will lead you down a lonely path, but sometimes that’s OK.

这些问题很重要。 您会发现大量有关使用Lambda构建技能的出色示例和文档,而对于替代方法却没有太多。 如果您接受这样一个前提,那就是同样重要的,我愿意这样做,那就是世界将变得无服务器 。 这是James Beswick关于该主题的精彩文章 。 使用HTTPS路由将带您走上一条孤独的道路,但是有时候没关系。

Here are some reasons why you may want or need to take that lonely path.

这是您可能想要或需要走那条孤独之路的一些原因。

  • You can write your Alexa web services using any programming language.您可以使用任何编程语言编写Alexa Web服务。
  • If you have existing RESTful services already deployed and you want to leverage that infrastructure/investment.如果您已经部署了现有的RESTful服务,并且想要利用该基础架构/投资。
  • If your CISO does not allow off-premise or cloud-based infrastructures.

    如果您的CISO不允许使用场外或基于云的基础架构。

  • If you like lonely paths.如果您喜欢孤独的道路。

In my case, I decided to explore the non-Lambda path primarily because I already had an existing services tier, which I wanted to leverage. There are POJOs and methods I wanted to reuse, without having to expose new endpoints. Of course, I could have created Lambdas that simply fronted those services, and that is a valid pattern. But I didn’t want to add another layer of deployment scripts, testing, and monitoring.

就我而言,我决定探索非Lambda路径主要是因为我已经拥有一个现有的服务层,我想利用它。 有一些我想重用的POJO和方法,而不必暴露新的端点。 当然,我本可以创建仅在这些服务之前的Lambda,这是一个有效的模式。 但是我不想添加另一层部署脚本,测试和监视。

You probably have your own reasons. If I were building a new greenfield application, I’d probably head down the Lambda path.

您可能有自己的原因。 如果我建立一个新的绿地应用程序,我可能会低着头拉姆达路径。

先决条件 (Prerequisites)

You’ll use the Alexa Developer Console to register your skill, define the intents and utterances, and test it. I’ve assumed that you’ve already created a developer account, and that you can setup a new custom Skill within the console.

您将使用Alexa开发人员控制台注册您的技能,定义意图和话语并进行测试。 我假设您已经创建了开发人员帐户,并且可以在控制台中设置新的自定义技能。

Sprint BootAlexa技能 (A Spring Boot Alexa Skill)

The rest of this article will show you how easy it is to add an Alexa Skill to your existing Spring Boot applications. To demonstrate this, we’ll create a skill that will lookup fun facts about either a specific year, or a random year. You’ll be able to interact with our skill by saying things such as:

本文的其余部分将向您展示向现有的Spring Boot应用程序添加Alexa Skill多么容易。 为了说明这一点,我们将创建一种技能,以查找有关特定年份或随机年份的有趣事实。 您可以通过以下方式与我们的技能进行互动:

Alexa, ask my demo app to tell me trivia about a random year.Alexa, ask my demo app, what happened in the year 1984?

Okay, yes, this is a pretty useless skill. But it will demonstrate all of the important aspects of an Alexa app, including:

好的,是的,这是一项非常无用的技能。 但这将展示Alexa应用程序的所有重要方面,包括:

  • custom intent handling自定义意图处理
  • using slots, session management使用插槽,会话管理
  • built-in intent handling内置意图处理

To accomplish this, our example skill will call a free third-party API to lookup the trivia information, using the wonderful NumbersAPI. Many thanks to David and Mack for creating this fun service.

为此,我们的示例技能将使用出色的NumbersAPI调用免费的第三方API来查找琐事信息。 非常感谢David和Mack创造了这项有趣的服务。

入门 (Getting started)

First things first. Add the Alexa Skills Kit SDK to your “pom.xml” file. At the time of writing, the latest version of the SDK is 1.8.1.

首先是第一件事。 将Alexa Skills Kit SDK添加到您的“ pom.xml”文件中。 在撰写本文时,SDK的最新版本是1.8.1。

<dependency>    <groupId>com.amazon.alexa</groupId>    <artifactId>alexa-skills-kit</artifactId>    <version>1.8.1</version></dependency>

The SDK includes a special servlet, named SpeechletServlet, which you will need to load as part of the app bootstrap. This is actually very easy to do.

SDK包含一个名为SpeechletServlet的特殊servlet,您需要在应用程序引导程序中加载该servlet。 这实际上很容易做到。

The servlet is a workhorse. It handles all of the messy requirements for hosting a skill, such as verifying that the request was sent by Alexa, validating the signature, and checking the timestamp. Fortunately for us, we don’t have to deal with any of those headaches. We just need to load the servlet. Here’s how we do that:

servlet是一个主力军。 它处理了托管技能的所有麻烦要求 ,例如验证请求是否由Alexa发送,验证签名以及检查时间戳。 对我们来说幸运的是,我们不必处理任何这些头痛的事情。 我们只需要加载servlet。 我们的操作方法如下:

Simple. You can see above that we’ve created a configuration class that loads our servlet. On line 10, you can see that SpeechletServlet is instantiated, and then on line 13 it is registered with Spring.

简单。 您可以在上面看到我们已经创建了一个配置类来加载我们的servlet。 在第10行,您可以看到SpeechletServlet被实例化,然后在第13行,它已在Spring中注册。

That’s pretty much all you need to do to load the servlet.

这几乎是您加载Servlet所需要做的全部工作。

As I noted, the servlet takes care of all the complicated handshake communications with Alexa. And after it does that, the servlet delegates the actual interaction business logic to a Speechlet, which you must implement. You can see on line 11 that the Speechlet, which I named HandlerSpeechlet, is assigned to the servlet. This Speechlet will be invoked with every Alexa interaction.

如前所述,该servlet负责与Alexa进行的所有复杂的握手通信。 然后,该servlet将实际的交互业务逻辑委托给Speechlet ,您必须实现它。 您可以在第11行看到将我称为HandlerSpeechlet的Speechlet分配给了servlet。 每次Alexa交互都会调用此Speechlet。

A Speechlet is just a POJO that conforms to the SpeechletV2 interface that is defined in the Alexa Skills SDK. Here is what the interface looks like.

Speechlet只是一个POJO,它符合Alexa Skills SDK中定义的SpeechletV2接口。 界面如下所示。

It’s your job to implement those four methods.

实现这四种方法是您的工作。

They’re all important, but most of the work happens in OnIntent(), which is invoked when the user says something meaningful. If you’re new to the vocabulary of Alexa programming, you should read Intents, Utterances, and Slots: The New Vocabulary Needed To Develop For Voice.

它们都很重要,但是大多数工作发生在OnIntent() ,当用户说出有意义的内容时会调用该函数。 如果您不熟悉 Alexa编程的词汇表,则应阅读Intents,Utterances和Slots:需要为语音开发的新词汇表 。

定义意图 (Defining intents)

Jump into the Alexa Developer Console. Set up a new custom skill within the console — that part is very easy. I’ve named my skill “MyDemoApp”, and under the Invocation menu, I set the Skill Invocation Name to “my demo app”.

跳到Alexa开发人员控制台 。 在控制台内设置新的自定义技能-这部分非常简单。 我已将技能命名为“ MyDemoApp”,并且在“调用”菜单下,将“技能调用名称”设置为“我的演示应用程序”。

Recall earlier in this article I said that you can interact with our skill by saying things such as:

回顾本文前面的内容,我曾说过,您可以通过以下方式与我们的技能进行互动:

Alexa, ask my demo app to tell me trivia about a random year.Alexa, ask my demo app, what happened in the year 1984?

You can see that each of the above sentences start with the wake word (“Alexa”) and the Skill Invocation Name (“my demo app”).

您可以看到上述每个句子都以唤醒词(“ Alexa”)和技能调用名称(“ my demo app”)开头。

Alexa, ask my demo app ...

Everything after the Skill Invocation Name is known as an utterance. It’s your job to list utterances in the developer console, and map those to an intent. A single intent normally has many utterances, representing the variations a user might say. For example, all of the following utterances are essentially the same:

技能调用名称之后的所有内容称为话语 。 在开发人员控制台中列出语音,然后将其映射到意图是您的工作。 单个意图通常具有许多话语,代表用户可能会说的变化。 例如,以下所有话语基本上都是相同的:

tell me trivia about a random year.say something about any year.pick a random year.tell me some trivia.say anything about any year.

All of these utterances mean the same thing, and therefore can map to a single intent. In my application, I’ve called this the “RandomYearIntent”. Here’s what it looks like in the developer console.

所有这些话语都是同一件事,因此可以映射到一个意图。 在我的应用程序中,我将其称为“ RandomYearIntent”。 这是开发者控制台中的外观。

返回编写代码 (Back to writing code)

With our first intent defined, it’s now time to jump back into our Spring application and write some code. Let’s edit our “HandlerSpeechlet”. For the moment, let’s skip the onSessionStarted and onLaunch methods of the Speechlet, and jump right into the onIntent method.

定义了我们的第一个意图之后,现在该回到我们的Spring应用程序并编写一些代码了。 让我们编辑“ HandlerSpeechlet”。 目前,让我们跳过Speechlet的onSessionStartedonLaunch方法,然后直接跳到onIntent方法。

Because our application will eventually handle multiple intents, we’ll first need to determine which intent is being invoked.

因为我们的应用程序最终将处理多个意图,所以我们首先需要确定正在调用哪个意图。

On line 10, we now have the name of the intent. In our example so far, this should be RandomYearIntent. At this point, you might be tempted to write a bunch of if-else statements against the intent name, but let’s try something a little smarter.

在第10行,我们现在有了意图的名称。 到目前为止,在我们的示例中,这应该是RandomYearIntent 。 在这一点上,您可能很想针对意图名称编写一堆if-else语句,但是让我们尝试一些更聪明的方法。

By making sure that our intents follow a specific naming convention, we can use some Spring magic to load and invoke specialized handlers for each intent. What follows is not something specific to the Alexa Skills SDK. It’s just my own way of handling multiple intents. There are many ways to implement this logic. Here’s mine.

通过确保我们的意图遵循特定的命名约定,我们可以使用一些Spring魔术来为每个意图加载和调用专门的处理程序。 接下来的内容并不是Alexa Skills SDK特有的。 这只是我自己处理多个意图的方式。 有许多方法可以实现此逻辑。 这是我的。

Let’s start by defining an interface which we’ll use for all of our handlers. Let’s create IntentHandler as:

让我们开始定义一个接口,该接口将用于所有处理程序。 让我们将IntentHandler创建为:

Next, for each intent, we’ll create a class that implements this interface. We’ll also be careful to name our classes the same as the intent name, with the word “Handler” appended. For example, for the intent “RandomYearIntent”, we’ll create a class named RandomYearIntentHandler.

接下来,针对每种意图,我们将创建一个实现此接口的类。 我们还要小心地将类的名称与意图名称相同,并在名称后附加“ Handler”。 例如,对于意图“ RandomYearIntent”,我们将创建一个名为RandomYearIntentHandler的类

Okay, let’s leave this unimplemented for now. We’ll go back to our “HandlerSpeechlet” to add code that will pass control to our new “RandomYearIntentHandler”. The basic strategy is to rely on our naming convention of “IntentName” + “Handler”.

好的,让我们暂时不执行此操作。 我们将回到“ HandlerSpeechlet” 添加将控制权传递给我们新的“ RandomYearIntentHandler”的代码。 基本策略是依靠我们的命名约定“ IntentName” +“ Handler”。

I have removed some details and error handling from the code below so that we can focus on the important bits. At the end of this article, you can find a link to my GitHub repo with the complete code.

我从下面的代码中删除了一些细节和错误处理,以便我们可以专注于重要的部分。 在本文的最后,您可以找到带有完整代码的指向我的GitHub存储库的链接。

Check out lines 12 and 13 below, which construct the class name, then ask Spring to find a registered bean with that name. Then, finally, on line 17, we pass control to that handler.

查看下面构造类名称的第12和13行,然后要求Spring查找具有该名称的已注册bean。 然后,最后,在第17行,我们将控制权传递给该处理程序。

RandomYearIntentHandler (RandomYearIntentHandler)

We now have the plumbing in place to call our specialized intent handlers. Let’s go back to the implementation of our “RandomYearIntentHandler”. This particular intent is simple. Here’s the complete implementation.

现在,我们可以使用管道来调用我们的专业意图处理程序。 让我们回到“ RandomYearIntentHandler”的实现。 这个特定的意图很简单。 这是完整的实现。

Simple! Did you catch the annotation on line 1? That @Component annotation is a cool little trick that will tell Spring to create an instance of this class as a Bean. This is how we’re able to access the handler in our Speechlet, using beanFactory.getBean(handlerBeanName).

简单! 您在第1行抓到注释了吗? 该@Component注释是一个很酷的小技巧,它将告诉Spring将此类的实例创建为Bean。 这就是我们能够使用beanFactory.getBean(handlerBeanName)访问Speechlet中的处理程序的方式。

On line 11 we create a random number between 1900 and the current year. Then we call the Numbers API to get trivia about that year.

在第11行,我们在1900和当前年份之间创建一个随机数。 然后,我们调用Numbers API获取有关该年的琐事。

On lines 14 and 15 we create a Card and a Speech. The Card is what is displayed in your Alexa mobile app — or on the screen in the Echo Show. The Speech is what is spoken back to the user.

在第14和15行上,我们创建了CardSpeechCard是您的Alexa移动应用程序中或回声秀屏幕上显示的内容。 语音就是对用户说的话。

AlexaUtils is a simple class I created. I won’t go into the details here, but you can review it on GitHub.

AlexaUtils是我创建的一个简单类。 我不会在这里详细介绍,但是您可以在GitHub上进行查看。

那很容易-插槽呢? (That was easy — what about slots?)

Slots are basically variables in utterances. Look back at the two intents in our application. The second intent, which I’ll name “SpecificYearIntent”, allows the user to say any year. For example:

基本上说来,槽是可变的 。 回顾一下我们应用程序中的两个意图。 第二个意图(我将其命名为“ SpecificYearIntent”)允许用户说出任何年份。 例如:

Alexa, ask my demo app, what happened in the year 1984?

In the above utterance, the year is highly variable. We do not want to define an utterance for every possible year. Instead, we’ll define this utterance using a slot, as:

在上述话语中,年份是高度可变的。 我们不想定义每个可能年份的发音。 相反,我们将使用广告位将此话语定义为:

Alexa, ask my demo app, what happened in the year {Year}?

{Year} represents a number. Jumping back into our developer console, we’ll setup a new “SpecificYearIntent” intent with its associated utterances as follows:

{Year}代表一个数字。 回到开发人员控制台,我们将设置一个新的“ SpecificYearIntent”意图及其相关的话语,如下所示:

I’ve defined a Slot named “Year”, which is of type “AMAZON.NUMBER”. Now, in my handler, I can fetch the slot value easily by name.

我定义了一个名为“年”的插槽,其类型为“ AMAZON.NUMBER”。 现在,在我的处理程序中,我可以按名称轻松获取插槽值。

Line 13 is where we resolve the year Slot. The rest is all boilerplate Java code, which follows the same pattern as the first intent — call the NumbersAPI service for the year and handle the response.

第13行是我们解决Slot 。 其余的都是样板Java代码,其遵循与第一个意图相同的模式-调用Years的NumbersAPI服务并处理响应。

会话和状态 (Sessions and state)

I didn’t get into the OnSessionStarted or OnLaunch methods of the Speechlet in this article, but I did include an implementation for OnLaunch in the sample project in GitHub.

在本文中,我没有涉及Speechlet的OnSessionStartedOnLaunch方法,但在GitHub的示例项目中确实包含了OnLaunch的实现。

You can use the Session object to store variables that will be retained across invocations when in conversation mode. Conversation mode occurs when the user invokes your skill but does not speak a recognized utterance. For example:

您可以在会话模式下使用Session对象存储将在调用之间保留的变量。 当用户调用您的技能但不说出公认的语音时,就会发生对话模式。 例如:

Alex, open my demo app.
>> Hello.  Here are some things you can say: Tell me something about a random year.  Or, what happened in nineteen eighty-nine?
What happened in the year 1984?
>> 1984 is the year that the European Economic Community makes £1.8 million available to help combat the Ethiopian famine on October 25th.
>> What else can I tell you? Say "Help" for some suggestions.
Cancel.
>> OK.  Goodbye.

You’ll notice in my source code that I have a method named setConversationMode. It simply sets a variable in the Session, letting me know that we are in conversation mode.

您会在我的源代码中注意到,我有一个名为setConversationMode的方法。 它只是在Session中设置了一个变量,让我知道我们处于对话模式。

摘要 (Summary)

Writing Alexa skills with Spring Boot is quite easy, and can be a powerful way to reuse your existing infrastructure. Download the complete app from GitHub for more details.

使用Spring Boot编写Alexa技能非常容易,并且可以成为重用现有基础架构的有效方法。 从GitHub下载完整的应用程序以获取更多详细信息。

And if you’re in the South Florida area, you can use my Cutler Stew Skill (built with Spring Boot) to learn when and where my band Cutler Stew is performing next.

如果您在南佛罗里达地区,则可以使用我的Cutler Stew技能 (由Spring Boot构建)来了解我的Cutler Stew乐队接下来何时何地演出。

翻译自: https://www.freecodecamp.org/news/implementing-an-alexa-skill-with-spring-boot-also-why-would-you-do-such-a-thing-9992c0797646/

如何通过Spring Boot实施Alexa技能相关推荐

  1. Spring Boot面试的终极指南

    在本文中,我们探讨了针对经验丰富或新手的Spring Boot面试问答.我们正在尝试分享经验和知识,以帮助您提升作为Spring Boot Developer的职业. 问:什么是Spring Boot ...

  2. 护网必备技能:Spring Boot 接口数据加解密 功能实现

    护网必备技能:Spring Boot 接口数据加解密 功能实现 文章目录 护网必备技能:Spring Boot 接口数据加解密 功能实现 1. 尽量少改动,不影响之前的业务逻辑: 2. 考虑到时间紧迫 ...

  3. spring boot社区疫苗接种管理系统毕业设计源码281442

    Springboot+社区疫苗接种管理系统 摘 要 预防预接种工作实行网络信息化管理,是我国免疫规划工作发展的需要.接种信息实行网络信息化不仅是预防接种工作步入了一个新的台阶,更重要的是解决了多年疫苗 ...

  4. (附源码)spring boot物联网智能管理平台 毕业设计 211120

    目   录 第1章  前  言 1.1  研究背景 1.2  研究现状 1.3  系统开发目标 第2章  相关技术 2.1 开发技术 2.2  spring boot框架介绍 2.3 MySQL数据库 ...

  5. 小程序+spring boot校园交友平台毕业设计-附源码191733

    摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,校园交友小程序被用户普遍使用,为方便用户能够 ...

  6. spring boot物联网智能管理平台 毕业设计-附源码211120

    目   录 第1章  前  言 1 1.1  研究背景 1 1.2  研究现状 1 1.3  系统开发目标 2 第2章  相关技术 3 2.1 开发技术 3 2.2  spring boot框架介绍 ...

  7. (附源码)spring boot基于微信小程序的口腔诊所预约系统 毕业设计 201738

    小程序springboot口腔诊所预约系统 摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱, ...

  8. 老婆问我Spring Boot怎么学

    近几年,微服务架构一直是互联网行业的热点之一,并且被公认为是 IT 软件架构的未来方向. 微服务架构是一种灵活的演进式架构,它不仅能提升企业研发效能,同时可以赋能业务快速创新,不管你是一个什么级别的程 ...

  9. (附源码)spring boot网上求职招聘系统 毕业设计 081201

    网上求职招聘系统 摘  要 随着社会的发展,社会的各行各业都在利用信息化时代的优势.计算机的优势和普及使得各种信息系统的开发成为必需. 网上求职招聘系统,主要的模块包括查看:首页.站点管理(轮播图.公 ...

  10. (附源码)spring boot学业指导系统 毕业设计 030958

    基于Springboot的学业指导APP 摘要 建立.加强和完善学业指导工作是高等教育培养优秀毕业生的一项基础保障,也是提高学生专业学习质量和技能的有效机制,高等学校学业指导工作的开展还需要给予高度重 ...

最新文章

  1. 企业网络翻译官——DNS
  2. 网络推广专员带大家了解网站优化中长尾词的特征与优势!
  3. 详解Linux2.6内核中基于platform机制的驱动模型 (经典)
  4. JavaWeb--数据库添加
  5. ubuntu中安装wmware-tools
  6. 手把手教你玩转ARP包(四)
  7. (一)低功耗设计目的与功耗的类型
  8. python等腰梯形_简单空实心图形打印|Python练习系列[3]
  9. 物联网应用层安全威胁_物联网安全国家标准发布,物联网安全产业链确立
  10. android开发之调皮的权限
  11. 详解淘宝直播背后的技术!
  12. 微信小程序获取 openid
  13. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_11_常用的函数式接口_Consumer接口练习...
  14. vue监听数组元素属性的变化_为什么Vue3.0不再使用defineProperty实现数据监听?
  15. 第八周项目4-个人所得税计算器
  16. 单元测试框架TestableMock快速入门(五):复用Mock类与方法
  17. 渗透测试基础总结(脚本小子)
  18. 如何用公式计算计算机的及格率,及格率和优秀率公式 在excel中如何计算及...
  19. 北鲲云联合珠海中科先进技术研究院推出代算服务
  20. C++ :线程的暂停、恢复和停止

热门文章

  1. 上海电信中兴B860A 4K版破解
  2. 再读红宝书(第四版)第二章 html 中的 javascript
  3. log4cpp编译安装
  4. Ant适用的省市区联动数据
  5. 低功耗电波钟的制作 - 电子设计竞赛
  6. 迈高图手机版_迈高图下载-迈高图最新版下载[地图软件]-天极下载
  7. CreateThread()与_beginthread()的区别详细解析
  8. limeSurvey资料
  9. 计算机基础常见八股问题集合(含计算机网络,操作系统,计算机组成,数据结构与算法,数据库)
  10. 前轮反馈控制(Stanley) 法