请原谅我冗长而描述性的问题。感谢您花时间阅读本文。
我在持久层之上有一个自定义的spring数据休息实现。 我使用UUID作为对象的id类型,而不是使用原始类型 持续存在。
我有一个像这样的存储库:
public interface DummyRepository extends PagingAndSortingRepository<Dummy, UUID> { }
我有我的自定义DummyController来执行GET和POST到存储库,如下所示:
@RestController
public class DummyController {
@Autowired
DummyRepository dummyRepository;
@Autowired
DummyResourceProcessor processor;
@RequestMapping(value="/dummies", method = POST,
consumes=MediaType.APPLICATION_JSON_VALUE,
produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Resource<Dummy>> createDummy(@RequestBody Dummy
dummy){
Dummy save = dummyRepository.save(dummy);
Resource<Dummy> dummyResource = new Resource<Dummy>(save);
return new
ResponseEntity<Resource<Dummy>>processor.process(dummyResource),
HttpStatus.CREATED);
}
@RequestMapping(value="/dummies/{id}", method = GET,
produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Resource<Dummy>> getDummy(@PathVariable("id")
Dummy dummy){
Resource<Dummy> dummyResource = new Resource<Dummy>(save);
return new ResponseEntity<Resource<Dummy>>
(processor.process(dummyResource), HttpStatus.OK);
}
}
保存虚拟对象时,会生成并分配UUID 持久化之前的id字段。 在我的资源处理器中,链接的设置如下:
@Component
public class DummyResourceProcessor implements
ResourceProcessor<Resource<Dummy>> {
@Override
public Resource<Dummy> process(Resource<Dummy> resource) {
Dummy dummy = resource.getContent();
resource.add(linkTo(methodOn(DummyController.class).
getDummy(dummy)).withSelfRel());
return resource;
}
}
从我的测试代码中我使用这样的方式进行POST:
result =
mockMvc.perform(
post("/dummies").content("{\"name\":\"TestDummy\"}")
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andDo(print())
.andExpect(status().isCreated()).andReturn();
我得到这样的东西:
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.util.UUID] to required type [java.lang.String] for property 'id': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:287)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:461)
... 72 more
{"cause":null,"message":"No converter found capable of converting from
type @org.springframework.web.bind.annotation.PathVariable
com.sudo.Dummy to type java.lang.String"}
这是使用DummyToStringConvertor修复的,基本上如下所示:
public class DummyToStringConverter implements Converter<Dummy, String> {
@Override
public String convert(Dummy dummy) {
return dummy.getId().toString();
}
}
然后我这样做GET:
String dummyLocation = result.getResponse().getHeader("Location");
result =
mockMvc.perform(get(dummyLocation)).andExpect(status().
isOk())..andExpect(jsonPath("$.name").value("TestDummy"))
.andDo(print()).andReturn();
我回来了:
Failed to convert value of type 'java.lang.String' to required type
'com.sudo.Dummy'; nested exception is java.lang.IllegalStateException
:Cannot convert value of type [java.lang.String] to required type
[com.sudo.Dummy]: no matching editors or conversion strategy found
这是使用自定义编辑器类修复的,以便将String转换回Dummy对象:
public class DummyEditor extends PropertyEditorSupport {
private final DummyRepository dummyRepository;
public DummyEditor(DummyRepository dummyRepository) {
this.dummyRepository = dummyRepository;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
Dummy dummy = dummyRepository.findOne(UUID.fromString(text));
setValue(dummy);
}
}
在控制器中我使用@Initbinder添加了它。它停了下来 侵犯。
我的工作理论是在虚拟内部生成链接 资源处理器,在调用方法期间(虽然没有执行, 我相信,@ PathVariable注释需要一个&#34; id&#34;但它得到了一个假人 对象和它因为无法将其转换为String而中断 (URI模板)。这是正确的吗 ?如果没有,为什么Dummy对象不存在 在链接生成期间自动解决?是因为UUID 场?当我将Dummy对象的id保存为String并更改时 从UUID到String的存储库签名,然后一切都按预期工作。是 有没有办法绕过这个问题,而无需使用自定义 转换器和编辑?
答案 0 :(得分:0)
这两个例外与链接生成代码无关。试图分别解析请求主体和参数时引发了两个异常。
您遇到了第一个异常,因为请求正文无法将您的输入Json转换为Dummy
对象。因为id的UUID
类型。实现转换器时问题得到解决。
在GET调用期间引发了第二个异常,因为Spring试图将{id}
占位符String
值转换为Dummy
对象,并且它不知道如何执行此操作。如果您更改GET
方法的方法签名,如下所示,那么您应该很好。您不需要PropertyEditorSupport
。
public ResponseEntity<Resource<Dummy>> getDummy(@PathVariable("id")
String dummyId){
}
希望这有帮助。