考虑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以这种方式实例化对象?我想这样做,以便我的控制器不需要知道使用什么实现。
答案 0 :(得分:0)
应该可以使用转换器。请参阅文档http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/validation.html。问题是,您如何知道您通过转换器返回哪个班级?而是重新考虑您的设计以在输入中使用POJO。
答案 1 :(得分:0)
我现在已经解决了这个问题,这个概念非常简单,但实现起来可能有点棘手。据我了解,只要提供可以从http请求转换为所需类型的@RequestBody
,就可以使用HttpMessageConverter
注释任何类型。
所以解决方案是:
HttpMessageConverter
HttpMessageConverter
。第二部分可能有点棘手。这是因为spring添加了一堆默认的HttpMessageConverter
,可以处理常见的类型,如字符串,整数,日期,我希望它们能像往常一样继续运行。另一个问题是,如果jackson在路径上,spring还会为通用json处理添加MappingJackson2HttpMessageConverter
,例如转换为具体对象,地图等。 Spring将使用它发现声称能够转换为您的类型的第一个HttpMessageConverter
。 MappingJackson2HttpMessageConverter
声称能够为我的对象执行此操作,但它无法执行此操作,因此失败并且请求失败。这可能被视为一个错误......
我想要的链是:
HttpMessageConverter
s。HttpMessageConverter
MappingJackson2HttpMessageConverter
我找到了两种方法来实现这一目标。首先,您可以通过xml明确声明这一点。
<mvc:annotation-driven>
<mvc:message-converters>
<!-- All converters in specific order here -->
</mvc:message-converters>
</mvc:annotation-driven>
这样做的缺点是,如果默认HttpMessageConverter
链在以后的版本中发生更改,则不会更改您的配置。
另一种方法是在HttpMessageConverter
之前以编程方式插入自己的MappingJackson2HttpMessageConverter
。
@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);
}
}
第二种方法将继续使用“默认配置”,即使它在以后的版本中发生了变化。我认为它有点hacky而且根本不优雅,但我认为它是一个有效的解决方案的原因是MappingJackson2HttpMessageConverter
声称能够转换为无法转换为的类型似乎存在缺陷。此外,您无法明确地将HttpMessageConverter
添加到链中的特定位置。
目前我正在使用第二种选择,但你的做法取决于你......