Лучший способ для (без) конструктора аргументов - ResponseBody - Spring

Разрешите представить свой код, а затем я задам вопрос. Это всего лишь пример. Я бы хотел узнать что-то новое, если это возможно.

BaseClass.java

public class BaseClass {

  private String baseName;

  BaseClass(String baseName){
    this.baseName = baseName;
  }
  //getters and setters
}

MyClass.java

public class MyClass extends BaseClass {

  private boolean isTest;
  private String name;

  MyClass(){
  }

  MyClass(String baseName){
    super(baseName);
    this.isTest = true;
  }
  //getters and setters
}

MyClassController.java

@Controller
public class MyClassController {

  @GetMapping(value = "/")
  @ResponseBody
  public String myClassController(@RequestBody MyClass myClass) {


    return "index";
  }
}

Запрос JSON:

{
  "name": "Name for BaseClass"
}

Итак, я отправляю название, например: Имя для BaseClass. Я хочу установить это имя для переменной BaseName в BaseClass через конструктор. @RequestBody не нуждается в конструкторе атрибутов, поэтому я не могу использовать этот второй конструктор с аргументами. Я могу справиться с этим, например для использования дополнительного метода:

Дополнительный метод в MyClass.java

  public MyClass setValues(String baseName){
    super(baseName);
    this.isTest = true;
    return this;
  }

Новый MyController.java

@Controller
public class MyClassController {

  @GetMapping(value = "/")
  @ResponseBody
  public String myClassController(@RequestBody MyClass myClass) {

    myClass.setValues(myClass.getName());
    //more uses for myClass

    return "index";
  }
}

Есть ли лучший способ сделать что-то подобное более "профессиональным" способом?

Должен ли ваш базовый класс обязательно иметь конструктор? Почему бы вам не использовать только геттеры и сеттеры?

raiyan 30.07.2018 20:55

Это просто пример. Конечно, я мог бы использовать геттеры и сеттеры, но для этого «настоящего» приложения необходимо использовать super и конструктор BaseClass, и я просто пытаюсь найти лучший способ справиться с этим.

Warmix 30.07.2018 21:05
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
226
2

Ответы 2

Если вы состоите в браке с текущей структурой наследования, вы можете использовать HttpMessageConverter для настройки способа десериализации HTTP-запросов Spring.

public class MyClassConverter extends AbstractHttpMessageConverter<MyClass> {

  public MyClassConverter() {
      super(new MediaType("text", "myClass"));
  }

  @Override
  protected boolean supports(Class<?> clazz) {
      return MyClass.class.isAssignableFrom(clazz);
  }

  @Override
  protected MyClass readInternal(Class<? extends MyClass> clazz, HttpInputMessage inputMessage)
          throws IOException, HttpMessageNotReadableException {

      // Deserialize JSON request

      MyClass inputObject = new MyClass(name);
      return inputObject;
  }

  @Override
  protected void writeInternal(MyClass myClass, HttpOutputMessage outputMessage) {

      // Serialize MyClass object

  }
}

Подробный пример

Проверено. Это работает, но это очень сложный способ сделать то, о чем я просил. Конечно, спасибо.

Warmix 31.07.2018 22:40

Хотя это не совсем ясно, я предполагаю, что name и baseName должны иметь одно и то же значение. В этом случае может иметь смысл использовать BaseClass как абстрактный класс или интерфейс.

абстрактный класс:

public class MyClass extends BaseClass {

    private String name;

    // constructors

    @Override
    String getName() {
        return name;
    }

    // setters
}

public abstract class BaseClass {
    abstract String getName();
}

интерфейс:

public class MyClass implements DtoWithName {

    private String name;

    // constructors

    @Override
    String getName() {
        return name;
    }

    // setters
}

public interface DtoWithName {
    String getName();
}

Кроме того, я не могу много рассказать о вашем сценарии использования из данного примера, но вы должны прочитать Состав над наследованием, чтобы убедиться, что вы все делаете правильно. В частности, с DTO обычно лучше всего просто.

Другие вопросы по теме