You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在spring-servlet.xml配置Jackson ObjectMapper实现@RequestBody转换

我来一步步帮你解决这个问题,咱们从错误根源到配置细节逐个梳理:

一、先搞定HTTP请求头解析错误

你遇到的"Error parsing HTTP request header..."错误,大概率是前端AJAX请求的姿势不对——把JSON数据直接拼到URL里了,或者没正确设置请求头。正确的AJAX应该把JSON放在请求体里,并且指定contentTypeapplication/json,示例代码如下:

var form = { 
    "order":"12r34e56e", 
    "state":"open",
    "date1":"2024-01-01",
    "date2":"2024-01-31",
    "address":"北京市某某区"
};

$.ajax({
    url: "/order/get-unclosed-packages", // 你的Controller接口地址
    type: "POST",
    contentType: "application/json; charset=utf-8", // 必须指定这个,告诉后端是JSON格式
    data: JSON.stringify(form), // 把JS对象转成JSON字符串
    dataType: "json",
    success: function(response) {
        // 把返回的数据传给DataTable渲染
        $('#package-table').DataTable({
            data: response,
            columns: [
                { data: "packageId" },
                { data: "packageState" },
                { data: "createTime" },
                // 其他你需要展示的字段
            ]
        });
    },
    error: function(xhr, status, err) {
        console.log("请求失败:", err);
    }
});
二、Controller正确配置:用@RequestBody接收JSON参数

首先要纠正一个误区:@RequestBody不能直接解析成PreparedStatement对象,它的作用是把请求体的JSON解析成你自定义的Java实体类(DTO)。因为你参数很多,自定义DTO是最清晰的方式。

1. 创建查询参数DTO

public class OrderQueryDTO {
    private String order;
    private String state;
    private String date1;
    private String date2;
    private String address;

    // 必须要有无参构造函数(Jackson默认用它实例化对象)
    public OrderQueryDTO() {}

    // 生成所有字段的getter和setter,或者用Lombok的@Data注解简化
    public String getOrder() { return order; }
    public void setOrder(String order) { this.order = order; }
    // 其他字段的getter/setter同理
}

2. 编写Controller方法

@Controller
@RequestMapping("/order")
public class OrderPackageController {

    // 注入你的WebService客户端(假设已经封装好调用逻辑)
    @Autowired
    private PackageWebServiceClient packageWebService;

    @PostMapping(value = "/get-unclosed-packages", 
                 consumes = MediaType.APPLICATION_JSON_VALUE,
                 produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<PackageVO> getUnclosedPackages(@RequestBody OrderQueryDTO queryDTO) {
        // 1. 用DTO里的参数调用WebService获取包裹列表
        List<WsPackage> wsPackageList = packageWebService.getUnclosedPackages(
            queryDTO.getOrder(),
            queryDTO.getState(),
            queryDTO.getDate1(),
            queryDTO.getDate2(),
            queryDTO.getAddress()
        );

        // 2. 把WebService返回的实体转换成前端DataTable需要的VO对象
        List<PackageVO> packageVOList = convertToVO(wsPackageList);

        // 3. 返回JSON格式的数据,Spring会自动通过Jackson序列化
        return packageVOList;
    }

    // 示例:WebService实体转前端VO
    private List<PackageVO> convertToVO(List<WsPackage> wsPackageList) {
        List<PackageVO> result = new ArrayList<>();
        for (WsPackage wsPkg : wsPackageList) {
            PackageVO vo = new PackageVO();
            vo.setPackageId(wsPkg.getPackageId());
            vo.setPackageState(wsPkg.getStatus());
            vo.setCreateTime(wsPkg.getCreateDate());
            // 其他字段映射
            result.add(vo);
        }
        return result;
    }
}
三、spring-servlet.xml中配置Jackson的ObjectMapper

如果你需要自定义JSON序列化/反序列化规则(比如日期格式、忽略空字段等),可以在spring配置文件里手动配置Jackson的消息转换器:

<!-- 配置RequestMappingHandlerAdapter,指定自定义的Jackson转换器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <ref bean="jackson2HttpMessageConverter"/>
        </list>
    </property>
</bean>

<!-- 自定义Jackson消息转换器 -->
<bean id="jackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="objectMapper">
        <bean class="com.fasterxml.jackson.databind.ObjectMapper">
            <!-- 配置日期格式化规则,适配前端传的date1/date2 -->
            <property name="dateFormat">
                <bean class="java.text.SimpleDateFormat">
                    <constructor-arg value="yyyy-MM-dd"/>
                </bean>
            </property>
            <!-- 只序列化非空字段,减少返回数据体积 -->
            <property name="serializationInclusion" value="NON_NULL"/>
            <!-- 关闭日期转时间戳,返回格式化后的字符串 -->
            <property name="disable" value="WRITE_DATES_AS_TIMESTAMPS"/>
        </bean>
    </property>
    <!-- 指定支持的媒体类型 -->
    <property name="supportedMediaTypes">
        <list>
            <value>application/json;charset=UTF-8</value>
        </list>
    </property>
</bean>
四、常见问题排查
  1. Jackson依赖是否完整:确保pom.xml里包含了jackson-databindjackson-corejackson-annotations三个核心依赖,版本要和你的Spring版本兼容(比如Spring 5.x对应Jackson 2.9+)。
  2. DTO字段名匹配:如果前端传的key和DTO字段名不一致,可以用@JsonProperty注解指定,比如@JsonProperty("order") private String orderNo;
  3. 是否开启了MVC注解驱动:如果你的spring-servlet.xml里有<mvc:annotation-driven/>,它会自动注册Jackson转换器,但如果手动配置了上面的转换器,需要注意避免冲突。

内容的提问来源于stack exchange,提问作者fuvu

火山引擎 最新活动