Java 自定义WebArgumentResolver,如@PathVariable

Java 自定义WebArgumentResolver,如@PathVariable,java,spring,spring-mvc,spring-annotations,Java,Spring,Spring Mvc,Spring Annotations,我想为id->entity使用自定义WebArgumentResolver。如果我使用请求参数,就很容易了:使用参数键来确定实体类型并相应地查找 但我希望它像@PathVariable注释一样 例如 会触发这种方法吗 @RequestMapping(value = "/something/{enquiry}/{item}") public String method(@Coerce Enquiry enquiry, @Coerce Item item) @强制注释会告诉WebArgument

我想为id->entity使用自定义WebArgumentResolver。如果我使用请求参数,就很容易了:使用参数键来确定实体类型并相应地查找

但我希望它像@PathVariable注释一样

例如

会触发这种方法吗

@RequestMapping(value = "/something/{enquiry}/{item}")
public String method(@Coerce Enquiry enquiry, @Coerce Item item) 
@强制注释会告诉WebArgumentResolver根据特定服务的类型使用该服务

问题是确定哪个uri部分属于实体

有人能解释一下PathVariable注释是如何做到的吗。是否可以用我的自定义注释来模拟它

谢谢。

您可以使用它让spring知道如何将给定字符串强制为自定义类型

您可能需要以下内容:

@RequestMapping(value = "/something/{enquiry}")
public String method(@PathVariable Enquiry enquiry) {...}


@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(Enquiry.class, new PropertyEditorSupport() {
        @Override
        public String getAsText() {
            return ((Enquiry) this.getValue()).toString();
        }

        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            setValue(new Enquiry(text));
        }
    });
}

对于不需要为每个实体指定一个PropertyEditor的通用方法,可以使用ConditionalGenericConverter:

public final class GenericIdToEntityConverter implements ConditionalGenericConverter {
    private static final Logger log = LoggerFactory.getLogger(GenericIdToEntityConverter.class);

    private final ConversionService conversionService;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    public GenericIdToEntityConverter(ConversionService conversionService) {
        this.conversionService = conversionService;
    }

    public Set<ConvertiblePair> getConvertibleTypes() {
        return ImmutableSet.of(new ConvertiblePair(Number.class, AbstractEntity.class),
                new ConvertiblePair(CharSequence.class, AbstractEntity.class));

    }

    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        return AbstractEntity.class.isAssignableFrom(targetType.getType())
        && this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(Long.class));
    }

    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        if (source == null) {
            return null;
        }

        Long id = (Long) this.conversionService.convert(source, sourceType, TypeDescriptor.valueOf(Long.class));

        Object entity = entityManager.find(targetType.getType(), id);
        if (entity == null) {
            log.info("Did not find an entity with id {} of type {}", id,  targetType.getType());
            return null;
        }

        return entity;
    }

}
公共最终类GenericdToEntityConverter实现ConditionalGenericConverter{
私有静态最终记录器log=LoggerFactory.getLogger(GenericIdToEntityConverter.class);
私有最终转换服务转换服务;
@持久上下文
私人实体管理者实体管理者;
@自动连线
公共GenericdToEntityConverter(转换服务转换服务){
this.conversionService=conversionService;
}
公共集getConvertibleTypes(){
返回ImmutableSet.of(新的ConvertiblePair(Number.class,AbstractEntity.class),
新的ConvertiblePair(CharSequence.class,AbstractEntity.class));
}
公共布尔匹配(TypeDescriptor源类型、TypeDescriptor目标类型){
返回AbstractEntity.class.isAssignableFrom(targetType.getType())
&&this.conversionService.canConvert(sourceType,TypeDescriptor.valueOf(Long.class));
}
公共对象转换(对象源、类型描述符源类型、类型描述符目标类型){
if(source==null){
返回null;
}
Long id=(Long)this.conversionService.convert(source、sourceType、TypeDescriptor.valueOf(Long.class));
Object entity=entityManager.find(targetType.getType(),id);
if(实体==null){
log.info(“未找到id为{}类型{}”、id为targetType.getType()的实体);
返回null;
}
返回实体;
}
}

真不敢相信我没看到。我有一个全局属性编辑器,使用PropertyEditorRegistrar而不是per-controller@InitBinder,但效果很好,类也更少。美好的