Spring Boot: prva web aplikacija u Javi

Lekcija 1 od 3 · Spring Boot

Spring Boot je najpopularniji alat za pravljenje web aplikacija i servisa u Javi. Program postaje server: čeka zahteve iz pregledača ili iz druge aplikacije i vraća odgovor – HTML stranu ili podatke u obliku JSON. U ovoj lekciji praviš projekat, pokrećeš server i pišeš prve adrese (rute) koje vraćaju tekst i JSON.

Pre nego što počneš: potrebno predznanje – kolekcije i record, lambda izrazi, osnove weba (HTTP, URL).
Kako da učiš: radi u svom projektu korak po korak i posle svakog koraka pokreni server i proveri rezultat u pregledaču. Primeri su za Spring Boot 3 ili 4 i Javu 17+; svaki deo koda upiši u fajl naveden u komentaru na vrhu primera.

Šta su Spring i Spring Boot

Spring je skup biblioteka za serverske aplikacije: obrada web zahteva, rad sa bazom, bezbednost (prijava korisnika), slanje mejlova… Spring Boot ga čini jednostavnim za početak: sam podešava većinu stvari i u aplikaciju ugrađuje web server (Tomcat), pa se aplikacija pokreće kao običan Java program.

PojamZnačenje
serverprogram koji čeka zahteve na nekom portu (Spring Boot: 8080)
ruta (endpoint)adresa na koju server odgovara, npr. /zdravo
kontrolerklasa čije metode obrađuju zahteve za određene rute
JSONtekstualni zapis podataka: {"ime": "Ana", "razred": 7}
anotacijaoznaka sa @ (npr. @GetMapping) kojom se Spring-u kaže šta je neka klasa ili metoda

Pre ove lekcije treba da znaš klase i objekte, kolekcije i osnovne pojmove o webu (Osnove weba: zahtev, odgovor, URL, HTTP metode).

Pravljenje projekta: start.spring.io

Potrebni su JDK 17 ili noviji (preporuka: 21) i razvojno okruženje – najlakše IntelliJ IDEA Community. Projekat se pravi na sajtu start.spring.io (Spring Initializr):

PoljeVrednost
ProjectMaven
LanguageJava
Spring Bootnajnovija stabilna verzija (bez oznake SNAPSHOT/M/RC)
Grouprs.svetprogramiranja
Artifactzadaci
PackagingJar
Java21 (ili 17)
DependenciesSpring Web (kasnije dodajemo još)

Dugme Generate preuzima zip. Raspakuj ga i otvori fasciklu u IntelliJ-u (File → Open); okruženje samo preuzima potrebne biblioteke (prvi put to traje par minuta).

zadaci/
├── pom.xml                      ← spisak biblioteka (zavisnosti) i podešavanja Maven-a
├── mvnw, mvnw.cmd               ← Maven omotač: pokretanje bez posebne instalacije Maven-a
└── src/
    ├── main/
    │   ├── java/rs/svetprogramiranja/zadaci/
    │   │   └── ZadaciApplication.java   ← glavna klasa (metoda main)
    │   └── resources/
    │       ├── application.properties   ← podešavanja aplikacije
    │       ├── static/                  ← HTML, CSS, JS i slike koje server šalje kakve jesu
    │       └── templates/               ← šabloni strana (ako se koriste)
    └── test/                            ← automatski testovi

Glavna klasa i pokretanje

Initializr pravi glavnu klasu. Anotacija @SpringBootApplication uključuje automatsko podešavanje i traženje komponenti (kontrolera, servisa) u ovom paketu i njegovim podpaketima.

// src/main/java/rs/svetprogramiranja/zadaci/ZadaciApplication.java
package rs.svetprogramiranja.zadaci;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ZadaciApplication {
    public static void main(String[] args) {
        // pokreće ugrađeni web server i celu aplikaciju
        SpringApplication.run(ZadaciApplication.class, args);
    }
}

Aplikacija se pokreće zelenim trouglom pored metode main u IntelliJ-u, ili iz komandne linije (cmd) u fascikli projekta:

mvnw.cmd spring-boot:run

U konzoli se pojavljuje poruka Tomcat started on port 8080. Za sada svaka adresa vraća stranu sa greškom 404 (Whitelabel Error Page) – nijedna ruta još ne postoji. Server se zaustavlja crvenim kvadratom ili sa Ctrl+C.

Prvi kontroler: ruta /zdravo

Kontroler je klasa označena sa @RestController. Svaka metoda označena sa @GetMapping("/putanja") odgovara na GET zahtev za tu putanju; ono što metoda vrati šalje se pregledaču.

// src/main/java/rs/svetprogramiranja/zadaci/ZdravoController.java
package rs.svetprogramiranja.zadaci;

import java.time.LocalTime;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ZdravoController {

    // http://localhost:8080/zdravo
    @GetMapping("/zdravo")
    public String zdravo() {
        return "Zdravo iz Spring Boot-a! Sada je " + LocalTime.now().withNano(0);
    }

    // parametar iz upita: http://localhost:8080/pozdrav?ime=Ana
    @GetMapping("/pozdrav")
    public String pozdrav(@RequestParam(defaultValue = "neznanče") String ime) {
        return "Zdravo, " + ime + "!";
    }

    // deo putanje kao parametar: http://localhost:8080/kvadrat/12
    @GetMapping("/kvadrat/{n}")
    public long kvadrat(@PathVariable long n) {
        return n * n;
    }
}

Posle izmene koda server se mora ponovo pokrenuti. Zatim u pregledaču otvori tri adrese iz komentara. @RequestParam čita vrednost iz dela adrese posle ?, a @PathVariable deo putanje u vitičastim zagradama. Spring sam pretvara tekst "12" u broj.

Vraćanje podataka u obliku JSON

Kada metoda kontrolera vrati objekat (na primer record) ili listu, Spring ga automatski pretvara u JSON. Tako server pravi podatke za JavaScript u pregledaču ili za mobilnu aplikaciju:

// src/main/java/rs/svetprogramiranja/zadaci/InfoController.java
package rs.svetprogramiranja.zadaci;

import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class InfoController {

    // record: polja postaju ključevi u JSON-u
    public record Lekcija(int broj, String naslov, boolean uradjena) { }

    // http://localhost:8080/lekcije
    @GetMapping("/lekcije")
    public List<Lekcija> lekcije() {
        return List.of(
                new Lekcija(1, "Prva web aplikacija", true),
                new Lekcija(2, "REST API", false),
                new Lekcija(3, "Baza podataka", false));
    }
}

Pregledač prikazuje odgovor:

[{"broj":1,"naslov":"Prva web aplikacija","uradjena":true},
 {"broj":2,"naslov":"REST API","uradjena":false},
 {"broj":3,"naslov":"Baza podataka","uradjena":false}]

application.properties i statičke strane

U src/main/resources/application.properties upisuju se podešavanja, na primer drugi port ako je 8080 zauzet:

# src/main/resources/application.properties
spring.application.name=zadaci
server.port=8081

Fajlovi u fascikli src/main/resources/static šalju se pregledaču bez izmena. Ako tu napraviš index.html, on se prikazuje na adresi http://localhost:8080/. Na toj strani JavaScript može da traži podatke od kontrolera:

<!-- src/main/resources/static/index.html -->
<!DOCTYPE html>
<html lang="sr">
<head><meta charset="UTF-8"><title>Lekcije</title></head>
<body>
  <h1>Moje lekcije</h1>
  <ul id="lista"></ul>
  <script>
    // traži JSON od servera i pravi stavke liste
    fetch("/lekcije")
      .then(odgovor => odgovor.json())
      .then(lekcije => {
        for (const l of lekcije) {
          const li = document.createElement("li");
          li.textContent = l.broj + ". " + l.naslov + (l.uradjena ? " ✔" : "");
          document.getElementById("lista").appendChild(li);
        }
      });
  </script>
</body>
</html>

Ovo je ista podela posla kao u svakoj web aplikaciji: frontend (HTML, CSS, JS – vidi kurs HTML, CSS i JavaScript) prikazuje podatke, a backend (Spring Boot) ih daje.

Zadaci za vežbu

Za svaki zadatak postoji primer, uputstvo i rešenje.

ZADATAK 01Težina: lako

Kalkulator kao web servis

Dodaj kontroler KalkulatorController sa rutama:

  • /zbir?a=5&b=7 vraća 12;
  • /faktorijel/{n} vraća n! kao broj tipa long (za n ≤ 20);
  • /delioci/{n} vraća listu delilaca broja n kao JSON niz, npr. [1,2,3,6] za 6.
Česte greške i saveti
  • Posle svake izmene Java koda ponovo pokreni server (ili dodaj zavisnost Spring Boot DevTools, koja to radi sama).
  • Kontroleri moraju biti u istom paketu kao glavna klasa ili u njegovom podpaketu – inače ih Spring ne pronalazi i dobija se greška 404.
  • Greška „Port 8080 was already in use“ znači da server već radi (možda u drugom prozoru) – zaustavi ga ili promeni server.port.
  • Adresa je osetljiva na velika i mala slova: /Zdravo nije isto što i /zdravo.

Proveri znanje

Otvori kviz

Spring Boot – osnove

1. Šta radi anotacija @GetMapping("/zdravo")?




2. Na kom portu podrazumevano radi Spring Boot aplikacija?




3. Šta Spring radi sa objektom koji vrati metoda kontrolera?




4. Kako se u metodi čita vrednost iz adrese /pozdrav?ime=Ana?