Java 未使用自定义 HTTP 消息转换器,415 不受支持的媒体类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21349030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:12:28  来源:igfitidea点击:

Custom HTTP Message Converter Not Being Used, 415 Unsupproted Media Type

javaspringrestspring-mvc

提问by Raghave Shukla

I am creating a test application to achieve conversion from XML String to Employee object before being passed to the controller. I don't want to use JAXB converter because the purpose is to test Custom HTTP Message Converter which I am going to use in my actual use case that involves XML parsing using SAX parser and some complex rules.

我正在创建一个测试应用程序,以在传递给控制器​​之前实现从 XML 字符串到 Employee 对象的转换。我不想使用 JAXB 转换器,因为目的是测试自定义 HTTP 消息转换器,我将在我的实际用例中使用它,涉及使用 SAX 解析器和一些复杂规则进行 XML 解析。

Here are the key steps performed:

以下是执行的关键步骤:

  • Creation of Employee.java Class: Domain Object
  • Creation of EmployeeManagementController.java class: Spring MVC Controller for Managing Employee
  • Creation of EmployeeConverter.java: Custom Converter for Converting XML String to Employee Object.
  • Creation of employee-servlet.xml: Spring Configuration file
  • Creation of web.xml: The Deployment Descriptor
  • 创建 Employee.java 类:域对象
  • 创建 EmployeeManagementController.java 类:用于管理员工的 Spring MVC 控制器
  • 创建 EmployeeConverter.java:用于将 XML 字符串转换为员工对象的自定义转换器。
  • 创建employee-servlet.xml: Spring 配置文件
  • 创建 web.xml:部署描述符

Employee.java

雇员.java

@Component
@XmlRootElement(name="employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee{

@XmlElement(name="name")
String name;
@XmlElement(name="designation")
String designation;
@XmlElement(name="skill")
String skill;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}

}

EmployeeManagementController.java

员工管理控制器.java

@Controller
@RequestMapping(value="/emp")
public class EmployeeManagementController {

    @RequestMapping(value="/add/employee", method=RequestMethod.POST, consumes="text/html")
    public void addEmployee(@RequestBody Employee employee){
        System.out.println("Employee Name : "+employee.getName());
        System.out.println("Employee Designation : "+employee.getDesignation());
        System.out.println("Employee Skill : "+employee.getSkill());

    }


}

EmployeeConverter.java

EmployeeConverter.java

@Component
public class EmployeeConverter extends AbstractHttpMessageConverter<Employee>{

    @Override
    protected Employee readInternal(Class<? extends Employee> arg, HttpInputMessage inputMsg) throws IOException,
            HttpMessageNotReadableException {
        // TODO Auto-generated method stub
        Map<String,String> paramMap = getPostParameter(inputMsg);
        BufferedReader file =  new BufferedReader(new StringReader(paramMap.get("xml")));
        Employee employee = null;
        JAXBContext jaxbContext;
        try {
            jaxbContext = JAXBContext.newInstance(Employee.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            employee = (Employee) jaxbUnmarshaller.unmarshal(file);
        } catch (JAXBException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(employee);
        return employee;
    }

    @Override
    protected boolean supports(Class<?> type) {
        if(type.getSimpleName().equalsIgnoreCase("Employee")){
            return true;
        }
        return false;
    }

    @Override
    protected void writeInternal(Employee arg0, HttpOutputMessage arg1)
            throws IOException, HttpMessageNotWritableException {
        // TODO Auto-generated method stub

    }

    private Map<String,String> getPostParameter(HttpInputMessage input) throws IOException{
        String payload = null;
        String[] params = null;
        BufferedReader buf = new BufferedReader(new InputStreamReader(input.getBody()));
        Map<String,String> paramMap = new HashMap<String,String>();

        String line="";
        while((line = buf.readLine())!=null){
            payload = payload+line;
        }

        if(payload.contains("&")){
            params = payload.split("&");
            for(String param : params){
                paramMap.put(param.split("=")[0],param.split("=")[1]);
            }
        }

        return paramMap;
    }


}

employee-servlet.xml

员工servlet.xml

<?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:util="http://www.springframework.org/schema/util"
                xsi:schemaLocation="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/mvc
                http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                http://www.springframework.org/schema/util
                http://www.springframework.org/schema/util/spring-util-3.1.xsd">

         <mvc:default-servlet-handler/> 

        <context:component-scan base-package="com"/>

         <mvc:annotation-driven>
            <mvc:message-converters>
                <bean class="com.converter.EmployeeConverter"/>             
            </mvc:message-converters>
        </mvc:annotation-driven>

        <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
            <property name="mediaTypes">
                <map>
                    <entry key="json" value="application/json"/>
                    <entry key="xml" value="text/xml"/>
                    <entry key="htm" value="text/html"/>
                </map>
            </property>
            <property name="defaultContentType" value="text/html"/>
        </bean>

        <!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
            <property name="messageConverters">    
                <util:list id="beanList">
                    <ref bean="employeeConverter"/>       
                </util:list>
            </property>
        </bean>  -->

        <!-- <bean id="employeeConverter" class="com.converter.EmployeeConverter"/> -->



</beans>

web.xml

网页.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>TestConverter</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>    
  </welcome-file-list>

  <servlet>
    <servlet-name>employee</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  <servlet-name>employee</servlet-name>
  <url-pattern>/*</url-pattern>
  </servlet-mapping>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/employee-servlet.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

</web-app>

When I Use FireFox RestClient I get Response as : 415 Unsupproted Media Type.

当我使用 FireFox RestClient 时,我得到的响应为:415 Unsupproted Media Type。

I set the Content-Type and Accept header as text/xml in RestClient and pass the following XML string in the body as parameter:

我在 RestClient 中将 Content-Type 和 Accept 标头设置为 text/xml 并在正文中传递以下 XML 字符串作为参数:

xml=<employee><name>Hyman</name><designation>Account Director</designation><skill>Commuication</skill></employee>

Can somebody help and let me know what changes are required? I have also tried to use AnnotationMethodHandlerAdapterfor registering the message converter.

有人可以帮忙并让我知道需要进行哪些更改吗?我也尝试过AnnotationMethodHandlerAdapter用于注册消息转换器。

采纳答案by Ralph

1. Set Media Type

1. 设置媒体类型

Comparing your implementation with some HttpMessageConverterimplementations provided by Spring (for example ′MappingHymanson2HttpMessageConverter′), shows that you missed to define the supportedMediaTypes.

将您的实现与HttpMessageConverterSpring 提供的一些实现(例如“MappingHymanson2HttpMessageConverter”)进行比较,表明您错过了定义supportedMediaTypes.

The common way* of HttpMessageConverterthat extends AbstractHttpMessageConverter<T>is to set the media type in the constructor, by using the super constructor AbstractHttpMessageConverter.(MediaType supportedMediaType).

HttpMessageConverter扩展的常用方法*AbstractHttpMessageConverter<T>是通过使用超级构造函数在构造函数中设置媒体类型AbstractHttpMessageConverter.(MediaType supportedMediaType)

 public class EmployeeConverter extends AbstractHttpMessageConverter<Employee> {
      public EmployeeConverter() {
            super(new MediaType("text", "xml", Charset.forName("UTF-8")));
      }
 }

BTW 1: you can also register more then one media type**

BTW 1:您还可以注册不止一种媒体类型**

super(MediaType.APPLICATION_XML,
      MediaType.TEXT_XML,
      new MediaType("application", "*+xml")); 

BTW 2: for xml conterter one should think extending from AbstractXmlHttpMessageConverter<T>

BTW 2:对于 xml conterter 应该考虑从 AbstractXmlHttpMessageConverter<T>

2. Register you Converter

2. 注册您的转换器

<mvc:annotation-driven>
    <mvc:message-converters>
       ...
       <bean class="com.example.YourConverter"/>
    </mvc:message-converters>
</mvc:annotation-driven>

The major drawback of <mvc:message-converters>is, that this replace the default configuration, so you must also register all default HttpMessageConverterexplicit.

的主要缺点<mvc:message-converters>是,这会替换默认配置,因此您还必须注册所有默认HttpMessageConverter显式。

To keep the default message convertes you need to use: <mvc:message-converters register-defaults="true">...

要保留默认消息转换,您需要使用: <mvc:message-converters register-defaults="true">...

  • *used by the other implementations like MappingHymanson2HttpMessageConverter′
  • **example take from AbstractXmlHttpMessageConverter<T>
  • *由其他实现使用,如 MappingHymanson2HttpMessageConverter'
  • **示例取自 AbstractXmlHttpMessageConverter<T>