2017-03-14 33 views
6

我有一個端點:春數據JPA方法+ REST:枚舉到整數轉換

/api/offers/search/findByType?type=X 

其中X應該是一個Integer值(我OfferType實例的序數值),而春季認爲XString,並將應用其StringToEnumConverterFactoryStringToEnum轉換器。

public interface OfferRepository extends PagingAndSortingRepository<Offer, Long> { 

    List<Offer> findByType(@Param("type") OfferType type); 

} 

所以我寫了一個自定義Converter<Integer, OfferType>它只是通過給定的序數得到一個實例:

public class IntegerToOfferTypeConverter implements Converter<Integer, OfferType> { 

    @Override 
    public OfferType convert(Integer source) { 
     return OfferType.class.getEnumConstants()[source]; 
    } 

} 

然後我用Configuration註冊得當:

@EnableWebMvc 
@Configuration 
@RequiredArgsConstructor 
public class GlobalMVCConfiguration extends WebMvcConfigurerAdapter { 

    @Override 
    public void addFormatters(FormatterRegistry registry) { 
     registry.addConverter(new IntegerToOfferTypeConverter()); 
    } 

} 

而且我預計到findByType?type=X的所有請求都會通過我的轉換器,但他們不會。

有沒有辦法說所有定義爲請求參數的枚舉都必須作爲Integer提供?此外,是否有任何方法可以在全球範圍內進行說明,而不僅僅是針對特定的枚舉?

編輯:我在我的classpath中找到了IntegerToEnumConverterFactory,這是我所需要的。並且它是用DefaultConversionService註冊的,這是用於轉換的默認服務。如何應用?

編輯2:這是一件小事,我想知道是否有一個屬性來打開枚舉轉換。

EDIT3:我試着寫一個Converter<String, OfferType>我從TypeDescriptor.forObject(value)String後,它並沒有幫助。

EDIT4:我的問題是,我已經把定製轉換器註冊到MVC配置(WebMvcConfigurerAdapteraddFormatters)而不是REST庫酮(RepositoryRestConfigurerAdapterconfigureConversionService)。

+0

這個問題與彈簧數據或JPA有什麼關係? –

+0

因爲他使用Spring Data JPA? Andrew,您正在查詢的實體是否在相應的字段上有@Enumerated註釋? 因爲這裏所討論:http://stackoverflow.com/questions/17242408/spring-query-annotation-with-enum-parameter – PaulNUK

+0

@PaulNUK,不,不 – Andrew

回答

4

Spring將查詢參數解析爲字符串。我相信它總是使用Converter<String, ?>轉換器將查詢參數轉換爲您的存儲庫方法參數。它使用增強型轉換器服務,因爲它註冊了its own converters,如Converter<Entity, Resource>

因此,您必須創建一個Converter<String, OfferType>,例如,:

@Component 
public class StringToOfferTypeConverter implements Converter<String, OfferType> { 

    @Override 
    public OfferType convert(String source) { 
     return OfferType.class.getEnumConstants()[Integer.valueOf(source)]; 
    } 
} 

,然後配置該轉換器由Spring數據REST中使用,一類擴展RepositoryRestConfigurerAdapter

@Configuration 
public class ConverterConfiguration extends RepositoryRestConfigurerAdapter { 

    @Autowired 
    StringToOfferTypeConverter converter; 

    @Override 
    public void configureConversionService(ConfigurableConversionService conversionService) { 
     conversionService.addConverter(converter); 
     super.configureConversionService(conversionService); 
    } 
} 

我試圖把它添加到the basic tutorial,添加了一個簡單枚舉的人類:

public enum OfferType { 
    ONE, TWO; 
} 


@Entity 
public class Person { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    private OfferType type; 


    public OfferType getType() { 
     return type; 
    } 

    public void setType(OfferType type) { 
     this.type = type; 
    } 
} 

當我打電話:

http://localhost:8080/people/search/findByType?type=1

我得到的結果是沒有錯誤:

{ 
    "_embedded" : { 
    "people" : [ ] 
    }, 
    "_links" : { 
    "self" : { 
     "href" : "http://localhost:8080/people/search/findByType?type=1" 
    } 
    } 
} 

要實現一個全球性的枚舉轉換器,你必須創建一個工廠,並使用該方法在配置上進行註冊:conversionService.addConverterFactory() 。下面的代碼是一個修改的example from the documentation

public class StringToEnumFactory implements ConverterFactory<String, Enum> { 

    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { 
     return new StringToEnum(targetType); 
    } 

    private final class StringToEnum<T extends Enum> implements Converter<String, T> { 

     private Class<T> enumType; 

     public StringToEnum(Class<T> enumType) { 
      this.enumType = enumType; 
     } 

     public T convert(String source) { 
      Integer index = Integer.valueOf(source); 
      return enumType.getEnumConstants()[index]; 
     } 
    } 
}