0% encontró este documento útil (0 votos)
17 vistas

Spring REST

Cargado por

Willy Granados
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PPTX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
17 vistas

Spring REST

Cargado por

Willy Granados
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PPTX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 63

Spring REST

Ing. César Alcívar Aray


REST
¿Qué es REST?

• REpresentational State Transfer (REST) es un estilo


arquitectónico para la Web. REST especifica un conjunto de
limitaciones. Estas limitaciones aseguran que los clientes
puedan interactuar con los servidores de forma flexible.
Terminologías comunes
• Servidor: Provee servicios. Exponer servicios que pueden ser
consumidos por los clientes

• Cliente: Consume servicios. Puede ser un brower o cualquier sistema

• Recurso: Cualquier información puede ser un recurso. Una persona,


una imagen, o producto

• Representación: Una forma específica de representar un recurso. Por


ejemplo, el recurso producto puede ser representado a través de JSON,
XML, HTML. Diferentes clientes pueden solicitar diferentes
representaciones de un recurso
• Client-Server: existe una separación entre los clientes y los
Limitaciones REST
servidores
• Stateless: la comunicación entre el cliente y el servidor debería
ser sin estados.
• Layered System: Múltiples capas jerárquicas como Gateways,
firewalls y proxy pueden existir entre el cliente y el servidor
• Cacheble: las solicitudes al servidor debería ser declaradas como
cacheable o no chachebles
• Uniform Interface: cada recurso tiene un identificador. En el
caso de los servicios Web, usamos URI, por ejemplo,
/users/Jack/todos/1

• Hypermedia as the engine of application state: El consumidor


Spring REST
Proyecto Spring Boot

• Creamos un proyecto Spring Boot llamado SpringRestBasic con


el paquete com.poo.isi

• Agregamos el starter: Web


Creamos el Primer controller
con su método

@RestController
public class BasicController {

@GetMapping("/welcome")
public String welcome() {
return "Hello String Rest";
}
}
Anotaciones

• @RestController: es una combinación de @ResponseBody y


@Controller. típicamente usadas para crear REST Controllers

• @GetMapping(‘’/welcome’’): Es un shortcut de
@RequestMapping(method = RequestMethod.GET)
Resultado de la ejecución
Retornando un objeto
• Creamos una clase llamada WelcomeBean con el atributo
message, como se muestra a continuación:

public class WelcomeBean {

private String message;

public WelcomeBean() {}

public WelcomeBean(String message) {


super();
this.message = message;
}
// getters and setters
}
Controller Method para retornar
un objeto

@RestController
public class BasicController {

@GetMapping("/welcome-with-object")
public WelcomeBean welcomeWithObject() {
return new WelcomeBean("Hello String Rest");
}
}
Resultado de la ejecución
Controller Method con
@PathVariable

@RestController
public class BasicController {

@GetMapping("/welcome-with-parameter/name/{name}")
public WelcomeBean welcomeWithParameter(@PathVariable String name) {
return new WelcomeBean("Hello, " + name);
}
}
Resultado de la ejecución
Creando un recurso
TODO
Request methods, operaciones

Http Request Method Operation

Obtener detalles de un
GET
recurso

Crear un nuevo
POST
recurso

Reemplazar un
PUT
recurso

PATCH Actualizar un recurso

DELETE Eliminar un recurso


La clase Todo
public class Todo {
private int id;

private String user;

private String desc;

private Date targetDate;


private boolean isDone;

public Todo() {}

public Todo(int id, String user, String desc, Date targetDate, boolean isDone) {
super();
this.id = id;
this.user = user;
this.desc = desc;
this.targetDate = targetDate;
this.isDone = isDone;
}
// getters and setters
}
La clase TodoService
@Service
public class TodoService {

private static List<Todo> todos = new ArrayList<Todo>();

private static int todoCount = 3;

static {
todos.add(new Todo(1,"Jack","Learn Spring MVC",new Date(),false));
todos.add(new Todo(2,"Jack","Learn Struts",new Date(),false));
todos.add(new Todo(3,"Jill","Learn Hibernate",new Date(),false));
}

public List<Todo> retrieveTodos(String user){


System.out.println("Cacheable");
List<Todo> filteredTodos = new ArrayList<Todo>();
for(Todo todo:todos) {
if(todo.getUser().equals(user)) {
filteredTodos.add(todo);
}
}
return filteredTodos;
}

public Todo addTodo(String name,String desc,Date targetDate,boolean isDone) {


Todo todo = new Todo(++todoCount,name,desc,targetDate,isDone);
todos.add(todo);
return todo;
}

public Todo retrieveTodo(int id) {


for(Todo todo:todos) {
if(todo.getId()==id)
return todo;
}
return null;
}
Obteniendo un Todo list

@RestController
public class TodoController {

@Autowired
private TodoService todoService;

@GetMapping("/users/{name}/todos")
public List<Todo> retrieveTodos(@PathVariable String name){
return todoService.retrieveTodos(name);
}
}
Obteniendo un Todo específico

@RestController
public class TodoController {

@GetMapping("/users/{name}/todos/{id}")
public Resource<Todo> retrieveTodo(@PathVariable String name,@PathVariable int id){
return todoService.retrieveTodo(id);
}
Agregando un Todo

@RestController
public class TodoController {


@PostMapping("users/{name}/todos")
public ResponseEntity<?> add(@PathVariable String name,@RequestBody Todo todo){
logger.info("Todo -> {}",todo);
Todo createdTodo = todoService.addTodo(name, todo.getDesc(), todo.getTargetDate(), todo.isDone());
if(createdTodo==null)
return ResponseEntity.noContent().build();

URI location = ServletUriComponentsBuilder.fromCurrentRequest()


.path("/{id}").buildAndExpand(createdTodo.getId()).toUri();

return ResponseEntity.created(location).build();
}
}
• @PostMapping(“/users/{name}/todos”): Mapea el método HTTP Request con un
método POST

• ResponseEntity<?>: Un HTTP post request debería idealmente retornar el URI


del recurso creado.

• ReponseEntity.noContent().build(): Usado para retornar que la creación del


recurso falló

• ServletUriComponentsBuilder.fromCurrentRequest().path(“/
{id}”).buildAndExpand(createdTodo.getId()).toUri(): URI creado para el recurso

• ResponseEntity.create(location).build(): Retorna el estatus 201 (CREATED)


Response Status
Postman para crear un Todo
Exception Handling
Introducción

• Cuando ocurre algún error, nosotros queremos retornar una


buena descripción del problema que sucedió cuando se
consumió un servicio.
Consumiendo un recurso que no
existe
Creamos una Custom Exception

public class TodoNotFoundException extends RuntimeException {

/**
*
*/
private static final long serialVersionUID = 1L;

public TodoNotFoundException(String msg) {


super(msg);
}
}
@RestController
public class TodoController {

@GetMapping("/users/{name}/todos/{id}")
public Todo retrieveTodo(@PathVariable String name,@PathVariable int id){
Todo todo = todoService.retrieveTodo(id);
if(todo==null)
throw new TodoNotFoundException("Todo Not Found");

return todo;
}
}
Personalizando el mensaje de
error

public class ExceptionResponse {

private Date timestamp = new Date();


private String message;
private String details;

public ExceptionResponse(String message, String details) {


super();
this.message = message;
this.details = details;
}

}
Controlando
TodoNotFoundException

@ControllerAdvice
@RestController
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(TodoNotFoundException.class)
public ResponseEntity<ExceptionResponse> toNoFound(TodoNotFoundException ex){
ExceptionResponse response = new ExceptionResponse(ex.getMessage(), "Any detail");
return new ResponseEntity<ExceptionResponse>(response,HttpStatus.NOT_FOUND);
}
• extends ResponseEntityExceptionHandler: nosotros extendemos
la clase ResponseEntityExceptionHandler, la cual es la clase
base que provee excepciones centralizadas de clases
ControllerAdvice en Spring MVC

• @ExceptionHandler(TodoNoFoundException.class): Define el
método que gestionara las excepciones
TodoNotFoundException

• ExceptionResponse exResponse = new


ExceptionResponse(ex.getMessage(),”Any details”): esto crea
un mensaje personalizado
Controlando todas las
Exceptions

@ExceptionHandler(Exception.class)
public final ResponseEntity<ExceptionResponse> handleAllExceptions(
Exception ex, WebRequest request) {

ExceptionResponse reponse =new ExceptionResponse(new


Date(),ex.getMessage(),request.getDescription(false));
return new
ResponseEntity<ExceptionResponse>(reponse,HttpStatus.INTERNAL_SERVER_ERROR);
}
Validaciones
Introducción

• Un buen servicio siempre valida los datos antes de procesarlos;


Bean Validation API es usado para validar servicios

• El Bean Validation API provee un núemro de anotaciones que


pueden ser usadas para validar jeans. La especificación JSR 349
es definida en Bean Validation API 1.1. Hibernate-validator es
una referencia de esa implementación
La anotación @Valid

@PostMapping("/users")
public User createUser(@Valid @RequestBody User user) {
userRepository.save(user);
return user;
}
Anotaciones de validación

@Entity
public class User {

@Id
@GeneratedValue
private Integer id;

@Size(min=2,message="Name should have atleast 2 characters")


private String name;

@Past
private Date birthdate;

Método para gestionar las validaciones de las
propiedades de objetos

@ControllerAdvice
@RestController
public class ReponseExceptionHandler extends ResponseEntityExceptionHandler {


@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest
request) {
ExceptionResponse reponse =new ExceptionResponse(new
Date(),ex.getMessage(),ex.getBindingResult().toString());

return new ResponseEntity<Object>(reponse,HttpStatus.BAD_REQUEST);


}

}
Internacionalización
Internacionalización

• Internacionalización es el proceso de desarrollar aplicación y


servicios que puedan ser personalizados para diferentes
lenguajes y culturas del mundo. también conocido como
localization

• En Spring Boot necesitamos agregar un LocaleResolver y un


ResourceBundleMessageSource como fuente de mensajes
En la clase main

@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.US);
return sessionLocaleResolver;
}

@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
• sessionLocaleResolver.setDefaultLocale(Locale.US): Se
establece la configuración por defecto de Locale.US

• messageSource.setBasenames(“messages”): establecemos el
nombre base de los archivos de mensajes (messages.properties,
messages_fr.properties)

• messageSource.setUseCodeAsDefaultMessage(true): si este
mensaje no esta, entonces el código es retornado como mensaje
por defecto
• messages.properties:

• welcome.message=Welcome
in English

• message_fr.properties:

• welcome.message=Bonjour
@RestController
public class HelloController {

@Autowired
private MessageSource messageSource;


@GetMapping("/hello-world-internacional")
public String helloWorldInternationalized(@RequestHeader(name="Accept-Language",required=false) Locale
locale) {
return messageSource.getMessage("welcome.message", null, locale);
}

}
• @RequestHeader(value=“Accept-Language”,required=false)
Locale local: el objeto Locale se establece en el header de la
solicitud.

• messageSource.getMessage(“welcome.message”,null,localte):
messageSource es inyectado dentro del controller. Nosotros
obtenemos en mensaje de la configuración regional del header.
Content Negotiation -
Implemening Support for
XML
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Configuring Auto Generation
of Swagger Documentation
Generating a Swagger
specification

• Springfox Swagger puede ser utilizado para generar


documentación de los servicios RESTful
Dependencias
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.4.0</version>
</dependency>

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
</dependency>
@Configuration
@EnableSwagger2
public class SwaggerConfig {

@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
}
• @Configuration: Define a archivo de configuración de Spring

• EnableSwagger2: La anotación habilita el soporte a Swagger

• Docket: Una clases para la configuración de generación de


Swagger documentation

• .apis(RequestHandlerSelectors.any()).paths(PathSelectors.any())
: Incluye documentación a todos los paths
http://localhost:8080/v2/api-docs
Swagger-UI
@ApiOperation(value = "Retrieve all users",
response = User.class,
produces = "application/json")
@GetMapping("/users")
public Iterable<User> retrieveAllUsers(){
return userRepository.findAll();
}
t
A B

Dato Dato

Siguiente Siguiente null

null Anterior Anterior


t
A B

Dato Dato

Siguiente Siguiente null

También podría gustarte