springboot @RequestHeader 实体对象接收header json参数

本文介绍了一种自定义Spring MVC的RequestHeaderMethodArgumentResolver的方法,通过创建ReplaceRequestHeaderMethodArgumentResolver类,可以更灵活地处理HTTP请求头中的数据,支持JSON格式的请求头解析。
部署运行你感兴趣的模型镜像

构建ReplaceRequestHeaderMethodArgumentResolver

    @PostMapping("/test")
    public void listProject(@RequestHeader UserInfo userInfo){
    	System.out.println(curUserInfo);
    }
curl --location --request POST 'localhost:8080/me/test' \
--header 'userInfo: {"openId":"111"}' \
--header 'Content-Type: application/json' \
--data-raw '{}'
package com.xx.xx.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import java.net.URLDecoder;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description:
 * @Copyright: Copyright (c) 2019  ALL RIGHTS RESERVED.
 * @CreateDate: 2020/3/5 12:26
 * @UpdateDate: 2020/3/5 12:26
 * @UpdateRemark: init
 * @Version: 1.0
 * @menu mapper配置类
 */
@Component
public class ReplaceRequestHeaderMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {

    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    @Autowired
    private DefaultListableBeanFactory defaultListableBeanFactory;

    public ReplaceRequestHeaderMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
        super(beanFactory);
    }

    @PostConstruct
    public void init(){

        List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(requestMappingHandlerAdapter.getArgumentResolvers());
        for (int i=0;i<resolvers.size();i++){
            if (resolvers.get(i) instanceof RequestHeaderMethodArgumentResolver){
                resolvers.set(i,new ReplaceRequestHeaderMethodArgumentResolver(defaultListableBeanFactory));
            }
        }
        requestMappingHandlerAdapter.setArgumentResolvers(resolvers);
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return (parameter.hasParameterAnnotation(RequestHeader.class) &&
                !Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType()));
    }

    @Override
    protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
        RequestHeader ann = parameter.getParameterAnnotation(RequestHeader.class);
        Assert.state(ann != null, "No RequestHeader annotation");
        return new ReplaceRequestHeaderMethodArgumentResolver.RequestHeaderNamedValueInfo(ann);
    }

    @Override
    @Nullable
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        String[] headerValues = request.getHeaderValues(name);

        if (headerValues == null){
            return null;
        }

        if (parameter.getParameterType() != String.class){
            String objStr = headerValues[0];
            if (StringUtils.isEmpty(objStr)){
                return null;
            }
            String decode = URLDecoder.decode(objStr, "UTF-8");
            return this.objectMapper.readValue(decode,parameter.getParameterType());
        }

        return (headerValues.length == 1 ? headerValues[0] : headerValues);
    }

    @Override
    protected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {
        throw new MissingRequestHeaderException(name, parameter);
    }


    private static final class RequestHeaderNamedValueInfo extends NamedValueInfo {

        private RequestHeaderNamedValueInfo(RequestHeader annotation) {
            super(annotation.name(), annotation.required(), annotation.defaultValue());
        }
    }
}

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>我们正在处理的问题是:Spring Boot POST接口接收JSON数据转换为对象时属性都为null的解决方案。 根据提供的引用,我们可以总结出以下几个可能的原因和解决方案: 1. 字段命名问题:JSON中的字段名与Java实体类的属性名不匹配。例如,Java使用驼峰命名,而JSON使用下划线命名,或者大小写不一致。 解决方案:在实体类的字段上使用@JsonProperty注解来指定JSON字段名,或者在setter方法上使用该注解。 2. 使用了不同的JSON解析库:Spring Boot默认使用Jackson,但项目中可能引入了Fastjson,并且配置了优先使用Fastjson,而Fastjson的配置可能导致解析问题。 解决方案:检查并确保JSON解析库的配置正确。如果使用Fastjson,可能需要配置HttpMessageConverter;如果使用Jackson,可能需要检查其配置。 3. 没有提供无参构造函数:Jackson在反序列化时需要无参构造函数(或通过其他方式构造,如Builder),如果实体类没有无参构造,可能导致反序列化失败。 解决方案:确保实体类有一个无参构造函数(可以是默认的)。 4. 字段的访问权限问题:如果实体类的字段是私有的,并且没有提供getter/setter方法,那么Jackson无法访问这些字段(除非配置了字段可见性)。 解决方案:为字段提供public的getter和setter方法,或者使用注解(如@JsonProperty)在字段上并配置Jackson可见性。 5. 使用了错误的注解:可能没有使用@RequestBody注解,或者使用了其他不正确的注解。 解决方案:确保在控制器方法的参数前正确使用了@RequestBody注解。 6. 全局参数预处理问题:可能需要配置全局的参数预处理,如使用@ControllerAdvice和@InitBinder(但这种情况较少用于JSON解析,可能更多用于表单数据)。 7. 请求的Content-Type不正确:如果请求的Content-Type不是application/json,Spring可能无法正确解析。 解决方案:确保请求头中的Content-Type设置为application/json。 8. 其他配置问题:例如,Spring Boot的自动配置可能被覆盖,或者自定义的HttpMessageConverter配置有误。 根据引用[1]和[3]的案例,我们可以给出以下具体步骤: 步骤1:检查字段命名并使用@JsonProperty 在实体类中,如果JSON字段名和Java属性名不一致,可以使用@JsonProperty注解。例如: ```java public class User { @JsonProperty("username") // 如果JSON中有字段"username",就会映射到userName属性 private String userName; // getter and setter } ``` 步骤2:检查JSON解析库的配置 如果项目中同时存在Jackson和Fastjson,并且你想使用Fastjson,需要配置Fastjson的HttpMessageConverter,并设置其优先级(如引用[3]所述)。如果使用Jackson,确保没有错误的配置。 步骤3:确保有无参构造函数 例如: ```java public class User { public User() { } // ... 其他代码 } ``` 步骤4:检查getter/setter方法 确保每个需要映射的属性都有public的getter和setter方法。 步骤5:检查@RequestBody注解 确保在控制器方法中正确使用了@RequestBody注解: ```java @PostMapping("/add") public ResponseEntity<?> addUser(@RequestBody User user) { // ... } ``` 步骤6:检查请求的Content-Type 使用Postman等工具发送请求时,确保请求头中Content-Type为application/json。 步骤7:检查全局配置 如果以上步骤都无效,检查是否有全局的配置影响了JSON解析,例如自定义的WebMvcConfigurer中配置了消息转换器。 根据引用[3]的情况,当发现FastJsonHttpMessageConverter已经在MappingJackson2HttpMessageConverter之前,并且问题解决,说明可能是消息转换器的顺序问题。如果你使用Fastjson,可以尝试配置如下: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 移除默认的Jackson转换器 converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); // 创建Fastjson转换器并添加到列表 FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter(); converters.add(0, fastJsonConverter); // 添加到第一个位置,使其优先 } } ``` 但是请注意,如果这样配置,需要确保Fastjson的依赖和配置正确。另外,也可以选择使用Jackson并解决其配置问题。 如果问题仍然存在,可以尝试在实体类上使用@JsonIgnoreProperties(ignoreUnknown = true)来忽略不匹配的字段,但这并不能解决字段为null的问题,只能避免因未知字段而报错。 最后,如果以上方法都无效,建议调试Spring MVC的源码,查看消息转换器的工作情况,或者检查JSON数据的格式是否正确。 由于问题可能由多种原因引起,需要逐一排查。 生成的相关问题: 1. 如何正确配置Spring Boot使用Fastjson? 2. Jackson和Fastjson在Spring Boot中有什么区别? 3. 如何调试Spring MVC的HttpMessageConverter? 4. 除了@RequestBody,还有哪些方式可以接收POST请求的JSON数据? 5. 如何全局处理Spring Boot中的参数绑定问题? </think> ### Spring Boot POST接口接收JSON数据时属性为null的解决方案 根据引用内容分析,常见原因及解决方法如下: #### 1. **字段命名不匹配**(最常见) 当JSON字段名与Java实体类属性名不一致时(如驼峰vs下划线),会导致属性无法映射: ```java public class User { @JsonProperty("username") // 显式指定JSON字段名 private String userName; // Java使用驼峰命名 // 必须提供setter方法 public void setUserName(String userName) { this.userName = userName; } } ``` > **关键点**:使用`@JsonProperty`注解明确映射关系[^1] #### 2. **JSON解析库冲突** Spring Boot默认使用Jackson,但Fastjson优先级可能导致问题: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 移除默认Jackson转换器 converters.removeIf(c -> c instanceof MappingJackson2HttpMessageConverter); // 显式添加Jackson并设置优先级 converters.add(0, new MappingJackson2HttpMessageConverter()); } } ``` > 引用[3]显示解析库冲突是常见原因,需调整转换器顺序 #### 3. **缺失Setter方法** 实体类必须为每个属性提供setter方法: ```java // ❌ 错误示例:缺少setter public class User { private String username; } // ✅ 正确示例 public class User { private String username; // 必须添加setter public void setUsername(String username) { this.username = username; } } ``` #### 4. **请求格式问题** 确保请求满足: - **Header**:`Content-Type: application/json` - **Body**:标准JSON格式(引号、逗号正确) ```json // ✅ 正确 {"username": "John", "age": 25} // ❌ 错误(缺少引号) {username: "John", age: 25} ``` #### 5. **构造函数问题** 若使用含参构造,需配合`@JsonCreator`: ```java public class User { private String username; @JsonCreator public User(@JsonProperty("username") String username) { this.username = username; } } ``` #### 完整排查流程图 ```mermaid graph TD A[属性为null] --> B[检查JSON字段名与属性名] B -->|不匹配| C[添加@JsonProperty] B -->|匹配| D[检查setter方法] D -->|缺失| E[添加setter] D -->|存在| F[检查JSON解析库] F -->|Fastjson冲突| G[调整转换器顺序] F -->|Jackson正常| H[检查请求格式] H -->|Content-Type错误| I[设置为application/json] H -->|JSON语法错误| J[校验JSON格式] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值