java - servicios - spring rest ejemplo
Spring 4.x/3.x(Web MVC) REST API y JSON2 Post requests, ¿cómo hacerlo bien de una vez? (2)
CURL Post call
curl -i -H "Content-Type: application/json" -X POST -d ''{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"[email protected]"}'' http://localhost:8080/[YOURWEBAPP]/api/user/add
Diferentes escenarios de error:
Aquí exploro los diferentes errores que podrías encontrar después de haber realizado una llamada curl y lo que posiblemente haya salido mal.
Escenario uno:
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 949
Date: Tue, 04 Jun 2013 02:59:35 GMT
Esto implica que la API REST no existe en la URL que proporcionó.
Causa principal:- Es posible que tenga un error tipográfico en su solicitud (créame que esto puede suceder).
- Podría ser que su configuración de resorte no sea correcta. Si este es el caso, es necesario profundizar en lo que realmente salió mal, pero he proporcionado algunas acciones iniciales que debes hacer antes de iniciar una investigación más sofisticada.
Después de haberse asegurado de que todo está bien hecho y nada está mal con su configuración ni con su URL: - Ejecute un maven clean. - Despliegue su aplicación web o simplemente elimínela. - Volver a implementar la aplicación web: asegúrese de usar solo una versión de Spring en su maven / gradle
Escenario dos:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 968
Date: Tue, 04 Jun 2013 03:08:05 GMT
Connection: close
La única razón detrás de esto es el hecho de que su solicitud no está formateada correctamente. Si selecciona la respuesta detallada de curl, debería poder ver "La solicitud enviada por el cliente fue sintácticamente incorrecta".
Causa principal:O bien su formato JSON no es correcto o le falta un parámetro obligatorio para el objeto JAVA.
Comportamiento:Asegúrese de proporcionar el objeto JSON en el formato correcto y con el número correcto de parámetros. Las propiedades anulables no son obligatorias, pero debe proporcionar datos para todas las propiedades NotNullable. Es MUY importante recordar que Spring está utilizando la reflexión de Java para convertir su archivo JSON en objetos Java, ¿qué significa esto? significa que los nombres de variables y métodos son CasE SensItiVe. Si su archivo JSON está enviando la variable "nombre de usuario", entonces su variable de coincidencia en su objeto Java DEBE también llamarse "nombre de usuario". Si tiene getters y setters, también tienen que seguir la misma regla. getUserName y setUserName para que coincida con nuestro ejemplo anterior.
Senario tres:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 24 Aug 2011 08:50:17 GMT
Causa principal:
El tipo de medio Json no es compatible con su servicio web. Esto podría deberse a que su anotación no especifica el tipo de medio o no especifica el tipo de medio en el comando Curl post.
Comportamiento:Verifique que su convertidor de mensajes esté configurado correctamente y asegúrese de que la anotación del servicio web coincida con el ejemplo anterior. Si esto estuvo bien, asegúrese de especificar el tipo de contenido en su solicitud de Curl.
El tipo de medio json no es compatible con su servicio web.
Senario N (!):
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 04 Jun 2013 03:06:16 GMT
Enhorabuena, el usuario se envía a su API REST del lado del servidor.
Para más detalles sobre cómo configurar su pago de primavera la guía mvc de primavera.
Publicaciones y preguntas relacionadas
Esta pregunta frecuente no fue posible si no fuera por todas las personas que proporcionaron las siguientes publicaciones y preguntas (esta lista se ampliará si encuentro publicaciones / preguntas relacionadas útiles):
- ¿Cuál es el tipo de contenido JSON correcto ?
- Spring 3.0 haciendo una respuesta JSON utilizando el convertidor de mensajes jackson
- ¿Cómo POSTAR datos JSON con Curl desde Terminal / Línea de Comando hasta Test Spring REST?
- Publicación de JSON en REST API
- https://github.com/geowarin/spring-mvc-examples
- Cómo publicar JSON en PHP con curl
- Spring REST | MappingJacksonHttpMessageConverter produce JSON no válido
- https://github.com/eugenp/REST
- Spring Web MVC: valide los parámetros de solicitud individuales
- ¿Cómo POSTAR datos JSON con Curl desde Terminal / Línea de Comando hasta Test Spring REST?
- Cómo se devuelve un objeto JSON desde un Servlet Java
- ¿Qué tipo MIME si JSON está siendo devuelto por una API REST?
Antes de entrar en detalles, sé que ha habido muchas conversaciones y preguntas relacionadas con Stackoverflow. Todos ellos me ayudaron de diferentes maneras, así que pensé en unir mis hallazgos como una sola pregunta organizada para resumir mis hallazgos.
Conceptos relacionados
Seguramente los conoces, pero los escribo como una revisión rápida. Siéntase libre de editar en caso de que me falta algo.
Solicitud HTTP POST:
Una solicitud posterior se utiliza cuando está dispuesto a enviar un objeto a un servicio web o una aplicación del lado del servidor.
Publicación por entregas:
Es el proceso de llevar el objeto desde su navegador web a su aplicación del lado del servidor. Se puede usar una llamada jQuery Ajax o una solicitud de Curl.
Protocolos de serialización:
Los días de tesis más populares son JSON y XML. XML se está volviendo menos popular ya que los objetos xml serializados son relativamente más grandes debido a la naturaleza del etiquetado XML. En esta pregunta frecuente, el foco principal es la serialización JSON2 .
Primavera:
Spring framework y su poderosa anotación permiten exponer el servicio web de manera eficiente. Hay muchas bibliotecas diferentes en Spring. El que nos enfoca aquí es Spring web MVC .
Curl vs JQuery:
Estas son las herramientas que puede usar para realizar una solicitud posterior en su lado del cliente. Incluso si está planeando usar JQuery ajax call, le sugiero que use Curl para fines de depuración, ya que le proporciona una respuesta detallada después de realizar la solicitud posterior.
@RequestBody vs @ RequestParam / @ PathVariable vs @ModelAttribute:
En los casos en que tenga un servicio web que no dependa de su modelo Java EE, se debe usar @RequestBody. Si está utilizando el modelo y su objeto JSON se agrega al modelo, puede acceder al objeto a través de @ModelAttribute. Solo en los casos en los que su solicitud sea una solicitud GET o una combinación de solicitud GET y POST, deberá usar @ RequestParam / @ PathVariable.
@RequestBody vs @ResposeBody:
Como puede ver por el nombre, tan simple como eso, solo necesita @ResponseBody si está enviando una respuesta al cliente luego de que el método del lado del servidor procesó la solicitud.
RequestMappingHandlerAdapter vs AnnotationMethodHandlerAdapter:
RequestMappingHandlerAdapter es el nuevo controlador de asignación para Spring framework que reemplazó a AnnotationMethodHandlerAdapter desde Spring 3.1. Si su configuración existente todavía está en AnnotationMethodHandlerAdapter, puede que le resulte útil esta publicación. La configuración proporcionada en mi publicación le dará una idea sobre cómo configurar RequestMappingHandlerAdapter.
Preparar
Deberá configurar un convertidor de mensajes. Así es como su cuerpo de mensaje JSON serializado se convierte en un objeto java local en su lado del servidor.
Configuración básica desde JSON2 . Los conversores fueron MarshallingHttpMessageConverter y CastorMarshaller en la JSON2 , los he reemplazado con MappingJackson2HttpMessageConverter y MappingJacksonHttpMessageConverter.
Dónde poner la configuración
La forma en que mi proyecto está configurado, tengo dos archivos de configuración:
- XML de contexto de la aplicación: Uno es el archivo XML de contexto de la aplicación donde se encuentran el bean de sessionFactory, el bean de DataSource, etc.
- MVC Dispatcher Servlet XML: Aquí es donde tiene su bean resolutor de vista e importa el XML de contexto de su aplicación.
hadlerAdapter bean tiene que estar ubicado en la parte posterior que es el archivo MVC Dispatcher XML.
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<ref bean="jsonConverter"/>
</list>
</property>
<property name="requireSession" value="false"/>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
Puede tener múltiples conversores de mensajes. aquí, he creado un JSON normal y un convertidor de mensajes JSON 2. Se usaron tanto el formato Ref y el formato normal de frijol en el archivo XML (personalmente prefiero la etiqueta ref como más clara).
API REST
Aquí hay un controlador de muestra que está exponiendo la API REST.
El controlador
Aquí es donde se expone su API REST para una solicitud de publicación HTTP.
@Component
@Controller
@RequestMapping("/api/user")
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String insertUser(@RequestBody final User user) {
System.out.println(user.toString());
userService.insertUser(user);
String userAdded = "User-> {" + user.toString() + "} is added";
System.out.println(userAdded);
return userAdded;
}
}
El objeto de Java
@JsonAutoDetect
public class User {
private int id;
private String username;
private String name;
private String lastName;
private String email;
public int getId() {
return externalId;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return this.getName() + " | " + this.getLastName() + " | " + this.getEmail()
+ " | " + this.getUsername() + " | " + this.getId() + " | ";
}
}
CURL Post call
curl -i -H "Content-Type: application/json" -X POST -d ''{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"[email protected]"}'' http://localhost:8080/[YOURWEBAPP]/api/user/add
Publicaciones y preguntas relacionadas
Esta pregunta frecuente no fue posible si no fuera por todas las personas que proporcionaron las siguientes publicaciones y preguntas (esta lista se ampliará si encuentro publicaciones / preguntas relacionadas útiles):
- ¿Cuál es el tipo de contenido JSON correcto ?
- Spring 3.0 haciendo una respuesta JSON utilizando el convertidor de mensajes jackson
- ¿Cómo POSTAR datos JSON con Curl desde Terminal / Línea de Comando hasta Test Spring REST?
- Publicación de JSON en REST API
- https://github.com/geowarin/spring-mvc-examples
- Cómo publicar JSON en PHP con curl
- Spring REST | MappingJacksonHttpMessageConverter produce JSON no válido
- https://github.com/eugenp/REST
- Spring Web MVC: valide los parámetros de solicitud individuales
- ¿Cómo POSTAR datos JSON con Curl desde Terminal / Línea de Comando hasta Test Spring REST?
- Cómo se devuelve un objeto JSON desde un Servlet Java
- ¿Qué tipo MIME si JSON está siendo devuelto por una API REST?
Debería ser bueno notar que una clase de bean NO se puede manejar si tiene 2 o más setter para un campo sin @JsonIgnore
en los opcionales. Spring / Jackson lanzan HttpMediaTypeNotSupportedException
y el estado http 415 Tipo de medio no admitido.
Ejemplo:
@JsonGetter
public String getStatus() {
return this.status;
}
@JsonSetter
public void setStatus(String status) {
this.status = status;
}
@JsonIgnore
public void setStatus(StatusEnum status) {
if (status == null) {
throw new NullPointerException();
}
this.status = status.toString();
}
Actualización: también tenemos que especificar @JsonGetter
y @JsonSetter
en este caso, para no tener problemas cuando se utiliza como tipo de devolución.
Acabo de probarlo con Spring 3.2.2 y Jackson 2.2. Funciona bien como parámetro ( @RequestBody
) y / o como tipo de retorno ( @ResponseBody
).
Actualización 2:
Si se especifican @JsonGetter
y @JsonSetter
, @JsonIgnore
no parece ser necesario.