3

考虑 spring 项目中的以下接口/对象层次结构:

public interface MyInterface {
    //method defenitions
}

@Component
@Scope(SCOPE_PROTOTYPE)
public class MyClass implements MyInterface {
   //method implementations
}

MyClass在从请求正文中读取它的控制器方法中使用:

@RequestMapping(method = POST, value = "/posturi", consumes = "application/json")
public void createEntity(@RequestBody MyClass myClass) {
    //handle request
}

jackson 库用于读取 json 数据并将其转换为 java 对象。

我想将控制器方法中的参数类型从MyClass更改为MyInterface。这似乎不起作用,因为无法使用new操作员实例化接口。但它可以这样创建:

MyInterface instance = applicationContext.getBean(MyInterface.class);

是否可以让 spring/jackson 以这种方式实例化对象?我想这样做,这样我的控制器就不需要知道使用了什么实现。

4

2 回答 2

0

转换器应该可以。请参阅文档http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/validation.html。问题是,你怎么知道转换器返回哪个类?而是重新考虑您的设计以在输入中使用 POJO。

于 2013-05-17T18:29:24.743 回答
0

我现在已经解决了这个问题,这个概念很简单,但实现起来可能有点棘手。据我了解,@RequestBody只要您提供HttpMessageConverter可以从 http 请求转换为所需类型的类型,就可以注释任何类型。所以解决方案是:

  1. 实施一个HttpMessageConverter
  2. 配置 spring 以便使用您HttpMessageConverter的。

第二部分可能有点棘手。这是因为 spring 添加了一堆默认值HttpMessageConverter,可以处理字符串、整数、日期等常见类型,我希望这些可以继续像往常一样工作。另一个问题是,如果jackson在路径上,spring还添加了一个MappingJackson2HttpMessageConverter用于通用json处理例如转换为具体对象、地图等。Spring 将使用HttpMessageConverter它发现的第一个声称能够转换为您的类型的类型。MappingJackson2HttpMessageConverter声称能够为我的对象这样做,但它不能,因此它失败并且请求失败。这可以被认为是一个错误......

我想要的链条是:

  1. 弹簧默认HttpMessageConverters。
  2. 我自己的HttpMessageConverter
  3. MappingJackson2HttpMessageConverter

我找到了两种方法来实现这一点。首先,您可以通过 xml 显式声明它。

<mvc:annotation-driven>
    <mvc:message-converters>
        <!-- All converters in specific order here -->
    </mvc:message-converters>
</mvc:annotation-driven>

这样做的缺点是,如果默认HttpMessageConverter链在以后的版本中发生更改,它不会因您的配置而更改。

另一种方法是HttpMessageConverterMappingJackson2HttpMessageConverter.

@Configuration
public class MyConfiguration {

    @Autowired
    private RequestMappingHandlerAdapter adapter;

    @Autowired
    private MyHttpMessageConverter myHttpMessageConverter;

    @PostConstruct
    private void modify() {
        List<HttpMessageConverter<?>> messageConverters = adapter.getMessageConverters();
        int insertLocation = messageConverters.size() - 1;
        for (int i = 0; i < messageConverters.size(); i++) {
            Object messageConverter = messageConverters.get(i);
            if (messageConverter instanceof MappingJackson2HttpMessageConverter) {
                insertLocation = i;
            }
        }
        messageConverters.add(insertLocation, myHttpMessageConverter);
    }
}

第二种选择将继续使用“默认配置”,即使它在以后的版本中发生更改。MappingJackson2HttpMessageConverter我认为它有点hacky,一点也不优雅,但我认为它是一个有效的解决方案的原因是,声称能够转换为它无法转换的类型似乎存在缺陷。而且您不能明确地将 a 添加HttpMessageConverter到链中的特定位置。

现在我选择第二个选项,但你怎么做取决于你......

于 2013-05-21T07:23:01.283 回答