Разрешите представить свой код, а затем я задам вопрос. Это всего лишь пример. Я бы хотел узнать что-то новое, если это возможно.
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";
}
}
Есть ли лучший способ сделать что-то подобное более "профессиональным" способом?
Это просто пример. Конечно, я мог бы использовать геттеры и сеттеры, но для этого «настоящего» приложения необходимо использовать super и конструктор BaseClass, и я просто пытаюсь найти лучший способ справиться с этим.




Если вы состоите в браке с текущей структурой наследования, вы можете использовать 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
}
}
Проверено. Это работает, но это очень сложный способ сделать то, о чем я просил. Конечно, спасибо.
Хотя это не совсем ясно, я предполагаю, что 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 обычно лучше всего просто.
Должен ли ваш базовый класс обязательно иметь конструктор? Почему бы вам не использовать только геттеры и сеттеры?