50+ REST API Pytania Rekrutacyjne 2026: HTTP Methods, Design i Bezpieczeństwo - Flipcards

50+ REST API Pytania Rekrutacyjne 2026: HTTP Methods, Design i Bezpieczeństwo

Sławomir Plamowski 14 min czytania
api-design backend http java nodejs pytania-rekrutacyjne rest-api spring

REST API to standard komunikacji w nowoczesnych aplikacjach webowych i mobilnych. Na rozmowie rekrutacyjnej backend developer musi wykazać się znajomością nie tylko implementacji, ale też zasad projektowania dobrych API. Ten przewodnik zawiera 50+ pytań rekrutacyjnych z odpowiedziami - od podstaw HTTP po zaawansowane tematy jak wersjonowanie, bezpieczeństwo i optymalizacja.

Spis treści

  1. Podstawy REST Pytania
  2. HTTP Methods Pytania
  3. HTTP Status Codes Pytania
  4. API Design Pytania
  5. Bezpieczeństwo API Pytania
  6. Obsługa Błędów Pytania
  7. Optymalizacja Pytania
  8. Powiązane Artykuły

Podstawy REST Pytania

Co to jest REST i jakie są jego główne zasady?

Odpowiedź w 30 sekund:

REST (Representational State Transfer) to styl architektoniczny oparty na 6 zasadach:

  1. Client-Server - separacja klienta od serwera
  2. Stateless - brak stanu sesji na serwerze
  3. Cacheable - odpowiedzi mogą być cache'owane
  4. Uniform Interface - standardowy interfejs
  5. Layered System - warstwy pośrednie
  6. Code on Demand - opcjonalny kod wykonywalny

Odpowiedź w 2 minuty:

REST opiera się na komunikacji klient-serwer za pomocą standardowych metod HTTP i zwracaniu danych w uniwersalnym formacie.

Client → Request (GET /users/1) → Server
       ← Response (JSON) + Status Code ←

Stateless - najważniejsza zasada:

// ❌ Stateful - serwer pamięta stan
session.setAttribute("user", user);

// ✅ Stateless - każdy request zawiera pełny kontekst
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

Uniform Interface - 4 ograniczenia:

  1. Identyfikacja zasobów (URI)
  2. Manipulacja przez reprezentacje (JSON/XML)
  3. Self-descriptive messages (Content-Type, Accept)
  4. HATEOAS (hypermedia links)

Korzyści REST:

  • Skalowalność (stateless = łatwy load balancing)
  • Prostota (HTTP jest znany)
  • Niezależność (klient i serwer mogą ewoluować osobno)

Czym różni się REST od RESTful?

Odpowiedź w 30 sekund:

  • REST - styl architektoniczny, zbiór zasad
  • RESTful - API które implementuje te zasady

W praktyce większość API to "REST-ish" - implementuje część zasad (HTTP methods, JSON) ale nie wszystkie (np. pomija HATEOAS).

Odpowiedź w 2 minuty:

Stopień "restfulness" API można określić za pomocą modelu dojrzałości Richardsona, który klasyfikuje implementacje na cztery poziomy.

Poziomy dojrzałości REST (Richardson Maturity Model):

Level Opis Przykład
0 HTTP jako transport POST /api z XML
1 Zasoby GET /users, GET /orders
2 HTTP verbs GET, POST, PUT, DELETE
3 HATEOAS Linki w odpowiedziach
// Level 2 (typowe "REST" API)
GET /users/1
{
  "id": 1,
  "name": "John"
}

// Level 3 (RESTful z HATEOAS)
GET /users/1
{
  "id": 1,
  "name": "John",
  "_links": {
    "self": { "href": "/users/1" },
    "orders": { "href": "/users/1/orders" },
    "update": { "href": "/users/1", "method": "PUT" }
  }
}

Większość produkcyjnych API to Level 2. Level 3 (HATEOAS) jest rzadko w pełni implementowany.


HTTP Methods Pytania

Jakie metody HTTP używamy w REST i do czego?

Odpowiedź w 30 sekund:

Method Operacja Idempotentne Safe
GET Read Tak Tak
POST Create Nie Nie
PUT Replace Tak Nie
PATCH Update Nie* Nie
DELETE Delete Tak Nie

Odpowiedź w 2 minuty:

Każda metoda HTTP ma określony cel i właściwości, które determinują jej zachowanie w kontekście idempotentności i bezpieczeństwa.

# GET - pobierz zasób
GET /users/1 HTTP/1.1

# POST - utwórz nowy zasób
POST /users HTTP/1.1
Content-Type: application/json
{"name": "John", "email": "john@example.com"}

# PUT - zastąp cały zasób
PUT /users/1 HTTP/1.1
Content-Type: application/json
{"name": "John Updated", "email": "john@example.com", "age": 30}

# PATCH - częściowa aktualizacja
PATCH /users/1 HTTP/1.1
Content-Type: application/json
{"email": "newemail@example.com"}

# DELETE - usuń zasób
DELETE /users/1 HTTP/1.1

Idempotentność:

GET /users/1    → wynik zawsze ten sam
PUT /users/1    → wielokrotne wywołanie = ten sam efekt
DELETE /users/1 → 1x delete = usunięte, 2x delete = nadal usunięte
POST /users     → każde wywołanie tworzy nowy zasób!

Safe methods (GET, HEAD, OPTIONS) nie modyfikują stanu - mogą być cache'owane, prefetchowane.


Czym różni się PUT od PATCH?

Odpowiedź w 30 sekund:

  • PUT - zastępuje cały zasób (wszystkie pola wymagane)
  • PATCH - aktualizuje tylko podane pola

PUT jest idempotentne, PATCH może nie być (zależy od implementacji).

Odpowiedź w 2 minuty:

Różnica między PUT a PATCH jest fundamentalna - PUT wymaga przesłania pełnej reprezentacji zasobu, podczas gdy PATCH aktualizuje tylko wybrane pola.

// Obecny zasób
{
  "id": 1,
  "name": "John",
  "email": "john@example.com",
  "age": 25
}

// PUT /users/1 - ZASTĘPUJE cały zasób
{
  "name": "John Updated"
}
// Wynik: {id: 1, name: "John Updated", email: null, age: null}
// Brakujące pola → null/default!

// PATCH /users/1 - aktualizuje TYLKO podane pola
{
  "name": "John Updated"
}
// Wynik: {id: 1, name: "John Updated", email: "john@example.com", age: 25}

Spring implementation:

// PUT - wymaga pełnego obiektu
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
    user.setId(id);
    return userRepository.save(user);  // nadpisuje wszystko
}

// PATCH - częściowa aktualizacja
@PatchMapping("/{id}")
public User patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
    User user = userRepository.findById(id).orElseThrow();
    updates.forEach((key, value) -> {
        Field field = ReflectionUtils.findField(User.class, key);
        field.setAccessible(true);
        ReflectionUtils.setField(field, user, value);
    });
    return userRepository.save(user);
}

Kiedy używać POST a kiedy PUT?

Odpowiedź w 30 sekund:

  • POST - tworzenie zasobu gdy serwer generuje ID
  • PUT - tworzenie/update gdy klient zna ID

POST tworzy pod różnymi URI, PUT zawsze pod tym samym.

Odpowiedź w 2 minuty:

Wybór między POST a PUT zależy od tego, kto odpowiada za identyfikator zasobu - klient czy serwer.

# POST - serwer decyduje o ID
POST /users HTTP/1.1
{"name": "John"}

201 Created
Location: /users/42
{"id": 42, "name": "John"}

# PUT - klient podaje ID (upsert)
PUT /users/42 HTTP/1.1
{"id": 42, "name": "John"}

201 Created  # jeśli nie istniał
# lub
200 OK       # jeśli istniał i został zaktualizowany

Use cases:

Scenariusz Method
Nowy user, ID generowane POST /users
User z określonym ID PUT /users/{id}
Upload file z nazwą PUT /files/report.pdf
Action na zasobie POST /orders/1/cancel
Partial update PATCH /users/1
// Spring - POST zwraca 201 + Location header
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
    User saved = userRepository.save(user);
    URI location = ServletUriComponentsBuilder
        .fromCurrentRequest()
        .path("/{id}")
        .buildAndExpand(saved.getId())
        .toUri();
    return ResponseEntity.created(location).body(saved);
}

HTTP Status Codes Pytania

Jakie kody HTTP status powinno zwracać REST API?

Odpowiedź w 30 sekund:

2xx - sukces:

  • 200 OK - ogólny sukces
  • 201 Created - zasób utworzony
  • 204 No Content - sukces bez body

4xx - błąd klienta:

  • 400 Bad Request - nieprawidłowe dane
  • 401 Unauthorized - brak autoryzacji
  • 403 Forbidden - brak uprawnień
  • 404 Not Found - zasób nie istnieje

5xx - błąd serwera:

  • 500 Internal Server Error

Odpowiedź w 2 minuty:

Poprawne używanie kodów HTTP status pomaga klientom API zrozumieć wynik operacji i odpowiednio zareagować na błędy.

# 200 OK - GET, PUT, PATCH sukces
GET /users/1 → 200 + body

# 201 Created - POST sukces
POST /users → 201 + Location header + body

# 204 No Content - DELETE sukces (lub PUT bez zwracania body)
DELETE /users/1 → 204

# 400 Bad Request - złe dane wejściowe
POST /users {"email": "invalid"} → 400

# 401 Unauthorized - brak lub nieprawidłowy token
GET /users (no token) → 401

# 403 Forbidden - token OK, ale brak uprawnień
DELETE /admin/users/1 (as regular user) → 403

# 404 Not Found - zasób nie istnieje
GET /users/9999 → 404

# 409 Conflict - konflikt (np. duplicate email)
POST /users {"email": "existing@email.com"} → 409

# 422 Unprocessable Entity - walidacja biznesowa
POST /orders {"quantity": -5} → 422

# 429 Too Many Requests - rate limiting
GET /api/... → 429 + Retry-After header

Spring - globalna obsługa błędów:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(EntityNotFoundException e) {
        return ResponseEntity.status(404)
            .body(new ErrorResponse("NOT_FOUND", e.getMessage()));
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .collect(Collectors.joining(", "));
        return ResponseEntity.badRequest()
            .body(new ErrorResponse("VALIDATION_ERROR", message));
    }
}

Czym różni się 401 od 403?

Odpowiedź w 30 sekund:

  • 401 Unauthorized - nie wiem kim jesteś (brak/nieprawidłowy token)
  • 403 Forbidden - wiem kim jesteś, ale nie masz uprawnień

401 = "Zaloguj się", 403 = "Nie masz dostępu"

Odpowiedź w 2 minuty:

Te dwa kody błędów są często mylone, ale mają zupełnie różne znaczenie w kontekście bezpieczeństwa API.

# 401 Unauthorized - brak tokenu
GET /users
Authorization: (brak)
→ 401 Unauthorized
WWW-Authenticate: Bearer

# 401 Unauthorized - nieprawidłowy/wygasły token
GET /users
Authorization: Bearer expired-token
→ 401 Unauthorized

# 403 Forbidden - token OK, user nie jest adminem
DELETE /admin/users/1
Authorization: Bearer valid-user-token
→ 403 Forbidden

Spring Security:

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")  // 403 jeśli nie admin
                .anyRequest().authenticated()  // 401 jeśli niezalogowany
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt())
            .build();
    }
}

API Design Pytania

Jak projektować URL-e w REST API?

Odpowiedź w 30 sekund:

  1. Rzeczowniki (nie czasowniki) - /users nie /getUsers
  2. Liczba mnoga - /users nie /user
  3. Hierarchia zasobów - /users/1/orders
  4. Kebab-case - /user-profiles nie /userProfiles
  5. Filtry w query params - /users?status=active

Odpowiedź w 2 minuty:

Dobrze zaprojektowane URL-e są intuicyjne, spójne i odzwierciedlają hierarchię zasobów w systemie.

# ✅ DOBRZE
GET    /users              # lista użytkowników
GET    /users/1            # konkretny użytkownik
POST   /users              # utwórz użytkownika
PUT    /users/1            # aktualizuj użytkownika
DELETE /users/1            # usuń użytkownika
GET    /users/1/orders     # zamówienia użytkownika
GET    /users/1/orders/5   # konkretne zamówienie użytkownika

# ❌ ŹLE
GET    /getUsers
GET    /user/1
POST   /createUser
GET    /getUserOrders/1
DELETE /deleteUser/1

# Akcje jako sub-zasoby lub POST
POST   /orders/1/cancel     # akcja na zasobie
POST   /users/1/activate    # akcja na zasobie

# Query params dla filtrowania, sortowania, paginacji
GET /users?status=active&sort=name&page=1&size=20
GET /products?category=electronics&minPrice=100&maxPrice=500

Zagnieżdżone zasoby:

# Płytkie zagnieżdżenie (zalecane)
GET /users/1/orders

# Głębokie zagnieżdżenie (unikaj)
GET /users/1/orders/5/items/3/reviews  # za głęboko!

# Lepiej - bezpośredni dostęp gdy zasób ma globalne ID
GET /orders/5
GET /order-items/3

Jak obsługiwać paginację w REST API?

Odpowiedź w 30 sekund:

Query params: ?page=1&size=20 lub ?offset=0&limit=20 Odpowiedź zawiera metadata: total, hasNext, links.

Odpowiedź w 2 minuty:

Efektywna paginacja wymaga nie tylko podziału danych na strony, ale także dostarczenia metadanych ułatwiających nawigację.

GET /users?page=0&size=20&sort=name,asc

HTTP/1.1 200 OK
{
  "content": [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"}
  ],
  "page": {
    "number": 0,
    "size": 20,
    "totalElements": 150,
    "totalPages": 8
  },
  "_links": {
    "self": "/users?page=0&size=20",
    "next": "/users?page=1&size=20",
    "last": "/users?page=7&size=20"
  }
}

Spring Data:

@GetMapping
public Page<User> getUsers(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "20") int size,
    @RequestParam(defaultValue = "id") String sortBy
) {
    Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
    return userRepository.findAll(pageable);
}

// Spring HATEOAS
@GetMapping
public PagedModel<EntityModel<User>> getUsers(Pageable pageable) {
    Page<User> users = userRepository.findAll(pageable);
    return pagedResourcesAssembler.toModel(users);
}

Cursor-based pagination (dla dużych zbiorów):

GET /events?after=cursor123&limit=20

{
  "data": [...],
  "cursors": {
    "before": "cursor122",
    "after": "cursor143"
  },
  "hasMore": true
}

Cursor jest lepszy gdy dane się zmieniają (unikasz duplicate/skip).


Jak wersjonować REST API?

Odpowiedź w 30 sekund:

3 podejścia:

  1. URL path - /api/v1/users (najpopularniejsze)
  2. Query param - /api/users?version=1
  3. Header - Accept: application/vnd.api.v1+json

Odpowiedź w 2 minuty:

1. URL versioning (zalecane):

GET /api/v1/users
GET /api/v2/users
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 { }

@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 { }

Zalety: jasne, łatwe w dokumentacji, testowaniu Wady: zmienia URI zasobu

2. Header versioning:

GET /api/users
Accept: application/vnd.myapi.v1+json
@GetMapping(produces = "application/vnd.myapi.v1+json")
public UserV1 getUserV1() { }

@GetMapping(produces = "application/vnd.myapi.v2+json")
public UserV2 getUserV2() { }

Zalety: URI stabilne Wady: trudniejsze testowanie (curl, browser)

Strategia wersjonowania:

  • Nowa wersja gdy breaking change (zmiana struktury, usunięcie pola)
  • Addytywne zmiany (nowe pola) - bez nowej wersji
  • Deprecate starą wersję z notice period
  • Sunset header: Sunset: Sat, 1 Jan 2025 00:00:00 GMT

Bezpieczeństwo API Pytania

Jak zabezpieczyć REST API?

Odpowiedź w 30 sekund:

  1. HTTPS - zawsze, bez wyjątków
  2. Authentication - JWT, OAuth2
  3. Authorization - sprawdzaj uprawnienia
  4. Input validation - waliduj wszystko
  5. Rate limiting - ochrona przed DDoS

Odpowiedź w 2 minuty:

Bezpieczeństwo REST API wymaga warstwowego podejścia - od zabezpieczenia transportu przez autentykację, po walidację danych wejściowych.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            // HTTPS tylko
            .requiresChannel(channel -> channel.anyRequest().requiresSecure())
            // CSRF dla stateless API
            .csrf(csrf -> csrf.disable())
            // JWT authentication
            .oauth2ResourceServer(oauth2 -> oauth2.jwt())
            // Authorization rules
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers(HttpMethod.GET, "/api/users/**").hasRole("USER")
                .requestMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            // No session
            .sessionManagement(session ->
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .build();
    }
}

Walidacja input:

@PostMapping
public User createUser(@Valid @RequestBody CreateUserRequest request) {
    // @Valid automatycznie waliduje
}

public record CreateUserRequest(
    @NotBlank @Size(max = 100) String name,
    @Email String email,
    @Min(18) @Max(120) Integer age
) {}

Rate limiting (Bucket4j):

@GetMapping
@RateLimiter(name = "api")
public List<User> getUsers() { }

Czym różni się autentykacja od autoryzacji?

Odpowiedź w 30 sekund:

  • Autentykacja - "Kim jesteś?" (weryfikacja tożsamości)
  • Autoryzacja - "Co możesz zrobić?" (weryfikacja uprawnień)

Autentykacja → Autoryzacja (w tej kolejności)

Odpowiedź w 2 minuty:

Proces zabezpieczania żądania przebiega w dwóch krokach - najpierw weryfikujemy tożsamość, potem sprawdzamy uprawnienia.

Request → Autentykacja → Autoryzacja → Controller
             ↓               ↓
         "To jest John"   "John może czytać users"

Autentykacja (Authentication):

# Basic Auth (nie zalecane)
Authorization: Basic am9objpwYXNzd29yZA==

# Bearer Token (JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

# API Key (dla integracji)
X-API-Key: sk_live_abc123

Autoryzacja (Authorization):

// Role-based
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { }

// Permission-based
@PreAuthorize("hasAuthority('users:delete')")
public void deleteUser(Long id) { }

// Resource-based (sprawdź czy user jest właścicielem)
@PreAuthorize("@userService.isOwner(#id, authentication)")
public void updateUser(Long id, User user) { }

JWT claims dla autoryzacji:

{
  "sub": "user123",
  "roles": ["USER", "EDITOR"],
  "permissions": ["users:read", "posts:write"],
  "exp": 1704067200
}

Jak działa JWT i jakie ma wady?

Odpowiedź w 30 sekund:

JWT (JSON Web Token) = Header.Payload.Signature

  • Self-contained (zawiera wszystkie dane)
  • Stateless (serwer nie przechowuje sesji)
  • Nie można unieważnić przed expiration (główna wada)

Odpowiedź w 2 minuty:

JWT składa się z trzech części oddzielonych kropkami - każda zakodowana w Base64URL. Header określa algorytm, Payload zawiera claims (dane), a Signature potwierdza integralność.

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiZXhwIjoxNzA0MDY3MjAwfQ.signature
     HEADER           .        PAYLOAD          .  SIGNATURE
// Header
{"alg": "HS256", "typ": "JWT"}

// Payload
{
  "sub": "user123",
  "name": "John Doe",
  "roles": ["USER"],
  "iat": 1704063600,
  "exp": 1704067200
}

// Signature
HMACSHA256(base64(header) + "." + base64(payload), secret)

Zalety:

  • Stateless - łatwe skalowanie
  • Self-contained - brak database lookup
  • Cross-domain / microservices

Wady:

  • Nie można unieważnić (tylko czekać na exp)
  • Payload czytelny (base64, nie szyfrowany)
  • Rozmiar tokenu większy niż session ID

Rozwiązania wad:

// Short-lived access token + refresh token
Access Token: 15 min expiration
Refresh Token: 7 days, stored in DB (można unieważnić)

// Blacklist (dla logout)
Set<String> blacklistedTokens = new ConcurrentHashSet<>();

public boolean isValid(String token) {
    return !blacklistedTokens.contains(token) && !isExpired(token);
}

Obsługa Błędów Pytania

Jak projektować odpowiedzi błędów w REST API?

Odpowiedź w 30 sekund:

Standardowa struktura:

{
  "error": "VALIDATION_ERROR",
  "message": "Invalid input",
  "details": [...],
  "timestamp": "2024-01-15T10:30:00Z",
  "path": "/api/users"
}

Odpowiedź w 2 minuty:

RFC 7807 Problem Details:

{
  "type": "https://api.example.com/errors/validation",
  "title": "Validation Error",
  "status": 400,
  "detail": "One or more fields failed validation",
  "instance": "/api/users",
  "errors": [
    {
      "field": "email",
      "message": "must be a valid email address",
      "rejectedValue": "invalid-email"
    },
    {
      "field": "age",
      "message": "must be at least 18",
      "rejectedValue": 15
    }
  ]
}

Spring implementation:

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    public ProblemDetail handleNotFound(EntityNotFoundException e, WebRequest request) {
        ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.NOT_FOUND);
        problem.setTitle("Resource Not Found");
        problem.setDetail(e.getMessage());
        problem.setProperty("timestamp", Instant.now());
        return problem;
    }

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers,
            HttpStatusCode status,
            WebRequest request) {

        ProblemDetail problem = ProblemDetail.forStatus(status);
        problem.setTitle("Validation Error");

        List<Map<String, String>> errors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> Map.of(
                "field", error.getField(),
                "message", error.getDefaultMessage()
            ))
            .toList();

        problem.setProperty("errors", errors);
        return ResponseEntity.status(status).body(problem);
    }
}

Optymalizacja Pytania

Jak zoptymalizować wydajność REST API?

Odpowiedź w 30 sekund:

  1. Caching - ETag, Cache-Control headers
  2. Compression - gzip responses
  3. Paginacja - nie zwracaj wszystkiego
  4. Projection - zwracaj tylko potrzebne pola
  5. Connection pooling - HTTP/2, keep-alive

Odpowiedź w 2 minuty:

HTTP Caching:

# Response
HTTP/1.1 200 OK
Cache-Control: max-age=3600
ETag: "abc123"

# Conditional request
GET /users/1
If-None-Match: "abc123"

# If not modified
HTTP/1.1 304 Not Modified
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    String etag = Integer.toHexString(user.hashCode());

    return ResponseEntity.ok()
        .eTag(etag)
        .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
        .body(user);
}

Compression:

# application.yml
server:
  compression:
    enabled: true
    mime-types: application/json,application/xml,text/html
    min-response-size: 1024

Sparse fieldsets:

GET /users/1?fields=id,name,email

# Response (tylko wybrane pola)
{
  "id": 1,
  "name": "John",
  "email": "john@example.com"
}

Batch requests:

POST /batch
{
  "requests": [
    {"method": "GET", "path": "/users/1"},
    {"method": "GET", "path": "/users/2"},
    {"method": "GET", "path": "/users/3"}
  ]
}

Powiązane Artykuły


Ten artykuł jest częścią serii przygotowującej do rozmów rekrutacyjnych na stanowisko Backend Developer. Sprawdź nasze fiszki z pytaniami rekrutacyjnymi.

Chcesz więcej pytań rekrutacyjnych?

To tylko jeden temat z naszego kompletnego przewodnika po rozmowach rekrutacyjnych. Uzyskaj dostęp do 800+ pytań z 13 technologii.

Kup pełny dostęp Zobacz bezpłatny podgląd
Powrót do blogu

Zostaw komentarz

Pamiętaj, że komentarze muszą zostać zatwierdzone przed ich opublikowaniem.