zoukankan      html  css  js  c++  java
  • springmvc4.3.7中使用RequestBody,传入json参数时,得到错误415 Unsupported Media Type

    在新建一个maven的项目的时候,当时并非springboot项目,是通过xml来配置的项目。在项目中DispatcherServlet的配置文件中配置了annotation-driven的,

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
    
        <description>spring Configuration</description>
        
        <mvc:annotation-driven />
    
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/" />
            <property name="suffix" value=".jsp" />
        </bean>
    
        <context:component-scan base-package="org.xuan.springmvc.controller"
            use-default-filters="false"><!-- base-package 如果多个,用“,”分隔 -->
            <context:include-filter type="annotation"
                expression="org.springframework.stereotype.Controller" /> <!-- 子标签是用来添加扫描注解的 -->
        </context:component-scan>
    </beans>

    后台接口定义方式:

        @RequestMapping("testrequest")
        @ResponseBody
        public String testRequest(@RequestBody User user) throws Exception {
            System.out.println(user);
            return "OK";
        }

    User.java定义

    package org.xuan.springmvc.model;
    
    
    public class User {
    
        private int id;
        private String username;
        
        private String password;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
    }

    前台请求方式:

        $("#test").click(function () {
            alert("aa")
            var param={
                id:1,
                username:"test"
            };
            $.ajax({
                url : "/testrequest",
                type : "POST",
                dataType : "json",
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify(param),
                success:function (data) {
                    alert(data)
                }
            });
        })

    结果发现不能请求成功:

    发现请求类型不正确。

    跟踪源码到AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters发现消息装换器messageConverters没有列出解析json格式的解析器:

    查询文档https://docs.spring.io/spring-framework/docs/4.3.7.RELEASE/spring-framework-reference/html/mvc.html看默认的消息转换器有哪些

    To enable MVC Java config add the annotation @EnableWebMvc to one of your @Configuration classes:

    @Configuration
    @EnableWebMvc
    public class WebConfig {
    
    }

    To achieve the same in XML use the mvc:annotation-driven element in your DispatcherServlet context (or in your root context if you have no DispatcherServlet context defined):

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <mvc:annotation-driven/>
    
    </beans>

    The above registers a RequestMappingHandlerMapping, a RequestMappingHandlerAdapter, and an ExceptionHandlerExceptionResolver (among others) in support of processing requests with annotated controller methods using annotations such as @RequestMapping@ExceptionHandler, and others.

    It also enables the following:

    1. Spring 3 style type conversion through a ConversionService instance in addition to the JavaBeans PropertyEditors used for Data Binding.
    2. Support for formatting Number fields using the @NumberFormat annotation through the ConversionService.
    3. Support for formatting DateCalendarLong, and Joda Time fields using the @DateTimeFormat annotation.
    4. Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath.
    5. HttpMessageConverter support for @RequestBody method parameters and @ResponseBody method return values from @RequestMapping or @ExceptionHandler methods.

      This is the complete list of HttpMessageConverters set up by mvc:annotation-driven:

      1. ByteArrayHttpMessageConverter converts byte arrays.
      2. StringHttpMessageConverter converts strings.
      3. ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.
      4. SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.
      5. FormHttpMessageConverter converts form data to/from a MultiValueMap<String, String>.
      6. Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML — added if JAXB2 is present and Jackson 2 XML extension is not present on the classpath.
      7. MappingJackson2HttpMessageConverter converts to/from JSON — added if Jackson 2 is present on the classpath.
      8. MappingJackson2XmlHttpMessageConverter converts to/from XML — added if Jackson 2 XML extension is present on the classpath.
      9. AtomFeedHttpMessageConverter converts Atom feeds — added if Rome is present on the classpath.
      10. RssChannelHttpMessageConverter converts RSS feeds — added if Rome is present on the classpath.

    原来使用MappingJackson2HttpMessageConverter 需要引入相关的jar

    然后引入包:

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.8.5</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.8.5</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.8.5</version>
            </dependency>

    在调一次接口发现增加了json解析:

    最后调用成功。

     原因是在创建RequestMappingHandlerAdapter的时候加载messageConverters

        public RequestMappingHandlerAdapter() {
            StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
            stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316
    
            this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
            this.messageConverters.add(new ByteArrayHttpMessageConverter());
            this.messageConverters.add(stringHttpMessageConverter);
            this.messageConverters.add(new SourceHttpMessageConverter<Source>());
            this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        }

    在AllEncompassingFormHttpMessageConverter中会判断是否jvm是否加载了类com.fasterxml.jackson.databind.ObjectMapper和com.fasterxml.jackson.core.JsonGenerator,只有加载了才会创建

    public AllEncompassingFormHttpMessageConverter() {
            addPartConverter(new SourceHttpMessageConverter<Source>());
    
            if (jaxb2Present && !jackson2XmlPresent) {
                addPartConverter(new Jaxb2RootElementHttpMessageConverter());
            }
    
            if (jackson2Present) {
                addPartConverter(new MappingJackson2HttpMessageConverter());
            }
            else if (gsonPresent) {
                addPartConverter(new GsonHttpMessageConverter());
            }
    
            if (jackson2XmlPresent) {
                addPartConverter(new MappingJackson2XmlHttpMessageConverter());
            }
        }

     

    备注:

     解析传入的参数是:AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters

     解析返回值是:AbstractMessageConverterMethodProcessor#writeWithMessageConverters
  • 相关阅读:
    Angular.js为什么如此火呢?
    Javascript实现页面跳转的几种方式
    Bootstrap:弹出框和提示框效果以及代码展示
    Bootstrap模态框(modal)垂直居中
    JS倒计时跳转页面
    复选框、单选框与文字对齐问题
    RFC/IEC/ISO
    shell
    websocket programming in python
    产品固件(系统)升级——curl/wget
  • 原文地址:https://www.cnblogs.com/grasp/p/11075884.html
Copyright © 2011-2022 走看看