从@PathVariable DomainObject转换为String?(使用ControllerLinkBuilder.methodOn)

Ben*_*n M 6 spring controller converter spring-mvc spring-hateoas

我试图ControllerLinkBuilder.methodOn()用非String类型调用Spring ,它总是失败.我不知道使用哪种Converter以及在何处注册.

这是我的控制器:

@RestController
@RequestMapping("/companies")
class CompanyController {

    @RequestMapping(value="/{c}", method=RequestMethod.GET)
    void getIt(@PathVariable Company c) {
        System.out.println(c);
        Link link = linkTo(methodOn(getClass()).getIt(c));
    }

}
Run Code Online (Sandbox Code Playgroud)

System.out.println(c)效果很好.我的Company域对象从数据库获取.(我正在使用DomainClassConverter)

但另一种方式不起作用: ConverterNotFoundException: No converter found capable of converting from type @PathVariable Company to type String

我只需要一个Converter<Company, String>吗?我应该在哪里注册?我在addFormatters(FormatterRegistry registry)方法中尝试了一些东西WebMvcConfigurationSupport,但它确实显示了同样的错误.但毕竟我不确定我到底尝试了什么......

Fra*_*sso 5

我有同样的问题,这是一个错误.如果你不想在每个控制器上复制和粘贴,你可以尝试在你的WebMvcConfigurationSupport.这个对我有用.

@Override
public void addFormatters(final FormatterRegistry registry) {
    super.addFormatters(registry);

    try {
        Class<?> clazz = Class.forName("org.springframework.hateoas.mvc.AnnotatedParametersParameterAccessor$BoundMethodParameter");
        Field field = clazz.getDeclaredField("CONVERSION_SERVICE");
        field.setAccessible(true);
        DefaultFormattingConversionService service = (DefaultFormattingConversionService) field.get(null);
        for (Converter<?, ?> converter : beanFactory.getBeansOfType(Converter.class).values()) {
            service.addConverter(converter);
        }
    }
    catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*n M 0

找到了“解决方案”。它需要从 Spring 的类中进行大量复制和粘贴,但至少它有效!

基本上我必须复制org.springframework.hateoas.mvc.AnnotatedParametersParameterAccessor并更改两行:

class AnnotatedParametersParameterAccessor {
    ...
    static class BoundMethodParameter {
        // OLD: (with this one you can't call addConverter())
        // private static final ConversionService CONVERSION_SERVICE = new DefaultFormattingConversionService();
        // NEW:
        private static final FormattingConversionService CONVERSION_SERVICE = new DefaultFormattingConversionService();

        ...

        public BoundMethodParameter(MethodParameter parameter, Object value, AnnotationAttribute attribute) {
            ...
            // ADD:
            CONVERSION_SERVICE.addConverter(new MyNewConverter());
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

该类由ControllerLinkBuilderFactory. 所以我也必须复制并粘贴它。

这个被使用了ControllerLinkBuilder。也可以复制和粘贴。

Converter只是这样做myDomainObject.getId().toString()

public class MyNewConverter implements Converter<Company, String> {
    @Override
    public String convert(Company source) {
        return source.getId().toString();
    }   
}
Run Code Online (Sandbox Code Playgroud)

ControllerLinkBuilder现在您可以在控制器内使用复制和粘贴,它会按预期工作!