当前位置: 首页 > 知识库问答 >
问题:

Spring MVC Rest控制器@RequestBody解析

袁和通
2023-03-14

我有一个SpringRest网络应用程序,包含一个通用的Rest控制器,如下所示。在Jackson将对象序列化到JSON的情况下,GET方法运行良好。但是,当我尝试调用保存方法时,请求体参数将被转换为LinkedHashMap,而不是由T泛型类型定义的类型。

@RestController
public abstract class CrudAPI<T extends Object, ID extends Serializable>{

    @Transactional
    @RequestMapping(method = RequestMethod.POST, consumes = "application/json")
    public ResponseEntity<Void> save(@RequestBody T entity){
        service.save(entity);
        return new ResponseEntity(HttpStatus.CREATED);
    }

}

JSON:

{
   "id":null,
   "version":null,
   "name":"Copel",
   "disabled":false,
   "type":"P",
   "labels":[
      {
         "id":null,
         "version":null,
         "name":"unidade consumidora"
      }
   ]
}

我得到以下错误:

HTTP状态500-请求处理失败;嵌套异常是org.springframework.beans.NotReadableProperty tyExcture: bean类[java.util.LinkedHashMap]的无效属性'version':在回退访问期间找不到属性字段!

Spring配置:

@Configuration
@Import(Application.class)
@EnableWebMvc
@ComponentScan(basePackages = {"br.com.doc2cloud"})
public class WebConfig extends WebMvcConfigurerAdapter implements WebApplicationInitializer {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    private MappingJackson2HttpMessageConverter jacksonConverter() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Hibernate5Module());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.setDateFormat(new ISO8601DateFormat());
        mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
        mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
        jacksonConverter.setObjectMapper(mapper);

        return jacksonConverter;
    }

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(jacksonConverter());
        super.configureMessageConverters(converters);
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.setInitParameter("javax.servlet.jsp.jstl.fmt.localizationContext", "messages");
        EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        FilterRegistration.Dynamic characterEncoding = servletContext.addFilter("characterEncoding", characterEncodingFilter);
        characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
    }
}

我的代码有什么问题?

共有2个答案

邰胤
2023-03-14

你用的是哪个版本的Jackson?我升级到2.7.3,当使用泛型时(我有一个基本控制器,具有用于保存、列表等的公共逻辑),我有同样的问题。回滚到2.6.5允许我继续使用我的通用基类。我还没有研究这个问题的原因,但是回滚为我解决了这个问题。

武峻熙
2023-03-14

我认为你不能达到你想要的。Java泛型机制只在编译时工作。编译后,泛型类型被擦除,并被实际类型替换(在您的例子中是Object)。控制器无法理解您试图解析JSON数据的类型。

之所以会得到LinkedHashMap,是因为Jackson默认将其用于“未知”类型。典型的JSON数据实际上是一个键值映射,Jackson保留属性顺序——这就是使用链接哈希映射的原因。

 类似资料:
  • /////////////////////个人控制器///////////////////////////////// ///////////////////个人/////////////////////////////////// ///////////////////PersondaoImpl/////////////////////////// /////////////人(模型)/////

  • 我有一个这样的控制器,我想提交一个带有文件上传的表单,以及一些表单数据,如下图所示的标签。此外,我想使用@RequestBody来实现这一点,以便在添加更多变量时,在包装器上使用@Valid注释。 我的包装纸是: 但我想将其从ModelAttributes转换为@RequestBody。 我尝试的方法是将文件上传作为请求参数分开,如下所示: 在模拟MVC中,我设置: 但我得到了这样一个错误,它说:

  • 我遇到了一种情况,在处理请求之前,我必须更新它。基本上,我必须用一个可以随时间变化的属性来更新请求。要求消费者随请求一起发送属性是不实际的..所以,我觉得唯一的办法就是..在处理请求之前,更新控制器方法中的请求.. 到目前为止,控制器方法中使用了HttpServletRequest。然后将请求读取为流,然后将其转换为json字符串进行处理。我正在考虑用@RequestBody替换它,并将请求读入p

  • 本文向大家介绍Jmeter逻辑控制器事务控制器使用方法解析,包括了Jmeter逻辑控制器事务控制器使用方法解析的使用技巧和注意事项,需要的朋友参考一下 一、基本概念: Transaction controller:一般是指要做的或所做的事情,在关系数据库一个事务可以是一条SQL语句,一组SQL语句或整个程序、在实际的工作过程中,将完成一个业务的一系列操作称作为事务,我们来举最为典型的用户登录场景为

  • 问题内容: 我刚刚开始学习Angular.js,并且一直在Angular主页上的“连接后端”示例中查看project.js。 我对控制器功能中的参数感到困惑: 这些控制器函数在routeProvider中调用,但未给出任何参数。 我能找到到目前为止,这可能解释发生了什么事情的唯一的事情是“注入服务整合到控制器”,这说明,而不是参数的方法和。 我的具体问题是: 控制器参数是什么? 带有参数的控制器功

  • 在创建资源类和指定资源格输出式化后, 下一步就是创建控制器操作将资源通过 RESTful APIs 展现给终端用户。 Yii 提供两个控制器基类来简化创建 RESTful 操作的工作:yii\rest\Controller 和 yii\rest\ActiveController, 两个类的差别是后者提供一系列将资源处理成 Active Record 的操作。 因此如果使用 Active Recor