用于 JSON 数据的 Spring MVC 自定义转换器不起作用

Rag*_*kla 1 java spring json spring-mvc typeconverter

我正在创建一个测试应用程序,以在传递给控制器​​之前实现从 JSON 字符串到员工对象的转换。

以下是执行的关键步骤

  • 创建 Employee.java 类:域对象
  • 创建 EmployeeManagementController.java 类:用于管理员工的 Spring MVC 控制器
  • 创建 EmployeeConverter.java:用于将 JSON 字符串转换为员工对象的自定义转换器。
  • Creation of employee-servlet.xml : Spring Configuration file
  • Creation of web.xml : The Deployment Descriptor

Employee.java

package com.bluebench.training.domain;

import org.springframework.stereotype.Component;

@Component("employee")
public class Employee {

    private PersonalDetail personal;
    private EducationDetail education;
    private WorkExperienceDetail experience;


    // Getters and Setters

}
Run Code Online (Sandbox Code Playgroud)

other domain objects are also defined

EmployeeManagementController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bluebench.training.domain.Employee;

@Controller
public class EmployeeManagementController {

    @RequestMapping(value="/ems/add/employee",method=RequestMethod.POST,consumes="application/json",produces="application/json")
    public @ResponseBody int addEmployee(@RequestBody Employee emp){
        System.out.println("RAGHAVE");
        System.out.println(emp.getPersonal().getName());
        int empId = 20;
        return empId;
    }




}
Run Code Online (Sandbox Code Playgroud)

EmployeeConverter.java

package com.bluebench.training.converter;

import java.io.IOException;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.core.convert.converter.Converter;

import com.bluebench.training.domain.Employee;

public class EmployeeConverter implements Converter<String,Employee>{

    @Override
    public Employee convert(String json) {
        System.out.println("Inside convert()");
        Employee emp = null;
        try {
            emp = new ObjectMapper().readValue(json,Employee.class);
        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }           
        return emp;
    }




}
Run Code Online (Sandbox Code Playgroud)

employee-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"
                xsi:schemaLocation="http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/mvc
                http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

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

                <mvc:annotation-driven  conversion-service="conversionService"/>

                <mvc:default-servlet-handler/>          

                <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 id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
                    <property name="converters">
                        <list>
                            <bean class="com.bluebench.training.converter.EmployeeConverter"/>
                        </list>
                    </property>
                </bean>

            </beans>
Run Code Online (Sandbox Code Playgroud)

web.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>PROJECT_38_SpringMVCRESTFul</display-name>

  <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>
Run Code Online (Sandbox Code Playgroud)

I am using Firefox RestClient to Test it.

Here is the JSON which correctly maps to the Employee object.

{"personal":{"name":"Raghave","age":33,"phoneNumber":"9594511111","address":"101, software appartment, software land , mumbai"},"education":{"qualifications":[{"insititute":"Amity University","degree":"Bachelor of Science","yearOfPassing":"2007","percentage":62.0}]},"experience":{"experience":[{"companyName":"QTBM","designation":"Programmer","years":3,"salary":12000.0},{"companyName":"Polaris","designation":"Software Developer","years":1,"salary":24000.0},{"companyName":"Ness","designation":"Senior Software Engineer","years":2,"salary":50000.0},{"companyName":"JPMC","designation":"Senior Applications Developer","years":1,"salary":120000.0}]}}
Run Code Online (Sandbox Code Playgroud)

There is no Exception thrown and the controller does receive the Employee Object in the addEmployee() method. But its not via converter. The Converter is not invoked. I dont know why ? I dont want to use init binders or @Valid. I wanted to know where am i going wrong. how to make it work?

And*_*son 5

您已经将 Spring 使用 Converters 和 ConversionService 的一般类型转换支持与其对 HTTP 消息转换的支持混淆了,后者专门用于转换 Web 请求和响应并理解媒体类型(如您正在使用的 application/json)。HTTP 消息转换使用 HttpMessageConverter 的实例。

在这种情况下,您实际上并不需要自定义转换器。Spring 的 MappingJacksonHttpMessageConverter 用于自动执行转换。可以自动执行转换,因为大概(您还没有发布 setter,所以我在做一个有根据的猜测),Employee 中的 setter 方法与 JSON 匹配,即 setName、setAge、setPhoneNumber 等。

可以说,您拥有的代码已经可以运行了。您可以安全地删除您的自定义转换器,拥有相同的功能,并且需要维护的代码更少。如果您真的想使用自定义转换器,则需要实现 HttpMessageConverter 并在 MappingJacksonHttpMessageConverter 之前/代替 MappingJacksonHttpMessageConverter 对其进行配置。