体验 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 上获得。


相关文章
|
1月前
|
开发框架 JavaScript 前端开发
如何选择合适的Web开发框架?
【9月更文挑战第1天】如何选择合适的Web开发框架?
54 1
|
7天前
|
Web App开发 JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的深度整合
【9月更文挑战第28天】在现代Web开发领域,Node.js和Express框架的结合已成为打造高性能、易扩展应用的黄金组合。本文将深入探讨如何利用这一技术栈优化Web应用架构,提供具体实践指导,并分析其性能提升的内在机制。通过代码示例,我们将展示从基础搭建到高级功能的实现过程,旨在为开发者提供一条清晰的学习路径,以实现技术升级和项目效率的双重提升。
20 3
|
11天前
|
JSON 安全 JavaScript
Web安全-JQuery框架XSS漏洞浅析
Web安全-JQuery框架XSS漏洞浅析
45 2
|
11天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
31 1
|
28天前
|
Web App开发 前端开发 JavaScript
Web前端项目的跨平台桌面客户端打包方案之——CEF框架
Chromium Embedded Framework (CEF) 是一个基于 Google Chromium 项目的开源 Web 浏览器控件,旨在为第三方应用提供嵌入式浏览器支持。CEF 隔离了底层 Chromium 和 Blink 的复杂性,提供了稳定的产品级 API。它支持 Windows、Linux 和 Mac 平台,不仅限于 C/C++ 接口,还支持多种语言。CEF 功能强大,性能优异,广泛应用于桌面端开发,如 QQ、微信、网易云音乐等。CEF 开源且采用 BSD 授权,商业友好,装机量已超 1 亿。此外,GitHub 项目 CefDetector 可帮助检测电脑中使用 CEF
105 3
|
6天前
|
JSON JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的完美结合
【9月更文挑战第28天】在现代Web开发中,Node.js和Express框架的结合为创建高性能、易扩展的应用提供了强有力的支持。本文将深入探讨如何利用这两种技术构建一个简单但功能强大的Web服务,同时提供代码示例以加深理解。
|
2月前
|
Rust 安全 开发者
惊爆!Xamarin 携手机器学习,开启智能应用新纪元,个性化体验与跨平台优势完美融合大揭秘!
【8月更文挑战第31天】随着互联网的发展,Web应用对性能和安全性要求不断提高。Rust凭借卓越的性能、内存安全及丰富生态,成为构建高性能Web服务器的理想选择。本文通过一个简单示例,展示如何使用Rust和Actix-web框架搭建基本Web服务器,从创建项目到运行服务器全程指导,帮助读者领略Rust在Web后端开发中的强大能力。通过实践,读者可以体验到Rust在性能和安全性方面的优势,以及其在Web开发领域的巨大潜力。
34 0
|
2月前
|
数据库 开发者 Java
颠覆传统开发:Hibernate与Spring Boot的集成,让你的开发效率飞跃式提升!
【8月更文挑战第31天】在 Java 开发中,Spring Boot 和 Hibernate 已成为许多开发者的首选技术栈。Spring Boot 简化了配置和部署过程,而 Hibernate 则是一个强大的 ORM 框架,用于管理数据库交互。将两者结合使用,可以极大提升开发效率并构建高性能的现代 Java 应用。本文将通过代码示例展示如何在 Spring Boot 项目中集成 Hibernate,并实现基本的数据库操作,包括添加依赖、配置数据源、创建实体类和仓库接口,以及在服务层和控制器中处理 HTTP 请求。这种组合不仅简化了配置,还提供了一套强大的工具来快速开发现代 Java 应用程序。
62 0
|
2月前
|
数据库 开发者 Java
Hibernate映射注解的魔力:实体类配置的革命,让你的代码量瞬间蒸发!
【8月更文挑战第31天】Hibernate 是一款出色的对象关系映射框架,简化了 Java 应用与数据库的交互。其映射注解让实体类配置变得直观简洁。本文深入剖析核心概念与使用技巧,通过示例展示如何简化配置。
24 0
|
2月前
|
数据库 开发者 Java
数据战争:Hibernate的乐观与悲观锁之争,谁将主宰并发控制的王座?
【8月更文挑战第31天】在软件开发中,数据一致性至关重要,尤其是在多用户并发访问环境下。Hibernate 作为 Java 社区常用的 ORM 框架,提供了乐观锁和悲观锁机制来处理并发问题。乐观锁假设数据不易冲突,通过版本号字段 (`@Version`) 实现;悲观锁则假定数据易冲突,在读取时即加锁。选择哪种锁取决于具体场景:乐观锁适合读多写少的情况,减少锁开销;悲观锁适合写操作频繁的场景,避免数据冲突。正确应用这些机制可提升应用程序的健壮性和效率。
28 0
下一篇
无影云桌面