[TUTORIAL] Como fazer API-REST com Spring
Saaalve pessoal, tudo bom ?, recentemente fiz uma "receita" para fazer APIS e gostaria de saber oque você acha disso.
Caso tenham algo a complementar, coloque nos comentarios.
Para podermos fazer esse passo a passo irei usar como base um projeto de TO DO LIST
- Esta é uma receitinha de bolo para construções de API
- é importante dizer que mesmo sendo uma receita de bolo, isso são apenas informações basicas,
Controller
First Header | Second Header | Third Header | Fourth Header |
---|---|---|---|
@RestController | @RequestMapping | @AllArgsConstructor | @Slf4j |
First Header | Second Header | Third Header | Fourth Header |
---|---|---|---|
@PostMapping | @ApiOperation | @ResponseStatus | @ApiResponses |
First Header | Second Header | Third Header | Fourth Header |
---|---|---|---|
@GetMapping | @PathVariable | @PutMapping | @DeleteMapping |
@RestController// this is a controller class
@RequestMapping("/api/v1")// base url
@AllArgsConstructor// lombok annotation for constructor
@Slf4j// lombok annotation for logger
public class TaskController {
TaskService taskService;
//primeiro ENDPOINT
@ApiOperation(value = "Create a task")
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Task created"),
@ApiResponse(code = 400, message = "Invalid request"),
@ApiResponse(code = 500, message = "Internal server error")
})
@PostMapping("/tasks")
@ResponseStatus(HttpStatus.CREATED)
public Task createTask(@RequestBody Task task)// @RequestBody annotation is used to bind the request body with a method parameter.
{ log.info("Task created[{}]",task);
return taskService.createTask(task);
}
//SEGUNDO ENDPOINT
@ApiOperation(value = "Get all tasks")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Task found"),
})
@GetMapping("/tasks")
@ResponseStatus(HttpStatus.OK)
public List<Task> getAllTasks() {
return taskService.listAllTasks();
}
//TERCEIRO ENDPOINT
@ApiOperation(value = "Get a task by id")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Task found"),
})
@GetMapping("/tasks/{id}")// {id} is a path variable
@ResponseStatus(HttpStatus.OK)// this annotation is used to set the http status code
public ResponseEntity<Task> getTaskById(@PathVariable (value = "id") Long id)// @PathVariable annotation is used to bind the path variable with a method parameter.
{ log.info("Task found[{}]",id);
return taskService.findTaskById(id);
}
//QUARTO ENDPOINT
@ApiOperation(value = "Update a task by id")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Task updated"),
})
@PutMapping ("/tasks/{id}")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<Task> UpdateById(@PathVariable (value = "id")Long id, @RequestBody Task task)
{log.info("Task updated[{}]",id);
return taskService.updateTaskId(task,id);
}
//QUINTO ENDPOINT
@ApiOperation(value = "Delete a task by id")
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Task deleted") })
@DeleteMapping("/tasks/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public ResponseEntity<Object> DeleteById(@PathVariable (value = "id") Long id)
{log.info("Task deleted[{}]",id);
return taskService.deleteById(id);
}
}
Model
Camada de dados
-
Responsavel por onde fica a entidade ( tabela do banco de dados)
-
Nome da classe pode ser ou não criado com o nome do pacote( recomendo que crie com o nome caso ainda esteja aprendendo estrutura de dados e de api)
-
@Entity (Clique aqui para relembrar o que é)
-
@Table (Clique aqui para relembrar o que é)
-
@Getter e @Setter (Clique aqui para relembrar o que é)
-
@ToString (Clique aqui para relembrar o que é)
Catalago
First Header | Second Header | Third Header | Fourth Header | Fifth Header |
---|---|---|---|---|
@Id | @GeneratedValue | @Column | @CreationTimestamp | @UpdateTimestamp |
public class Task { public class Task { ... }: estamos definindo a classe Task, que provavelmente
contém informações sobre uma tarefa no sistema.)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@CreationTimestamp
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at")
private LocalDateTime updatedAt;
}
Repository
- Interface
- taskRepository
First Header |
---|
@Repository |
@Repository
public interface TaskRepository extends JpaRepository<Task(Model), Long(tipo da chave primaria)> {
}
Service
First Header | Second Header | Third Header | Fourth Header |
---|---|---|---|
@Service | @AllArgsConstructor | @RequiredArgsConstructor | @Autowired |
@Service
@AllArgsConstructor
public class TaskService {
private TaskRepository taskRepository;
public Task(model) createTask(Task(model) task) {
return taskRepository.save(task);
}
public List<Task> listAllTasks() {
return taskRepository.findAll();
}
public ResponseEntity<Task> findTaskById(Long id) {
return taskRepository.findById(id).map(task -> ResponseEntity.ok().body(task)).orElse(ResponseEntity.notFound().build());
}
public ResponseEntity<Task> updateTaskId(Task task, Long id) {
return taskRepository.findById(id)
.map(taskToUpdate -> {
taskToUpdate.setTitle(task.getTitle());
taskToUpdate.setDescription(task.getDescription());
taskToUpdate.setDeadLine(task.getDeadLine());
Task updated = taskRepository.save(taskToUpdate);
return ResponseEntity.ok().body(updated);
}).orElse(ResponseEntity.notFound().build());
}
public ResponseEntity<Object> deleteById (Long id ) {
return taskRepository.findById(id)
.map(taskToDelete -> {
taskRepository.deleteById(id);
return ResponseEntity.noContent().build();
}).orElse(ResponseEntity.notFound().build());
}
}
Obs: Em diferentes design pattern o Swagger fica na pasta DOCS ou CONFIGURATION, aqui deixarei como DOCS por estar fazendo o projeto
Fonte: https://dev.to/oficialthyago