Varias formas en que Spring MVC maneja las solicitudes de tipo json y devuelve el formato Json

Varias formas en que Spring MVC maneja las solicitudes de tipo json y devuelve el formato Json

Uno, anotación @RequestBody

Puede ayudarnos a analizar los datos json enviados por el cliente (dispositivo móvil, navegador, etc.) y encapsularlos en la clase de entidad.
Los tipos MIME de solicitud http comúnmente utilizados son application / json, text / html, text / xml, image / jpeg, etc., que son tipos de tipo de contenido correspondientes a formatos fijos.
En la sintaxis del elemento de formulario en la página web, EncType indica el formato de los datos enviados. Utilice el atributo Enctype para especificar el tipo de codificación que utiliza el navegador al enviar los datos al servidor.
P.ej:

  • application / x-www-form-urlencoded: Los datos del formulario se codifican como pares de nombre / valor. Este es el formato de codificación predeterminado (estándar). Cuando se obtiene el método del formulario, el navegador usa el método de codificación de x-www-form-urlencoded para convertir los datos del formulario en una cadena (nombre1 = valor1 & nombre2 = valor2 ...), y luego agregar esta cadena al final de la URL y dividirla con?, Cargue esta nueva URL.
  • multipart / form-data: Los datos del formulario se codifican como un mensaje. Cada control en la página corresponde a una parte del mensaje. Esto se usa generalmente cuando se cargan archivos. Cuando se publica la acción, el navegador encapsula los datos del formulario en el cuerpo http y los envía al servidor. Si no hay control type = file, use la aplicación predeterminada / x-www-form-urlencoded. Pero si hay type = file, se usará multipart / form-data. El navegador dividirá el formulario completo en unidades de controles y agregará Disposición de contenido (datos de formulario o archivo), Tipo de contenido (texto predeterminado / sin formato), nombre (nombre de control) y otra información a cada parte, y Agregar el separador (límite).
  • texto / sin formato: los datos del formulario están codificados en forma de texto sin formato, que no contiene controles ni caracteres de formato, que no están incluidos en el tipo de formulario.
    El punto está aquí ~~~
    @ReqeustBody: a
    menudo se usa para procesar contenido cuyo tipo de contenido no es la codificación predeterminada application / x-www-form-urlcoded , como application / json o application / xml, etc., que se utilizan a menudo para procesar el tipo application / json.
    Nota: @requestBody recibe la cadena json del front-end, no el objeto JSON. En el protocolo http, solo se puede transmitir la cadena. El objeto solo puede existir en el lenguaje front-end o back-end, por lo que el -end El objeto Json debe usar javascript Proporciona el método JSON.stringify () para convertir a una cadena json.
    Además, cuando se usa ajax de JQuery, el tipo de tipo de contenido predeterminado es application / x-www-form-urlcoded.
    Un ejemplo de código JQuery ajax
// Jquery Ajax请求
$.ajax({
    
    
    url : "doindex.action",
    type : "POST",
    contentType : "application/json;charset=UTF-8",
    data :JSON.stringify(json),
    dataType : "json",
    success : function(data) {
    
    
    }
});

Tenga en cuenta que el contentType en ajax: "application / json; charset = UTF-8", charset = UTF-8 debe estar escrito en él; de lo contrario, el backend es propenso a los caracteres chinos confusos y el conjunto de caracteres predeterminado de tomcat no es utf -8
. La anotación @RequestBody se usa en la firma del método final para leer la cadena json pasada en el párrafo anterior, ver un ejemplo

@RequestMapping("/doindex.action")
    public @ResponseBody Customer getPages(@RequestBody(required=true) Map<String,Object> map , HttpServletRequest request)throws Exception{
    
    
        Customer cust=new Customer();
        cust.setLcname("马雷");
        cust.setCreatetime(new Timestamp(System.currentTimeMillis()));
        //mv.addObject(cust);
        //Map<String,Object> map=new HashMap();
        //map.put("cust",cust);
        ObjectMapper om=new ObjectMapper();
        om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        //ModelAndView mv=new ModelAndView(new MappingJackson2JsonView(om),cust);
        return cust;
    }

Independientemente del significado del código específico en el cuerpo del método, la información del parámetro de cadena json de la interfaz se completa automáticamente en el tipo de mapa Map <String, Object> marcado por @RequestBody (required = true). ¿Cómo se hace esto?
Spring ha creado una gran cantidad de HttpMessageConverter para nosotros, por ejemplo, MappingJackson2HttpMessageConverter, StringHttpMessageConverter, etc. Principalmente para cooperar con @RequestBody y @ResponsetBody.
La interfaz HttpMessageConverter es una interfaz recién agregada en Spring 3.0, que es responsable de 1, convertir la información de la solicitud en un objeto (tipo T), y 2, generar el objeto (tipo T) como información de respuesta.
Eche un vistazo al código de la interfaz

public interface HttpMessageConverter<T> {
    
    
    //指定转换器 可以读取的对象类型,即转换器是否可将请求信息转换为clazz类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)
    boolean canRead(Class<?> var1, MediaType var2);
    //指定转换器 是否可将 clazz类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。–LIst getSupportMediaTypes():该转换器支持的媒体类型
    boolean canWrite(Class<?> var1, MediaType var2);
	
    List<MediaType> getSupportedMediaTypes();
	//将请求信息流转换为 T 类型的对象
    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
     //将T类型的对象写到响应流中,同时指定相应的媒体类型为contentType
    void write(T var1, MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

A partir del código de interfaz anterior, se puede ver que el convertidor puede convertir la información de la solicitud o convertir automáticamente la información de respuesta, por lo que, según el ejemplo de solicitud ajax anterior, el método de recepción del código de back-end puede ser

  //以下三种方法头都可以接收前段ajax传入的非application/x-www-form-urlcoded类型信息
 //将传入的json参数自动封装到map里,参数名成是key,参数值时value
 public @ResponseBody Customer getPages(@RequestBody(required=true) Map<String,Object> map , HttpServletRequest request)
 //将传入的json字符串直接复制给username字段
 public @ResponseBody Customer getPages(@RequestBody(required=true) String username, HttpServletRequest request)
 //将传入的json字符串中每个字段的值赋给user对象实例对应名称的属性
 public @ResponseBody Customer getPages(@RequestBody(required=true) User user , HttpServletRequest request)

Nota: Lo anterior es para usar el convertidor predeterminado SpringMVC. Si especifica otros convertidores en el archivo de configuración springmvc, no hay garantía de que se pueda realizar la encapsulación automática anterior, dependiendo de la función de convertidor especificada.

Dos, anotación @ResponseBody

Se utiliza para convertir el objeto devuelto por el método Controller en datos en el formato especificado a través de la interfaz HttpMessageConverter, como json, xml, etc., y responder al cliente a través de la Respuesta.
Nota: No es necesario pasar la cadena, Si hay una clase Java correspondiente, SpringMVC ayudará a convertirla automáticamente en un formato de datos que cumpla con los requisitos (json / xml).
Aquí hay varios métodos que se pueden devolver al tipo correspondiente de json en la sección anterior después de la medición real:

1. Configuración de requisitos previos para los siguientes métodos

En web.xml, configure una intercepción de * .action en la interceptación de solicitudes de DispatcherServlet, que se usa para procesar la devolución de json. Si no se agrega, se llamará por defecto al solucionador de vistas configurado para resolverlo. Si la resolución falla, se informará un error 406. Entonces, después de agregar un nuevo tipo de mapeo, los retornos json se procesan especialmente.

<servlet-mapping>
  <servlet-name>miniappservice</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 解决*.html后缀请求,无法返回json -->
<servlet-mapping>
  <servlet-name>miniappservice</servlet-name>
  <url-pattern>*.action</url-pattern>
 </servlet-mapping>

Cuando se agrega la interceptación de solicitudes

<servlet-mapping>
  <servlet-name>miniappservice</servlet-name>
  <url-pattern>*.action</url-pattern>
 </servlet-mapping>

Todas las solicitudes anteriores que necesitan devolver json deben tener el sufijo action. Por supuesto, action se puede cambiar a cualquier nombre como do

2. Varios @ResponseBody que devuelven el formato json

Dado que procesar el formato json en springmvc requiere el soporte de algunos paquetes jar, primero agregue las siguientes dependencias a la lista pom:

    <!--com.fasterxml.jackson.databind.ObjectMapper servlet配置需要-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.10.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.1</version>
    </dependency>
  • Use la vista MappingJackson2JsonView para devolver el
    archivo de configuración json springmvc ( **-servlet.xml) para configurar el analizador de vista JSP;
    configure en el archivo de configuración springmvc ( **-servlet.xml) <mvc:annotation-driven/>;
    método use @ResponseBodyanotaciones;
    configure la vista MappingJackson2JsonView en el ModelAndView devuelto, y devuelva la instancia de entidad json, Colección o tipo de mapa copiado directamente a ModelAndView, aquí para prestar atención a lo siguiente, si la instancia de entidad, colección o tipo de mapa que se devolverá se agrega a ModelAndView y se especifica el nombre, el nombre json devuelto es el nombre especificado, si no hay nombre se especifica, el json devuelto. El nombre es el nombre en minúsculas de la instancia de entidad, colección o nombre del tipo de mapa. Ver un ejemplo
  @RequestMapping("/test1.action")
    @ResponseBody
    public ModelAndView getDo1(@RequestBody(required=true) String username , HttpServletRequest request){
    
    
        Customer cust=new Customer();
        cust.setLcname("测试");
        cust.setCreatetime(new Timestamp(System.currentTimeMillis()));
        ModelAndView mv=new ModelAndView(new MappingJackson2JsonView());
        mv.addObject(cust);
        return mv;
    }

El parámetro solicitado por la interfaz es una cadena json {"username":"测试","password":"123456fg"}, y el valor inyectado obtenido por el nombre de usuario del parámetro de tipo de cadena @RequestBody en el método es la cadena json pasada desde la interfaz.
La salida de respuesta devuelta a la etapa anterior después de que se ejecuta el método getDo1 es:

{
    
    "customer":{
    
    "sysId":null,"createtime":1577084421101,,"lcname":"马雷"}}

Se puede ver que la salida json al front-end genera el nombre de clase en minúsculas de la instancia cust como la clave de la cadena json, y la fecha de creación y hora se genera de acuerdo con el tipo de marca de tiempo. Si desea formatear la salida de hora, necesita usar la com.fasterxml.jackson.databind.ObjectMapperclase En este momento, modifique el código anterior de la siguiente manera:

@RequestMapping("/test2.action")
    @ResponseBody
    public ModelAndView getDo2(@RequestBody(required=true) String username , HttpServletRequest request){
    
    
        Customer cust=new Customer();
        cust.setLcname("马雷");
        cust.setCreatetime(new Timestamp(System.currentTimeMillis()));
        //引入格式化
        ObjectMapper om=new ObjectMapper();
        om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        ModelAndView mv=new ModelAndView(new MappingJackson2JsonView(om));
        mv.addObject(cust);
        return mv;
    }

Los parámetros de la solicitud permanecen sin cambios y los resultados correspondientes son los siguientes:

{
    
    "customer":{
    
    "sysId":null,"2019-12-23 15:10:41","lcname":"马雷"}}

  • Devuelva directamente el tipo de objeto y genere el archivo de configuración springmvc en formato json ( **-servlet.xml) para configurar el analizador de vista de JSP;
    configure en el archivo de configuración springmvc ( **-servlet.xml) <mvc:annotation-driven/>;
    método use @ResponseBodyanotación;
    método anterior:
 @RequestMapping("/test3.action")
    public @ResponseBody Map<String,Object> getDo3(@RequestBody(required=true) String username , HttpServletRequest request){
    
    
        Customer cust=new Customer();
        cust.setLcname("测试");
        cust.setCreatetime(new Timestamp(System.currentTimeMillis()));
        Map<String,Object> map=new HashMap<>();
        map.put("customer",cust);
        return map;
    }

@ResponseBody se puede marcar en el método o en la firma del método;
los parámetros solicitados por el front-end siguen siendo cadenas json {"username":"测试","password":"123456fg"}. En la siguiente introducción, cada parámetro de solicitud del front-end es esta cadena, por lo que no los repetiré por separado.
El resultado de salida correspondiente al front-end es:

{
    
    "customer":{
    
    "sysId":null,"createtime":1577085315542,"lcname":"测试"}}

Se puede ver que createtime sigue siendo la marca de tiempo de salida y no hay una buena forma de convertirla en un formato de fecha y hora.
Nota: La diferencia entre los dos métodos anteriores
1. Para formatear la fecha, solo se puede usar el primero;
2. Si el json de salida necesita el formato {"clave": "valor", "clave": "valor"}, puede utilizar los dos primeros tipos o el primer tipo y el segundo tipo utilizar encapsulación de mapa;

  • MappingJackson2HttpMessageConverter implementa la salida json.
    Primero **-servlet.xmlconfigure el siguiente código en el archivo de configuración springmvc ( )
   <!-- mvc:annotation-driven:使用mvc注解,解决406同时解决时间问题 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="dateFormat">
                            <bean class="java.text.SimpleDateFormat">
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

El código anterior reemplaza mvc: annotation-
drive ; el segundo paso es usar la anotación @ResponseBody en o sobre el método, vea el código

@RequestMapping("/test4.action")
    public @ResponseBody Customer getDo4(String username,String password, HttpServletRequest request){
    
    
        Customer cust=new Customer();
        cust.setLcname("测试");
        cust.setCreatetime(new Timestamp(System.currentTimeMillis()));
        return cust;
    }

La interfaz utiliza el formato application / x-www-form-urlcoded, y la URL es test4.action? Username = 测试 & password = 123456fg; la
salida de respuesta es

{
    
    
    "sysId": null,
    "createtime": "2019-12-23 16:08:17",
    "lcname": "测试"
}

El front-end también puede usar el formato application / json; charset = UTF-8, y el método de back-end es el siguiente:

@RequestMapping("/test4.action")
    public @ResponseBody List<Customer> getDo4(@RequestBody(required=true) Map<String,Object> map1 , HttpServletRequest request){
    
    
        Customer cust=new Customer();
        cust.setLcname("测试");
        cust.setCreatetime(new Timestamp(System.currentTimeMillis()));
        List<Customer> map=new ArrayList<>();
        map.add(cust);
        return map;
    }

Quiero enfatizar aquí que cuando usa la firma @RequestBody, puede encapsular el mapa para recibir la cadena json desde el front-end, o usar la clase de entidad para recibir la cadena json desde el front-end. No puede usar directamente la cadena string para recibir el front-end. Si se usa el json, reportará un error 400. Además, si la clase de entidad se usa para recibir el string json de la cadena del front-end, el atributo de la clase de entidad es menor que el atributo de la cadena pasada, también se informará el error 400.
La ventaja de utilizar este método para generar json es que puede formatear la fecha;

Además, presento una herramienta, posman se usa para simular solicitudes de depuración, lo cual es particularmente bueno. Dar dos direcciones de referencia:
dirección de descarga,
instrucciones de uso,
parche win7

Supongo que te gusta

Origin blog.csdn.net/u011930054/article/details/103663772
Recomendado
Clasificación