Я изо всех сил пытался найти какие-либо примеры того, как можно переопределить стандартное поведение Spring Boot Data Rest JpaRepository, чтобы получить что-то отличное от ответа HAL.Я обнаружил, что и Siren, и Json-LD могут соответствовать требованиям, но не примеры того, как заставить его работать с пружиной.Я использую Spring 5, Spring Data Rest 2.0.4.RELEASE.Пожалуйста, обратите внимание, я не собираюсь делать это для настраиваемого контроллера остатка, но для репозитория по умолчанию, предоставляемого расширением JpaRepository.Это моя первая публикация, поэтому я прошу прощения за любые правила, которые я мог случайно нарушить.
Обновление: Мне удалось найти библиотеку Hydra-Spring с SirenMessageConverter, следуя примеру на репо, я смог сделать следующее:
@Configuration
@EnablePluginRegistries(RelProvider.class)
public class Config implements WebMvcConfigurer {
private static final boolean EVO_PRESENT =
ClassUtils.isPresent("org.atteo.evo.inflector.English", null);
@Autowired
private PluginRegistry<RelProvider, Class<?>> relProviderRegistry;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(sirenMessageConverter());
converters.add(hydraMessageConverter());
converters.add(halConverter());
converters.add(uberConverter());
converters.add(xhtmlMessageConverter());
converters.add(jsonConverter());
}
@Bean
public RepositoryRestConfigurerAdapter repositoryRestConfigurer() {
return new RepositoryRestConfigurerAdapter() {
@Override
public void configureHttpMessageConverters(
List<HttpMessageConverter<?>> messageConverters) {
messageConverters.add(0, sirenMessageConverter());
}
};
}
@Bean
public HttpMessageConverter<?> uberConverter() {
UberJackson2HttpMessageConverter converter = new UberJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(HypermediaTypes.UBER_JSON));
return converter;
}
private HttpMessageConverter<?> xhtmlMessageConverter() {
XhtmlResourceMessageConverter xhtmlResourceMessageConverter = new XhtmlResourceMessageConverter();
xhtmlResourceMessageConverter.setStylesheets(
Arrays.asList(
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"
));
xhtmlResourceMessageConverter.setDocumentationProvider(new JsonLdDocumentationProvider());
return xhtmlResourceMessageConverter;
}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
final ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setWarnLogCategory(resolver.getClass()
.getName());
exceptionResolvers.add(resolver);
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(HypermediaTypes.SIREN_JSON);
}
@Bean
public HydraMessageConverter hydraMessageConverter() {
return new HydraMessageConverter();
}
@Bean
public SirenMessageConverter sirenMessageConverter() {
SirenMessageConverter sirenMessageConverter = new SirenMessageConverter();
sirenMessageConverter.setRelProvider(new DelegatingRelProvider(relProviderRegistry));
sirenMessageConverter.setDocumentationProvider(new JsonLdDocumentationProvider());
sirenMessageConverter.setSupportedMediaTypes(Collections.singletonList(HypermediaTypes.SIREN_JSON));
return sirenMessageConverter;
}
@Bean
public ObjectMapper jacksonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
return objectMapper;
}
@Bean
public MappingJackson2HttpMessageConverter jsonConverter() {
MappingJackson2HttpMessageConverter jacksonConverter = new
MappingJackson2HttpMessageConverter();
jacksonConverter.setSupportedMediaTypes(Arrays.asList(MediaType.valueOf("application/json")));
jacksonConverter.setObjectMapper(jacksonObjectMapper());
return jacksonConverter;
}
@Bean
public CurieProvider curieProvider() {
return new DefaultCurieProvider("ex", new UriTemplate("http://localhost:8080/webapp/hypermedia-api/rels/{rels}"));
}
@Bean
public MappingJackson2HttpMessageConverter halConverter() {
CurieProvider curieProvider = curieProvider();
RelProvider relProvider = new DelegatingRelProvider(relProviderRegistry);
ObjectMapper halObjectMapper = new ObjectMapper();
halObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
halObjectMapper.registerModule(new Jackson2HalModule());
halObjectMapper.setHandlerInstantiator(new
Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider, null));
MappingJackson2HttpMessageConverter halConverter = new
MappingJackson2HttpMessageConverter();
halConverter.setSupportedMediaTypes(Arrays.asList(MediaTypes.HAL_JSON));
halConverter.setObjectMapper(halObjectMapper);
return halConverter;
}
@Bean
RelProvider defaultRelProvider() {
return EVO_PRESENT ? new EvoInflectorRelProvider() : new DefaultRelProvider();
}
@Bean
RelProvider annotationRelProvider() {
return new AnnotationRelProvider();
}
}
Это мой текущий Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="`http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd`">
<modelVersion>`4.0.0`</modelVersion>
<groupId>com.knowledgebase.DataRest</groupId>
<artifactId>DataRest</artifactId>
<version>2.1.0.M2</version>
<packaging>jar</packaging>
<name>DataRest</name>
<description>Demo project for Spring Boot DataRest</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath /><!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<dependency>
<groupId>de.escalon.hypermedia</groupId>
<artifactId>hydra-spring</artifactId>
<version>0.4.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
Однако это все равно не дает результатов, которые я ищу.Я знаю, что некоторые из изменений, которые я ввел в классе config, имеют значение, так как вывод теперь выглядит следующим образом:
{
"_embedded": {
"ex:contacts": []
},
"_links": {
"self": {
"href": "http://localhost:8080/contacts{?page,size,sort}",
"templated": true
},
"profile": {
"href": "http://localhost:8080/profile/contacts"
},
"search": {
"href": "http://localhost:8080/contacts/search"
},
"curies": [
{
"href": "http://localhost:8080/webapp/hypermedia-api/rels/{rels}",
"name": "ex",
"templated": true
}
]
},
"page": {
"size": 20,
"totalElements": 0,
"totalPages": 0,
"number": 0
}
}
Как вы можете видеть, поставщик Curries - единственное, что действительно работает.По какой-то причине при загрузке данных весенней загрузки JpaRepository не меняет тип приложения по умолчанию на SIREN_JSON, несмотря на:
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(HypermediaTypes.SIREN_JSON);
}