Spring REST
Spring REST
@RestController
public class BasicController {
@GetMapping("/welcome")
public String welcome() {
return "Hello String Rest";
}
}
Anotaciones
• @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 WelcomeBean() {}
@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
Obtener detalles de un
GET
recurso
Crear un nuevo
POST
recurso
Reemplazar un
PUT
recurso
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 {
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));
}
@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();
return ResponseEntity.created(location).build();
}
}
• @PostMapping(“/users/{name}/todos”): Mapea el método HTTP Request con un
método POST
• ServletUriComponentsBuilder.fromCurrentRequest().path(“/
{id}”).buildAndExpand(createdTodo.getId()).toUri(): URI creado para el recurso
/**
*
*/
private static final long serialVersionUID = 1L;
return todo;
}
}
Personalizando el mensaje de
error
@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
@ExceptionHandler(Exception.class)
public final ResponseEntity<ExceptionResponse> handleAllExceptions(
Exception ex, WebRequest request) {
@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;
@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());
@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
<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
• .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
Dato Dato