Kalkulator kao web servis
Dodaj kontroler KalkulatorController sa rutama:
/zbir?a=5&b=7vraća12;/faktorijel/{n}vraćan!kao broj tipalong(zan ≤ 20);/delioci/{n}vraća listu delilaca brojankao JSON niz, npr.[1,2,3,6]za 6.
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.
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.
| Pojam | Značenje |
|---|---|
| server | program koji čeka zahteve na nekom portu (Spring Boot: 8080) |
| ruta (endpoint) | adresa na koju server odgovara, npr. /zdravo |
| kontroler | klasa čije metode obrađuju zahteve za određene rute |
| JSON | tekstualni zapis podataka: {"ime": "Ana", "razred": 7} |
| anotacija | oznaka 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).
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):
| Polje | Vrednost |
|---|---|
| Project | Maven |
| Language | Java |
| Spring Boot | najnovija stabilna verzija (bez oznake SNAPSHOT/M/RC) |
| Group | rs.svetprogramiranja |
| Artifact | zadaci |
| Packaging | Jar |
| Java | 21 (ili 17) |
| Dependencies | Spring 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
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.
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.
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}]
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.
Za svaki zadatak postoji primer, uputstvo i rešenje.
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.server.port./Zdravo nije isto što i /zdravo.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?