Routes, Controllers & Twirl Templates
Reactive, Non-Blocking by Design
Play is a Scala/Java web framework built for high-throughput, reactive applications on the JVM, historically built on Akka. Unlike a traditional thread-per-request servlet model, a Play request handler doesn't need to hold a dedicated thread blocked for a slow I/O operation — the thread frees up while waiting, improving resource utilization under high concurrency.
The conf/routes File
GET /users/:id controllers.UserController.show(id: Long)
POST /users controllers.UserController.create()Routes map HTTP method + URL pattern to a controller action in one concise, declarative file — a centralized view of the app's whole URL structure, rather than scattering route annotations across many controller files.
Controllers & Actions
class UserController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
def show(id: Long) = Action.async {
userService.find(id).map {
case Some(u) => Ok(views.html.user(u))
case None => NotFound
}
}
}A controller groups action methods; each handles a request and returns a Result. Actions returning Future[Result] (via Action.async) reflect the non-blocking model directly — the framework frees the thread while an async database/API call completes, rather than blocking on it.
Twirl — Compiled, Type-Safe Templates
Twirl templates (.scala.html) compile to actual JVM functions rather than being interpreted at runtime. A template's expected parameters and types are checked by the compiler — passing the wrong type produces a compile-time error, not a runtime failure discovered only when a user happens to trigger that page.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free