У меня есть @RestController в приложении Spring Boot.
@PutMapping("{table}/{key}")
public void update(@PathVariable("tables") String tableName,
@PathVariable("key") String key,
@RequestBody Entity entity) {
...
}
Более удобно преобразовать это отображение в:
@PutMapping("{table}/{key}")
public void update(@RequestBody Entity entity) {
...
}
и ожидать, что информация из @PathVariable будет внутри @RequestBody.
Причина: У меня есть другой @RestController, в котором я получаю AnotherEntity anotherEntity. Этот стиль архитектуры позволяет мне создавать общая иерархия в сервисных слоях.
Вопрос 1: Разве это не плохой паттерн? Это достаточно хорошо, как идеальный сервис ОТДЫХ, или мне следует избегать его? вопрос 2: в этом случае я не использую @PathVariable, и мне просто нужно указать какое-то слово/другое слово как @PutMappingдорожка. Есть ли способ указать что-то вроде любой/любой без интеллектуальной проверки, которую я должен использовать?
Обновление: пример архитектуры
public abstract class Validator<T> {
public abstract void validate(T t);
}
public class FirstEntityValidator extends Validator<FirstEntity> {
public void validate(FirstEntity entity){
...
}
}
public class SecondEntityValidator extends Validator<SecondEntity> {
public void validate(SecondEntity entity){
...
}
}
public abstract class EntityService<T> {
private Validator<T> validator;
public EntityService(Validator<T> validator){
this.validator = validator;
}
}
public class FirstEntityService extends EntityService<FirstEntity> {
public FirstEntityService(FirstEntityValidator<FirstEntity> validator){
super(validator);
}
}
public class SecondEntityService extends EntityService<SecondEntity> {
public SecondEntityService(SecondEntityValidator<SecondEntity> validator){
super(validator);
}
}




Я бы избегал чего-то подобного. Вы должны разделить свои контроллеры REST так же, как вы разделяете свои службы. В случае, если вам нужно что-то изменить только для одной сущности, вам все равно придется рефакторить все или создать какой-то уродливый код.
Я думаю, что вы пытаетесь представить свои репозитории как веб-сервис REST. Spring может справиться с этим за вас. Проверь это: https://docs.spring.io/spring-data/rest/docs/current/reference/html/
Используйте интерфейсы. Не используйте абстрактные классы. В этом нет необходимости, и это может быть очень сложно реализовать в больших проектах.
Это было бы лучше:
public interface class Validator<T> {
void validate(T t);
}
public class FirstEntityValidator implements Validator<FirstEntity> {
public void validate(FirstEntity entity){
....
}
}
public class SecondEntityValidator implements Validator<SecondEntity> {
public void validate(SecondEntity entity){
....
}
}
public interface EntityService{
//your methods....
}
public class FirstEntityService implements EntityService{
private FirstEntityValidator validator;
public FirstEntityService(FirstEntityValidator validator){
this.validator = validator;
}
}
Не используйте абстрактные службы. Используйте композицию. Это очень поможет вам в будущем. Прочтите это: en.wikipedia.org/wiki/Composition_over_inheritance
а как насчет принципа подстановки Лисков?
Это то, чему я научился в своем последнем большом проекте. Наследование больше не должно использоваться. Вы можете сделать все в композиции, что сделает ваш проект более удобным в сопровождении
Принцип единой ответственности javacodegeeks.com/2014/02/… Я думаю, это то, чему разработчики научились за последние 10 лет. Наследование может быть полезным. Но почти во всех случаях композиция — лучший выбор.
Я просто хочу указать, подходит ли это для моего примера. Я добавил пример в вопросе: это плохая архитектура? Я прячу все за общим интерфейсом и избегаю копипаста, но я неопытен и очень этим интересуюсь. Не могли бы вы проверить, пожалуйста?
У меня последний вопрос - в своем ответе вы указали валидатор как тип FirstEntityValidator внутри сервиса. Почему вы не указали It как тип интерфейса Validator?
Вы можете сделать это, конечно. Я просто хотел показать вам, что вы используете конкретную реализацию в этом сервисе.
Есть еще одна проблема — информация из @RequestBody и @PathVariable может отличаться. Вы сказали о возможных изменениях, но если у меня есть 2 службы для 2 разных объектов (служба - это что-то абстрактное, это может быть распределенная служба, служба кэширования и т. д.), и у них один и тот же метод? Отличие только одно - тип параметра. С одной стороны у меня есть копипаста. С другой стороны, если я использую AbstractService с типом T, у меня могут возникнуть проблемы в будущем. Похоже, оба варианта не совсем хороши