体验 Scala 语言的 Play Web 框架

简介: 体验 Scala 语言的 Play Web 框架

1. 概览

在本文中将介绍 Scala 的 Play Web 开发框架。我们将会学习如何创建一个 Play 项目,使用开发工具生成我们的第一个项目以及实现自定义的功能,另外还将体验一下 Play 框架的测试能力。

对于 Java 开发者来说,也可以看这篇文章 Introduction To Play In Java

2. 项目搭建

在开始之前,我们需要安装 sbt 命令行工具 (至少是 JDK 8 及以上),在本文中我们将使用 sbt 1.6.2 来安装 Play Framework 2.8.16

3. 命令行工具

Play 框架官方文档提到 sbt 是一个强大的控制台和构建工具,我们可以从使用 sbt 工具生成一个空白的 Play 框架的项目开始。

sbt new playframework/play-scala-seed.g8
复制代码

f326aa302c60450493649df05df91650_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

在依赖信息加载完成后,该工具将提示并要求我们输入新项目的名称和组织信息

This template generates a Play Scala project 
name [play-scala-seed]:
复制代码

我们给这个项目命名为 baeldung-play-framework.。组织的名称将会作为项目中包的名称,Scala 的包名的命名规则和 Java 的包名命名规则一样,因此我可以可以给包命名为 baeldung.com

2839ee8dc56c46569659e5229f84a926_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

现在,我们可以进入到 baeldung-play-framework 项目文件夹中并启动该项目

cd baeldung-play-framework 
sbt run
复制代码

这是我们第一次启动项目,可能会花点时间在构建和编译上。

d98dde81a71748b79fb12fa17d797eab_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

178411950cd24ce88aa032fa1430a7cd_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

92ac5f5327544083b45f98af47505090_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

完成后我们可以通过浏览器进入 http://localhost:9000/ 就可以看到默认的欢迎页面了

ddde467cfc0b44a0a603aef17743717d_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

到目前为止我们已经通过 Play 框架创建了一个正在运行的 HTTP 服务器,并且没有书写一行代码就完成了。

4. 项目结构

现在,可以使用 IntelliJ IDE 打开项目并查看项目的目录结构

b9cf14c5530e4a8897f15c346b4f5808_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

在项目目录中,有四个文件夹是由 sbt 模板创建的,分别是 app/controllers, app/views, confpublic

  • controllers 目录用来保存 Scala 代码
  • views 目录用来保存 HTML 模板
  • conf 保存着路由配置既请求的 URL 地址和类以及函数的映射关系
  • public 目录保存着 Play 框架服务器的一些静态内容
baedung-play-framework$ tree -L 2
.
├── app
│   ├── controllers
│   └── views
├── build.sbt
├── build.sc
├── conf
│   ├── application.conf
│   ├── logback.xml
│   ├── messages
│   └── routes
├── logs
│   └── application.log
├── project
│   ├── build.properties
│   ├── plugins.sbt
│   ├── project
│   └── target
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
├── target
│   ├── global-logging
│   ├── scala-2.13
│   ├── streams
│   ├── task-temp-directory
│   └── web
└── test
    └── controllers
20 directories, 9 files
复制代码

这就是目前我们需要了解的关于项目的目录结构。

5. 第一次变更

Play 框架为我们提供了一个“点击刷新工作流”。意味着我们可以通过刷新浏览器就可以查看更改后的内容,而无需重新启动服务器。

首先我们在 app/views 文件夹下创建一个新文件并命名为 firstexample.scala.html

7b318f447a3c4adb9abe26fd1a2eb2d1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

打开这个文件并输入以下代码:

@()
@main("Welcome to Introductio to Play Framework"){
  <h1>Welcome to Introduction to Play Framework</h1>
}
复制代码

除了修改 HTML 文件,我们还必须修改 Scala 代码。打开 app/controllers/HomeController.scalas 文件并将:Ok(views.html.index()) 更改为 Ok(viewers.html.firstexample())

def index() = Action { implicit request: Request[AnyContent] =>
  Ok(views.html.index())
}
复制代码
def index() = Action { implicit request: Request[AnyContent] =>
  Ok(views.html.firstexample())
}
复制代码

查看仍在运行的 Play 服务器的输出时,没有看到任何新内容。似乎更改未生效。

但是,当我们点击浏览器中的 “刷新” 按钮时,我们将在浏览器窗口中看到以下内容:

image.png

6. 如何定义一个新的请求

在前面的示例中,我们对代码进行了一些更改,并看到了更改后的结果。现在,让我们看看 Play 框架项目的内部结构,了解它是如何工作的,以及我们还可以做什么。

当 Play 项目服务器接收到请求时,它首先会检查 conf/routes 文件,以确定哪个 Controller 控制器和方法将处理该请求。在 Controller 控制器内部定义并在路由文件中使用的方法称为 Action。

我们想在 HomeController 控制器中定义一个新的 Action 以及路由,这个 Action 将会从 URL 地址中接收到两个参数并且打印出这两个数的和。简单来说我们将从 URL 中读取两个数并且在页面中展示这两个数的和

为了实现这个功能,我们需要在 HomeController.scala 控制器中添加新的方法,这个方法接收两个参数,计算它们的和并传递到视图模板中渲染。

def printSum(first: Long, second: Long) = Action { implicit  request: Request[AnyContent] =>
  val sum = first + second
  Ok(views.html.index(sum))
}
复制代码

image.png

现在打开视图模板 index.scala.html,在模板顶部添加 sum 参数并在内容中使用这个参数

@(sum: Long)
@main("Add two numbers") {
  <h1>The sum is @sum</h1>
}
复制代码

image.png

我们刚刚定义了一个生成页面的函数。视图文件的第一行描述函数参数。其他行是生成输出的代码。

sum 参数在 HomeController.scala 中计算并传递给 Ok 函数,该函数返回状态代码为 200 内容为 OK

最后我们需要打开 conf/routes 文件并添加一个新的路径和 action

# add two numbers
GET /sum/:first/:second controllers.HomeController.printSum(first: Long, second: Long)
复制代码

image.png

该路由包含了三个部分,第一个是 HTTP 的请求方式,接着我们定义了路径以及参数,这里我们使用两个变量 first 和 second 来计算 sum 参数。

最后我们通过指定 Controller 以及处理请求的 action,需要注意的是我们在路径中使用的参数正是函数中用到的参数。

在浏览器中打开如下地址 http://localhost:9000/sum/5/15 就可以看到这个页面

image.png

7. 编写测试用例

最后,我们来看看有 sbt 命令行工具在创建 Play 框架项目的时候生成的测试用例文件夹。

tests/controllers 目录下打开 HomeControllerSpec 文件时,我们会看到 ScalaTest 的一些规范。

image.png

为了使测试用例更完整,我们需要为我们路由编写测试用例。定义一个名为 “render a page that prints the sum of two numbers” 的新测试用例,该测试用例会调用 /sum 路由并带有两个路径参数

"render a page that prints the sum of two numbers" in {
  val request = FakeRequest(GET, "/sum/10/20")
  val sumOfNumbers = route(app, request).get
}
复制代码

调用完之后还需要添加断言来判断结果,在这个测试用例中我们期望看到 “The sum is 30” 在 HTML 页面上渲染出来。

// 断言内容
status(sumOfNumbers) mustBe OK
contentType(sumOfNumbers) mustBe Some("text/html")
contentAsString(sumOfNumbers) must include("The sum is 30")
复制代码

image.png

我们可以通过 sb test 命令来执行测试,执行完成后就可以看到我们的测试用执行通过

image.png

image.png

8. 总结

在本文中,我们使用 Play Framework 的命令行工具创建了一个简单的网站,添加了一个新的视图模板,并使用参数化模板定义了一条新路由。最后,我们查看了自动生成的测试用例并实现了我们创建的功能的测试用例并通过测试。

该项目的源码可以在 GitHub 上获得。


相关文章
|
2月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
60 4
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
166 3
|
1月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
182 45
|
1月前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。
|
1月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
38 2
|
1月前
|
中间件 Go API
Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架
本文概述了Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架。
85 1
|
1月前
|
缓存 前端开发 中间件
go语言中Web框架
【10月更文挑战第22天】
48 4
|
1月前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP是一种流行的服务器端脚本语言,自诞生以来在Web开发领域占据重要地位。从简单的网页脚本到支持面向对象编程的现代语言,PHP经历了多次重大更新。本文探讨PHP的现代演进历程,重点介绍其在Web开发中的应用及框架创新,如Laravel、Symfony等。这些框架不仅简化了开发流程,还提高了开发效率和安全性。
35 3
|
1月前
|
前端开发 JavaScript 开发工具
从框架到现代Web开发实践
从框架到现代Web开发实践
46 1
|
1月前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP 自发布以来一直在 Web 开发领域占据重要地位,历经多次重大更新,从简单的脚本语言进化为支持面向对象编程的现代语言。本文探讨 PHP 的演进历程,重点介绍其在 Web 开发中的应用及框架创新。自 PHP 5.3 引入命名空间后,PHP 迈向了面向对象编程时代;PHP 7 通过优化内核大幅提升性能;PHP 8 更是带来了属性、刚性类型等新特性。
33 3