Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

REST API pomocí Spring Boot

  • Doporučuji přidat závislost Spring Web

Po inicializaci je třeba spustit v IDE kompilaci, aby se stáhly základní závislosti. Pak je již možné začít psát kód projektu.

Spouštění aplikace z Navigaroru pomocí příkazu “spring-boot run”.

Konfigurace aplikace je v src/main/resources/application.properties.

Pro začátek je dobré umět nastavit port a detailnější debug výstup:

debug
server.port=9999

Nejběžnější anotace v Spring Boot

@SpringBootApplication

Vstupní bod aplikace se Spring Boot. Zajišťuje automatickou konfiguraci.

Vygenerovaný teplate přes Initializr:

package cz.cvut.pjv.restDemo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class RestDemoApplication {
 
	public static void main(String[] args) {
		SpringApplication.run(RestDemoApplication.class, args);
	}
}

@RestController

Označuje třídu, která bude schopna obsluhovat jednotlivé endpointy.

@GetMapping

Mapování požadavků typu GET. Javadoc GetMapping

package cz.cvut.pjv.restDemo;
 
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class AppVersion {
    @GetMapping("/version")
    public String hello() {
        return "verze 1.0";
    }    
}

Možnost vrátit objekt jako JSON:

public class VersionData {
    private String name;
    private int number;
    public VersionData(String name, int number) {
        this.name = name;
        this.number = number;
    }
    public String getNameX() {
        return name;
    }
    public int getNumberX() {
        return number;
    }
}
 
@GetMapping(path = "/versionObject",produces = "application/json" )
    public VersionData helloObject() {
        VersionData tmp = new VersionData("First version",1);
        return tmp;
    }  

@PostMapping

Mapování požadavků typu POST.

Javadoc PostMapping

Příkladem je třeba přihlášení uživatele a získání tokenu:

public class TokenResponse {
        private String token;
        public TokenResponse(String token) {
            this.token = token;
        }
        public String getToken() {
            return token;
        }
    }
 
    //presunout do vlastniho souboru UserData
    public class UserData {
    public String user;
    public String password;
 
    public UserData(String user, String password) {
        this.user = user;
        this.password = password;
    }        
}
 
    @PostMapping(path = "/login", produces = "application/json")
    public TokenResponse login(@RequestBody UserData userData) {
        System.out.println("User=" + userData.user + " pass=" + userData.password);
        if (userData.password.equals("secret") && userData.user.equals("user")) {
            System.out.println("GRANTED");
            return new TokenResponse("secretUUID");
        }
        return new TokenResponse("");
    }

Vyvolání výjimky a nastavení příslušného HTTP error kódu:

@ResponseStatus(code = HttpStatus.UNAUTHORIZED, reason = "Wrong credentials")
    public class UnauthorizedException extends Exception {
        public UnauthorizedException() {
        }
    }
 
    @PostMapping(path = "/loginExcept", produces = "application/json")
    public TokenResponse loginExc(@RequestBody UserData userData) throws UnauthorizedException {
        System.out.println("User=" + userData.user + " pass=" + userData.password);
        if (userData.password.equals("secret") && userData.user.equals("user")) {
            System.out.println("GRANTED");
            return new TokenResponse("secretUUID");
        }
        throw new UnauthorizedException();
    }
}

@PutMapping

@DeleteMapping

@PatchMapping

Nepovinné parametry endpointu

Je možné se například podle nastaveného tokenu ptát na data:

// data table of ID, names
    private String[][] dataTable
            = {{"1", "Admin"},
            {"2", "Admin2"},
            {"100", "PowerUser1"},
            {"101", "PowerUser2"},
            {"102", "PowerUser3"},
            {"1000", "BFUser1"},
            {"1001", "BFUser2"},
            {"1002", "BFUser3"}};
 
    @GetMapping(value = "/list", produces = "text/plain")
    public String getList(@RequestHeader(value = "bearer", required = false) String token, @RequestParam int idLow, @RequestParam int idHigh) throws UnauthorizedException {
        boolean authorized = false;
        StringBuilder sb = new StringBuilder();
        if (token != null) {
            if (token.equals("secretUUID")) {
                authorized = true;
            }
        }
        if (!authorized) {
            // bearer token not presented
            // block access by throwing exception:
            //throw new UnauthorizedException();
            //get only IDs:
            sb.append("Available IDs:\n");
            for (int i = 0; i < dataTable.length; i++) {
                String textID = dataTable[i][0];
                int id = Integer.parseInt(textID);
                if (id > idLow && id < idHigh) {
                    sb.append(dataTable[i][0] + "\n");
                }
            }
        } else {
 
            sb.append("Available IDs and users:\n");
            for (int i = 0; i < dataTable.length; i++) {
                String textID = dataTable[i][0];
                int id = Integer.parseInt(textID);
                if (id > idLow && id < idHigh) {
                    sb.append(dataTable[i][0] + " " + dataTable[i][1] + "\n");
                }
            }
        }
        return sb.toString();
    }  

Proměnná přímo v cestě endpointu

Je možné ptát se například na detaily jednoho záznamu z kolekce:

  @GetMapping(value = "/list/{id}", produces = "text/plain")
    public String getList(@PathVariable int id) {
        StringBuilder sb = new StringBuilder();
        for (String[] strings : dataTable) {
            if (Integer.parseInt(strings[0])==id){
                sb.append(strings[1]+"\n");
            }
        }
        return sb.toString();
    }

Testování pomocí CURL

/version

curl http://localhost:9999/version

/login

curl -X POST http://localhost:9999/login -H "Content-Type: application/json" -d "{\"user\":\"user\",\"password\":\"secret\"}"

/list

bez tokenu:

curl -sS "http://localhost:9999/list?idLow=10&idHigh=999"

s tokenem:

curl -sS "http://localhost:9999/list?idLow=10&idHigh=999" -H "bearer: secretUUID"

detaily o jedne polozce s konkretnim ID:

curl http://localhost:9999/list/100

courses/b0b36pjv/tutorials/11/java_rest.txt · Last modified: 2022/05/04 16:41 by mudromar