2015-10-22 4 views
3

Есть ли способ использовать интерфейс @Projection как представление по умолчанию для ресурса в SDR? Либо через репозитории SDR, либо через пользовательский контроллер?Использование Spring Data Rest @Projection как представление ресурса в пользовательском контроллере

Это было возможно в пользовательском контроллере, чтобы сделать это, введя ProjectionFactory и используя метод createProjection, но это было нарушено недавним обновлением Spring Data Rest.

Я хотел бы обеспечить конкретный вид объекта, и проекции SDR выглядят как идеальный метод для этого, особенно в контексте API HAL, в отличие от написания жестких классов DTO для пользовательского контроллера и сопоставление между ними и т. д. Выражения выдержки не являются тем, чем я занимаюсь, поскольку они применяются только при рассмотрении связанного ресурса.

ответ

8

Чтобы ответить на мой собственный вопрос, есть теперь несколько easyish способов сделать это.

Вы можете сделать SDR репозиториев искатели вернуть проекции по умолчанию:

public interface PersonRepository extends PagingAndSortingRepository<Person,Long> { 

    Set<PersonProjection> findByLastName(String lastName); 

} 

Вы можете также выборочно отменить ответ, что SDR бы обрабатываемые для вас по умолчанию путем создания пользовательского Spring MVC контроллер с @BasePathAwareController. Вам нужно будет ввести ProjectionFactory и, возможно, PagedResourcesAssembler, если вы планируете предоставлять постраничный ответ.

@BasePathAwareController 
public class CustomPersonController { 

@Autowired 
private ProjectionFactory factory; 

@Autowired 
private PersonRepository personRepository; 

@Autowired 
private PagedResourcesAssembler<PersonProjection> assembler; 

@RequestMapping(value="/persons", method = RequestMethod.GET, produces = "application/hal+json") 
public ResponseEntity<?> getPeople(Pageable pageable) { 
    Page<Person> people = personRepository.findAll(pageable); 
    Page<PersonProjection> projected = people.map(l -> factory.createProjection(PersonProjection.class, l)); 
    PagedResources<Resource<PersonProjection>> resources = assembler.toResource(projected); 
    return ResponseEntity.ok(resources); 
} 
+1

В дополнение к @adam respone, необходимо добавить '@ Bean' в некоторый файл' @ Configuration', например. '@Configuration класс SomeConfig { @Bean общественного SpelAwareProxyProjectionFactory projectionFactory() { вернуть новый SpelAwareProxyProjectionFactory(); } } ' [источник] (http://stackoverflow.com/a/29386907/3245552) – Tirias

2

Невозможно из коробки. Выражения выдержки всегда используются, если ресурс встроен. И на одном ресурсе вы можете предоставить желаемую проекцию в качестве параметра запроса.

Что вы можете сделать, это использовать Jackson Mixins для изменения представления json.

Вы можете найти несколько хороших примеров здесь: https://github.com/olivergierke/spring-restbucks/blob/master/src/main/java/org/springsource/restbucks/JacksonCustomizations.java

+0

Спасибо. Ранее (до SDR 2.4.0), можно было просто ввести экземпляр «SpelAwareProxyProjectionFactory» в ваш класс контроллера, а затем в пользовательские контроллеры вызвать «createProjection» на объект домена, который вы хотите спроектировать, а затем вернуть проекцию в ответ, но это, к сожалению, было нарушено одним или несколькими изменениями на стороне SDR. маршрут Джексона Миксинса гораздо более активен и clunkier. –

+1

Ранее был аналогичный вопрос, и Оливер Гирке прямо подтолкнул его к некоторым приятным аргументам, почему не рекомендуется использовать прогнозы для отдельных ресурсов - см. Http://stackoverflow.com/questions/30220333/why-is-an-excerpt -projection-not-apply-automatic-for-a-spring-data-rest-it –

+0

Да, я видел это, хотя это было в основном связано с выдержками и использованием стандартных хранилищ, экспортированных SDR. Хотя, Оливер также рассказал, как сделать то, что я делаю (и что я делаю) здесь: https://stackoverflow.com/questions/29376090/how-to-apply-spring-data-projections-in-a- spring-mvc-контроллеры/29386907 # 29386907 и здесь: https://spring.io/blog/2015/03/26/what-s-new-in-spring-data-fowler, но эти примеры кода больше не работают в текущей версии SDR, бросая исключение Джексона. –

1

Я хотел бы предложить еще одно решение.

Я использовал пользовательский контроллер как @adam, до тех пор, пока мне не понадобилось PATCH ресурса и получить новое представление назад. Невозможно переопределить метод репозитория save для использования проекции по умолчанию. Внедрение пользовательских контроллеров все время привносит в проект некоторые шаблоны.

Поскольку я уже использовал ResourceProcessor, я решил применить проекцию по умолчанию прямо внутри этих процессоров.

@Component 
public class ProductResourceProcessor implements ResourceProcessor<Resource<Product>> { 

    @Autowired 
    private ProjectionFactory projectionFactory; 

    @Override 
    @SuppressWarnings("unchecked") 
    public Resource<Product> process(Resource<Product> resource) { 
     Product content = resource.getContent(); 
     ProductInline projection = projectionFactory.createProjection(ProductInline.class, content); 
     Resource<ProductInline> result = new Resource<>(projection); 
     //copying and adding links 
     return (Resource) result; 
    } 
} 

Процессор обрабатывает содержимое ресурса обработки. Способ Thsi применяется, независимо от того, какой обработчик возвратил ресурс в качестве ответа (GET, POST, PATCH ничего).

Недостатком этого подхода является то, что spring-data-rest не требует, чтобы тип содержимого был таким же после обработки. Это может измениться в будущем в будущих выпусках.

 Смежные вопросы

  • Нет связанных вопросов^_^