Especialização em Backend com Java & Spring Boot • Demonstrações Práticas Compiláveis


💻 Código de Exemplo 01 — CRUD REST Completo com DTOs em Record e ResponseEntity

package com.empresa.api.produto.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;
import java.math.BigDecimal;

public record ProdutoRequestDTO(
    @NotBlank String nome,
    @Positive BigDecimal preco
) {}
package com.empresa.api.produto.dto;

import java.math.BigDecimal;

public record ProdutoResponseDTO(Long id, String nome, BigDecimal preco) {}
package com.empresa.api.produto;

import com.empresa.api.produto.dto.ProdutoRequestDTO;
import com.empresa.api.produto.dto.ProdutoResponseDTO;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

@RestController
@RequestMapping("/api/v1/produtos")
public class ProdutoController {

    private final ProdutoService service;

    public ProdutoController(ProdutoService service) {
        this.service = service;
    }

    @GetMapping
    public ResponseEntity<Page<ProdutoResponseDTO>> listar(Pageable pageable) {
        return ResponseEntity.ok(service.listar(pageable));
    }

    @GetMapping("/{id}")
    public ResponseEntity<ProdutoResponseDTO> buscarPorId(@PathVariable Long id) {
        return ResponseEntity.ok(service.buscarPorId(id));
    }

    @PostMapping
    public ResponseEntity<ProdutoResponseDTO> criar(@Valid @RequestBody ProdutoRequestDTO dto) {
        ProdutoResponseDTO criado = service.criar(dto);
        return ResponseEntity.created(URI.create("/api/v1/produtos/" + criado.id())).body(criado);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deletar(@PathVariable Long id) {
        service.deletar(id);
        return ResponseEntity.noContent().build();
    }
}

package com.empresa.api.produto;

import com.empresa.api.produto.dto.ProdutoResponseDTO;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

@RestController
@RequestMapping("/api/v1/produtos")
public class ProdutoHateoasController {

    private final ProdutoService service;

    public ProdutoHateoasController(ProdutoService service) {
        this.service = service;
    }

    @GetMapping("/{id}/hateoas")
    public ResponseEntity<EntityModel<ProdutoResponseDTO>> buscarComLinks(@PathVariable Long id) {
        ProdutoResponseDTO produto = service.buscarPorId(id);

        EntityModel<ProdutoResponseDTO> recurso = EntityModel.of(produto);
        WebMvcLinkBuilder linkSelf = linkTo(methodOn(ProdutoHateoasController.class).buscarComLinks(id));
        recurso.add(linkSelf.withSelfRel());

        return ResponseEntity.ok(recurso);
    }
}