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

无web.xml配置Spring MVC时Postman请求RestController返回400错误

问题原因

400错误由配置错误+请求规则不匹配共同导致,核心诱因有三点:

  • 类级别@RequestMapping错误添加了consumes = MediaType.APPLICATION_JSON_UTF8_VALUE属性,强制该控制器下所有接口(包括无请求体的GET接口)必须匹配JSON请求的Content-Type。浏览器发GET请求时默认不带Content-Type头,Spring会跳过校验因此访问正常;Postman会记忆上次请求的Header配置,若默认带上了非JSON类型的Content-Type(如form-data、x-www-form-urlencoded),会触发校验失败(部分Spring版本下媒体类型不匹配会返回400而非标准的415状态码)。
  • Spring容器分层配置错误:@EnableWebMvc属于Spring MVC Web层的配置注解,被错误放在了根容器(RootConfig)中。根容器负责管理Service、DAO等业务持久层Bean,DispatcherServlet对应的子容器才负责管理Controller、消息转换器、参数解析器等Web层组件,配置错位会导致JSON解析、请求匹配逻辑异常。
  • 若Postman发送的是POST请求,大概率是请求配置错误:未设置Content-Type为application/json、请求体JSON格式非法、字段与Curso实体类不匹配、实体类缺少无参构造方法导致Jackson反序列化失败,都会触发400错误。
解决方法

按以下步骤逐一修复:

1. 修正控制器的请求映射配置

将consumes属性从类级别移到需要接收JSON请求体的POST方法上,避免给GET接口强加不必要的请求限制:

@RestController
@RequestMapping(
    value = "/cursos",
    produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public class CursoRestController {

    @Autowired
    private CursoService cursoService;

    @GetMapping
    @ResponseStatus(HttpStatus.OK)
    public List<Curso> listAll() {
        System.out.println("Test");
        return cursoService.findAll();
    }

    // 只给POST方法加consumes限制
    @PostMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Void> save(@RequestBody Curso curso) {
        cursoService.save(curso);
        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(curso.getId())
                .toUri();
        return ResponseEntity.created(location).build();
    }
}

2. 修正Spring容器分层配置

将Web层配置和业务持久层配置拆分,避免容器扫描错位:

  • 新增独立的Web层配置类SpringWebConfig,将@EnableWebMvc移到此类中,专门扫描Controller包:
@Configuration
@EnableWebMvc
@ComponentScan("br.com.gabriel.restful.controller")
public class SpringWebConfig implements WebMvcConfigurer {
    // 如需配置静态资源映射、自定义消息转换器可在此处重写对应方法
}
  • 修改SpringRootConfig,移除@EnableWebMvc注解,排除Web层组件扫描,显式导入JPA配置避免漏扫:
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "br.com.gabriel.restful",
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                value = RestController.class
        ))
@Import(SpringJpaConfig.class)
public class SpringRootConfig {
}
  • 修改SpringInitConfig,将Web配置类注册到DispatcherServlet的子容器中:
public class SpringInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringRootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringWebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

3. 检查Postman请求配置

  • 发GET请求时不要手动设置Content-Type头,直接访问/cursos即可。
  • 发POST请求时按以下要求配置:
    • 请求头添加Content-Type: application/json
    • Body选择raw类型,右侧下拉选择JSON格式
    • 传入合法JSON,字段与Curso实体类属性一一对应,示例:
    {
      "nome": "Spring MVC入门课程",
      "cargaHoraria": 40
    }
    
  • 确认Curso实体类添加了public无参构造方法,避免Jackson反序列化失败。

4. 调试定位(可选)

如果修复后仍返回400,添加日志配置打印具体错误原因,在项目resources目录下的配置文件中添加:

# SpringMVC web层调试日志
logging.level.org.springframework.web=DEBUG
# JSON反序列化日志
logging.level.com.fasterxml.jackson.databind=DEBUG

重启项目后发请求,控制台会明确打印400错误的具体触发点(如JSON字段不匹配、参数缺失等)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:45:33