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
Custom HTTP Message Converter Not Being Used, 415 Unsupproted Media Type
提问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 AnnotationMethodHandlerAdapter
for registering the message converter.
有人可以帮忙并让我知道需要进行哪些更改吗?我也尝试过AnnotationMethodHandlerAdapter
用于注册消息转换器。
采纳答案by Ralph
1. Set Media Type
1. 设置媒体类型
Comparing your implementation with some HttpMessageConverter
implementations provided by Spring (for example ′MappingHymanson2HttpMessageConverter′), shows that you missed to define the supportedMediaTypes
.
将您的实现与HttpMessageConverter
Spring 提供的一些实现(例如“MappingHymanson2HttpMessageConverter”)进行比较,表明您错过了定义supportedMediaTypes
.
The common way* of HttpMessageConverter
that 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 HttpMessageConverter
explicit.
的主要缺点<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>