You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot项目中如何定义无需Content-Type请求头的REST服务

问题原因

你遇到的400错误是Spring MVC的默认消息转换逻辑导致的:@RequestBody注解依赖Content-Type请求头选择对应的HttpMessageConverter来解析请求体,如果客户端不传该头,Spring会默认将请求体识别为application/octet-stream(二进制流),找不到能将二进制流转为Document对象的转换器,因此请求在进入控制器方法前就被拦截,返回400错误。

解决方案

提供两种常用实现方案,可根据业务场景选择:

方案1:全局过滤器补全默认Content-Type(推荐,业务侵入小)

通过过滤器对未携带Content-Type的指定接口请求,自动填充你需要的默认类型(比如接口用JSON就填application/json,XML就填application/xml),完全不修改原有业务代码。

  1. 定义过滤器实现逻辑:
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;

public class DefaultContentTypeFilter implements Filter {
    // 按你的接口实际接收格式修改默认值
    private static final String DEFAULT_CONTENT_TYPE = "application/json";
    private static final String CONTENT_TYPE_HEADER = "Content-Type";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String contentType = httpRequest.getHeader(CONTENT_TYPE_HEADER);
        // 仅对未传Content-Type的请求做处理
        if (contentType == null || contentType.isBlank()) {
            HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpRequest) {
                @Override
                public String getContentType() {
                    return DEFAULT_CONTENT_TYPE;
                }

                @Override
                public String getHeader(String name) {
                    if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) {
                        return DEFAULT_CONTENT_TYPE;
                    }
                    return super.getHeader(name);
                }

                @Override
                public Enumeration<String> getHeaders(String name) {
                    if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) {
                        return Collections.enumeration(Collections.singletonList(DEFAULT_CONTENT_TYPE));
                    }
                    return super.getHeaders(name);
                }
            };
            chain.doFilter(wrapper, response);
            return;
        }
        chain.doFilter(request, response);
    }
}
  1. 注册过滤器,仅对需要的接口生效:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<DefaultContentTypeFilter> defaultContentTypeFilter() {
        FilterRegistrationBean<DefaultContentTypeFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new DefaultContentTypeFilter());
        // 配置需要生效的接口路径,多个接口可以追加
        registrationBean.addUrlPatterns("/mock/iban/payment");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

方案2:手动读取请求体,跳过Spring自动转换

如果仅单个接口有该需求,可以移除@RequestBody注解,自行读取解析请求体,不需要额外加过滤器:

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;

@RestController
@RequestMapping(value="/mock/iban/")
public class IbanController {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @PostMapping(value="/payment")
    ResponseEntity<PaymentResponse> payment(HttpServletRequest request) throws IOException {
        // 自行读取请求体字符串
        String requestBody = request.getReader().lines().reduce("", String::concat);
        // 手动解析为Document对象
        Document doc = objectMapper.readValue(requestBody, Document.class);
        PaymentResponse response = new PaymentResponse();
        return new ResponseEntity<>(response,HttpStatus.OK);
    }
}
注意事项

如果你的接口需要支持多种请求格式,可根据实际请求内容调整默认Content-Type,或者在方案2的逻辑中自行判断请求体格式选择对应的解析方式。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 20:06:03