ΠΠ΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΠΌΠΎΠ΄ΡΠ»Ρ Π΄Π»Ρ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ Π² DTO. ΠΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΡ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ Π·Π° ΡΡΠ΅Ρ ΡΠ΅ΡΠ»Π΅ΠΊΡΠΈΠΈ. ΠΠ»Ρ Π½Π°ΡΠ°Π»Π° ΡΠ°Π±ΠΎΡΡ Ρ ΠΌΠΎΠ΄ΡΠ»Π΅ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π½Π°ΡΡΡΠΎΠΈΡΡ ΡΠΊΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ², Π΄Π»Ρ ΡΠ΅Π³ΠΎ Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ Π±ΠΈΠ½ ConversionConfiguration Π»ΡΠ±ΡΠΌ ΡΠ΄ΠΎΠ±Π½ΡΠΌ ΡΠΏΠΎΡΠΎΠ±ΠΎΠΌ. ΠΠ»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΡΠΊΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π½ΡΠΆΠ½ΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ EnableConversions Π°Π½Π½ΠΎΡΠ°ΡΠΈΡ Π² Π»ΡΠ±ΡΡ ΡΠΎΡΠΊΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ.
ΠΠ»Ρ ΡΠ΄ΠΎΠ±Π½ΠΎΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΏΠ°ΡΡΠ΅ΡΠ½Π° DTO. ΠΠΎΠ΄ΡΠ»Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π½Π΅ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΈΡΡΡ ΠΎΠ± ΡΡΡΠ½ΠΎΠΌ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ , ΠΈ Π΄Π΅Π»Π°Π΅Ρ ΡΡΠΎ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ.
ΠΠΎΠ³Π΄Π° Π΅ΡΡΡ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΡΠ»ΠΎΠΆΠ½ΡΠ΅ ΠΌΠΎΠ΄Π΅Π»ΠΈ, ΠΈ Π΅ΡΡΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠ΅ ΠΏΠΎΠ»Ρ ΡΡΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠΌΡ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ. ΠΠΎΠ³Π΄Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ DDD ΠΈ ΠΊΠ»Π°ΡΡ A ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ ΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠΌΡ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ ΠΊΠ°ΠΊ C ΠΈΠ»ΠΈ D Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°.
- ΠΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠΈ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ Π½Π° Π²ΡΡ
ΠΎΠ΄Π΅ ΠΈΠ· ΠΌΠ΅ΡΠΎΠ΄Π° ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅ΡΠ°, ΠΌΠΎΠΆΠ΅Ρ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΠΎΡΠΈΠ±ΠΊΠ° hibernate: "No Session".
ΠΠ»Ρ ΡΠ΅ΡΠ΅Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ eager Π·Π°Π³ΡΡΠ·ΠΊΡ ΠΏΠΎΠ»Π΅ΠΉ, ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ join Π·Π°Π³ΡΡΠ·ΠΊΡ ΠΏΠΎΠ»Π΅ΠΉ JPA. - Π Π΅ΠΊΡΡΡΠΈΠ²Π½ΠΎΠ΅ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊ DTO Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΡ
ΠΏΠΎΠ»Π΅ΠΉ.
ΠΠ»Ρ ΡΠ΅ΡΠ΅Π½ΠΈΡ Π½Π΅ Π½ΡΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΏΠΎΠ»Ρ ΠΈ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°ΡΡ ΠΈΡ ΠΏΠΎ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΡΡΠΈ.
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.asewhy.conversions.ConversionStore;
import io.github.asewhy.conversions.support.annotations.EnableConversions;
import io.github.asewhy.conversions.support.ConversionConfiguration;
import io.github.asewhy.conversions.support.naming.ConversionNamingStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConversions
public class ConversionConfig implements ConversionConfiguration {
@Autowired
protected ObjectMapper objectMapper;
@Autowired
protected ApplicationContext context;
@Autowired
protected ConversionSupportContext supportContext;
@Override
public ConversionStore conversionStore() {
var store = new ConversionStore(context);
store.from("com.example");
return store;
}
@Override
public ObjectMapper objectMapper() {
return objectMapper;
}
@Override
public Object context() {
return supportContext;
}
}
ΠΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π²ΡΡΠ΅ Π² ΠΌΠ΅ΡΠΎΠ΄Π΅ provideStore
Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ Π²Π΅ΡΠ½ΡΡΡ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΠΉ. Π Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ Ρ
ΡΠ°Π½ΡΡΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ
ΠΎ ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΡΠ΅ΠΌΡΡ
ΡΡΡΠ½ΠΎΡΡΡΡ
, ΠΈ ΠΌΠ°ΠΏΠΏΠΈΠ½Π³ΠΈ ΠΏΠΎΠ»Π΅ΠΉ ΠΊ Π½ΠΈΠΌ. ΠΠ°Π»Π΅Π΅ ΠΏΠΎΡΡΠ°Π²ΡΠΈΠΊΠΎΠΌ ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΠΉ Π²ΡΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ Π±ΡΠ΄ΡΡ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡΡΡ ΠΈΠ· ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° ΡΡΠΎΠ³ΠΎ
Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ°.
ΠΡΠ»ΠΈ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠ° ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½Π°Ρ ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ° ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΡ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ, ΡΠΎ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²ΠΈΡΡ Π΅Ρ Π² ΠΌΠ΅ΡΠΎΠ΄Π΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ namingPolicy
. ΠΡΠΈΠΌΠ΅Ρ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠΉ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅:
public class ConversionConfig implements ConversionConfiguration {
// ...
@Autowired
protected ConversionNamingStrategy conversionNamingStrategy;
@Override
public ConversionNamingStrategy namingStrategy() {
return conversionNamingStrategy;
}
// ...
}
ΠΡΠΈΠΌΠ΅Ρ ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠΈ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΠΈΠ΄Π΅ΡΡ Π½ΠΈΠΆΠ΅:
import io.github.asewhy.conversions.support.CaseUtil;
import io.github.asewhy.conversions.support.naming.ExtrudableNamingStrategy;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import paa.coder.noodleCriteriaBuilder.restFilter.payloads.RestFilter;
import paa.coder.noodleCriteriaBuilder.restFilter.payloads.RestOrder;
import paa.coder.noodleCriteriaBuilder.restFilter.payloads.RestPage;
import java.util.Set;
@Component
public class ConversionNamingStrategy extends ExtrudableNamingStrategy {
/**
* ΠΡΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ ΠΊΡΠΎΠΌΠ΅ ΡΡΠΈΡ
Π±ΡΠ΄ΡΡ ΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΡ ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ΅
*/
private final static Set<Class<?>> EXCLUDED = Set.of(
RestFilter.class,
RestPage.class,
RestOrder.class
);
@Override
protected boolean isExcluded(@NotNull String defaultName, @NotNull Class<?> rawReturnType) {
return EXCLUDED.contains(rawReturnType);
}
/**
* Π‘Π»Π΅Π΄ΡΡ ΡΡΠΎΠΉ ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ΅, ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅Ρ Π΄ΡΠΌΠ°Π΅Ρ ΡΡΠΎ Π²ΡΠ΅ ΠΏΠΎΠ»Ρ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ ΠΈΠΌΠ΅ΡΡ snakeCase Π² Π·Π°ΠΏΡΠΎΡΠ΅, ΠΈ ΠΎΡΠ²Π΅ΡΠ΅
*/
@Override
protected String convert(@NotNull String defaultName) {
return CaseUtil.toLowerSnakeCase(defaultName);
}
}
Π ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π½Π° ΡΠ°Π±ΠΎΡΠ° Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎ ExtrudableNamingStrategy
ΠΊΠ»Π°ΡΡΠΎΠΌ, Π½ΠΎ Π½ΠΈΠΊΡΠΎ Π½Π΅ Π·Π°ΠΏΡΠ΅ΡΠ°Π΅Ρ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΡΠ²ΠΎΡ Π»ΠΎΠ³ΠΈΠΊΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ConversionNamingStrategy
;
ΠΠΎΠ½Π²Π΅ΡΡΠ΅ΡΡ Π² ΠΌΠΎΠ΄ΡΠ»Π΅ Π΄Π΅Π»ΡΡΡΡ Π½Π° ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅ΡΡ ΠΎΡΠ²Π΅ΡΠ° ΠΈ ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅ΡΡ Π·Π°ΠΏΡΠΎΡΠ°.
ΠΠ»Ρ ΡΠΊΠ°Π·Π°Π½ΠΈΡ ΡΠΎΠ³ΠΎ ΡΡΠΎ ΠΊΠ»Π°ΡΡ ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠ΅Π»ΡΡ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ ΠΎΡΠ²Π΅ΡΠ° Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠΌΠ΅ΡΠΈΡΡ Π΅Π³ΠΎ ΠΊΠ°ΠΊ @ResponseDTO
, ΠΊΠ°ΠΊ Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.ConversionResponse;
import io.github.asewhy.conversions.support.annotations.ResponseDTO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@ToString
@ResponseDTO
public class SomeSourceObjectDTO extends ConversionResponse<SomeSourceObject> {
private Long id;
}
ΠΡΠ»ΠΈ Π΅ΡΡΡ ΠΊΠ°ΠΊΠΈΠ΅-ΡΠΎ ΠΏΠΎΠ»Ρ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅Ρ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΡΠ°Π·ΡΠ΅ΡΠΈΡΡ ΡΠ°ΠΌ, ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄ fillInternal ΠΊΡΠ΄Π° ΠΏΠ΅ΡΠ²ΡΠΌ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠΌ Π±ΡΠ΄Π΅Ρ ΠΏΠΎΠ΄Π°Π²Π°ΡΡΡΡ ΠΈΡΡ ΠΎΠ΄Π½Π°Ρ ΡΡΡΠ½ΠΎΡΡΡ. ΠΡΠΈΠΌΠ΅Ρ ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.ConversionResponse;
import io.github.asewhy.conversions.support.annotations.ResponseDTO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@ToString
@ResponseDTO
public class SomeSourceObjectDTO extends ConversionResponse<SomeSourceObject> {
private Long id;
private String someUnfilledField;
@Override
protected void fillInternal(SomeSourceObject from, Object context) {
this.someUnfilledField = from.someMethodWhoReturnsSomeUnfilledFieldValue();
}
}
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΏΠΎΠ»Π΅ someUnfilledField
Π±ΡΠ΄Π΅Ρ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΌΠ΅ΡΠΎΠ΄Π° someMethodWhoReturnsSomeUnfilledFieldValue
Ρ SomeSourceObject
.
ΠΠ°ΡΠΈΠ½Π°Ρ Ρ Π²Π΅ΡΡΠΈΠΈ 1.0.3 Π΅ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ A ΠΈ B ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²ΡΠ²Π°ΡΡΠΈΡ ΠΎΠ±ΡΠΈΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π² ΠΎΠ΄Π½Ρ ΡΡΡΠ½ΠΎΡΡΡ ΠΎΡΠ²Π΅ΡΠ°. ΠΡΠΈΠΌΠ΅Ρ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΠΈΠ΄Π΅ΡΡ Π½ΠΈΠΆΠ΅:
public interface ExampleTestBook {
String getName();
String getIsbin();
}
@Getter
@Setter
@ToString
@AllArgsConstructor
public class ExampleTestBookInterfaceA implements ExampleTestBook {
private String name;
private String isbin;
private String genre;
}
@Getter
@Setter
@ToString
@AllArgsConstructor
public class ExampleTestBookInterfaceB implements ExampleTestBook {
private String name;
private String isbin;
private Integer pageCount;
}
@Getter
@Setter
@ToString
@ResponseDTO
public class ExampleTestBookInterfaceResponse extends ConversionResponse<ExampleTestBook> {
private String name;
private String isbin;
}
ΠΡΠΈΠΌΠ΅Ρ Π²ΡΡΠ΅ ΡΠΊΠ°ΠΆΠ΅Ρ ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅ΡΡ ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ Π²ΡΠ΅ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ExampleTestBook
Π² ExampleTestBookInterfaceResponse
ΠΠ»Ρ ΡΠΊΠ°Π·Π°Π½ΠΈΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ ΠΈΡΡ
ΠΎΠ΄Π½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠ΅Π»ΡΡ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ° Π½ΡΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ΅ΡΠΈΡΡ Π΅Π³ΠΎ Π°Π½Π½ΠΎΡΠ°ΡΠΈΠ΅ΠΉ @ConversionMutator
, ΠΊΠ°ΠΊ Π² ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.ConversionMutator;
import io.github.asewhy.conversions.support.annotations.MutatorDTO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.Min;
@Setter
@Getter
@ToString
@MutatorDTO
public class SomeSourceObjectMutatorDTO extends ConversionMutator<SomeSourceObjectDTO> {
@Min(0)
private int someInt;
}
ΠΡΠ»ΠΈ Π΅ΡΡΡ ΠΊΠ°ΠΊΠΈΠ΅-ΡΠΎ ΠΏΠΎΠ»Ρ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅Ρ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΡΠ°Π·ΡΠ΅ΡΠΈΡΡ ΡΠ°ΠΌ, ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄ fillInternal ΠΊΡΠ΄Π° ΠΏΠ΅ΡΠ²ΡΠΌ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠΌ Π±ΡΠ΄Π΅Ρ ΠΏΠΎΠ΄Π°Π²Π°ΡΡΡΡ ΠΈΡΡ ΠΎΠ΄Π½Π°Ρ ΡΡΡΠ½ΠΎΡΡΡ. ΠΡΠΈΠΌΠ΅Ρ ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.ConversionMutator;
import io.github.asewhy.conversions.support.annotations.MutatorDTO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.Min;
@Setter
@Getter
@ToString
@MutatorDTO
public class SomeSourceObjectMutatorDTO extends ConversionMutator<SomeSourceObjectDTO> {
@Min(0)
private int someInt;
private long p;
@Override
protected void fillInternal(SomeSourceObjectDTO fill, Object context) {
if(context instanceof SomeService ss) {
p = ss.doSomeWhoReturnsP();
}
}
}
ΠΠ° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π²ΡΡΠ΅, Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΡΡΠ½ΠΎΡΡΠΈ ΠΏΠΎΠ»Π΅ p Π±ΡΠ΄Π΅Ρ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΎ ΠΈΠ· ΡΠ΅ΡΠ²ΠΈΡΠ° SomeService. ΠΡΠΈ ΡΡΠΎΠΌ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ SomeService Π½ΡΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π² ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΊΠ°ΠΊ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ.
ΠΡΠ»ΠΈ Π΅ΡΡΡ ΠΌΡΡΠΈΡΡΠ΅ΠΌΠ°Ρ ΡΡΡΠ½ΠΎΡΡΡ ΡΠ²Π»ΡΠ΅ΡΡΡ Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ, ΡΠΎ Π² Π½Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡΡ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠΎΠ»Ρ ΠΈΠ· ΡΠΎΠ΄ΠΈΡΠ΅Π»ΡΡΠΊΠΎΠΉ ΡΡΡΠ½ΠΎΡΡΠΈ. ΠΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΌΠ΅ΡΠΎΠ΄ fillParentInternal
ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΎΠ΄ΠΈΡΠ΅Π»ΡΡΠΊΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΡΠΈΠΌΠ΅Ρ ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.ConversionMutator;
import io.github.asewhy.conversions.support.annotations.MutatorDTO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.Min;
@Setter
@Getter
@ToString
@MutatorDTO
public class SomeParentSourceObjectMutatorDTO extends ConversionMutator<SomeSourceObjectDTO> {
private int id;
private SomeSourceObjectMutatorDTO children;
}
import io.github.asewhy.conversions.ConversionMutator;
import io.github.asewhy.conversions.support.annotations.MutatorDTO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.Min;
@Setter
@Getter
@ToString
@MutatorDTO
public class SomeSourceObjectMutatorDTO extends ConversionMutator<SomeSourceObjectDTO> {
@Min(0)
private int someInt;
private int parentId;
@Override
protected void fillParentInternal(SomeSourceObjectDTO fill, Object parent, Object context) {
if(parent instanceof SomeParentSourceObjectMutatorDTO p) {
this.parentId = p.getId();
}
}
}
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΏΠΎΠ»Π΅ parentId
Ρ ΠΌΡΡΠ°ΡΠΎΡΠ° SomeSourceObjectMutatorDTO
Π±ΡΠ΄Π΅Ρ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΡΠΎΠ΄ΠΈΡΠ΅Π»ΡΡΠΊΠΈΠΌ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠΌ, Π² ΡΠ»ΡΡΠ°Π΅
Π΅ΡΠ»ΠΈ ΡΡΡΠ½ΠΎΡΡΡ Π±ΡΠ΄Π΅Ρ Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ.
ΠΠΎΠΆΠ΅Ρ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ ΡΠΈΡΡΠ°ΡΠΈΡ ΠΊΠΎΠ³Π΄Π° ΠΌΡΡΠ°ΡΠΎΡ Π±ΡΠ΄Π΅Ρ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ, ΡΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΡΡΠΎΠΌΠ½ΡΠΉ ΡΠ΅ΡΠΎΠ»Π²Π΅Ρ ΡΠ°ΠΊΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ°. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ,
ΠΈΠΌΠ΅Π΅ΡΡΡ ΠΊΠ»Π°ΡΡ ExampleTestNonMutatorRequest
ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· ΠΏΠΎΠ»Π΅ΠΉ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ΄Π΅Ρ ΠΌΡΡΠ°ΡΠΎΡ ExampleTestMutatorRequest
, Π΄Π»Ρ ΠΏΡΠΈΠΌΠ΅ΡΠ° ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ
Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ ΠΏΠΎΠ»Π΅ request
. Π’ΠΎΠ³Π΄Π° ΡΠ΅ΡΠΎΠ»Π²Π΅Ρ Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ° ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠ°ΠΊΠΈΠΌ:
import com.fasterxml.jackson.databind.JsonNode;
import io.github.asewhy.conversions.ConversionProvider;
import org.springframework.stereotype.Component;
import java.lang.reflect.Type;
@Component
public class ExampleTestNonMutatorRequestResolver extends RequestResolver<ExampleTestNonMutatorRequest> {
@Override
protected ExampleTestNonMutatorRequest resolveInternalRequest(
@NotNull JsonNode node,
Class<? extends ExampleTestNonMutatorRequest> fromClass,
Type generics,
@NotNull ConversionProvider provider
) {
var config = provider.getConfig();
var objectMapper = config.getObjectMapper();
try {
var data = objectMapper.treeToValue(node, ExampleTestNonMutatorRequest.class);
provider.createMutator(data.getRequest(), node.get("request"));
return data;
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
@Override
protected boolean canProcess(Class<?> from, Type generics, ConversionProvider provider) {
return ExampleTestNonMutatorRequest.class.isAssignableFrom(from);
}
}
ΠΠ±ΡΠ°ΡΠΈΡΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΡΡΠΎ ΠΊΠ»Π°ΡΡ ExampleTestNonMutatorRequest
Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΌΡΡΠ°ΡΠΎΡΠΎΠΌ.
ΠΠ° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π²ΡΡΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ ΠΏΡΠΎΡΠ΅ΡΡ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠΈ ΠΌΡΡΠ°ΡΠΎΡΠ° Π·Π°ΠΏΡΠΎΡΠ°, ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΎΡΠ²Π΅ΡΠ°. ΠΠΎΡΠ»Π΅ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠΈ, Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π² ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅ΡΠ΅ ΠΏΡΠΎΡΡΠΎ ΡΠΊΠ°Π·Π°Π²
ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅Ρ ΠΊΠ°ΠΊ @ShiftController
ΠΈΠ»ΠΈ ΠΏΠΎΠΌΠ΅ΡΠΈΠ² ΠΌΠ΅ΡΠΎΠ΄ ΠΊΠ°ΠΊ @ConvertResponse
, Π½Π΅ Π±ΡΠ΄Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π΅ΡΠ»ΠΈ ΠΌΠ΅ΡΠΎΠ΄ ΡΠΆΠ΅ ΠΏΠΎΠΌΠ΅ΡΠ΅Π½, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ ΠΊΠ°ΠΊ @ResponseBody
.
ΠΡΠΈΠΌΠ΅Ρ ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅ΡΠ° ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.support.annotations.ShiftController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@ShiftController
@RequestMapping("/comments")
public class CommentController {
@GetMapping("/{id}")
public SomeSourceObjectMutatorDTO get(@PathVariable("id") I id) {
// ΠΠ΅ΡΠΎΠ΄ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ SomeSourceObject
return (SomeSourceObjectMutatorDTO) provideService().restFindById(id);
}
}
ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΊΠΎΠ½Π²Π΅ΡΡΠ΅ΡΠ° Π·Π°ΠΏΡΠΎΡΠ° ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.support.annotations.ConvertMutator;
import io.github.asewhy.conversions.support.annotations.ShiftController;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@ShiftController
@RequestMapping("/comments")
public class CommentController {
@PostMapping
public void editSomeEntity(@ConvertMutator @Valid SomeSourceObjectMutatorDTO payload) {
var foundEntity = null;// ΠΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ ΡΠ΅Π΄Π°ΠΊΡΠΈΡΡΠ΅ΠΌΠΎΠΉ ΡΡΡΠ½ΠΎΡΡΠΈ
// ΠΠ΅ΡΠΎΠ΄ fill ΠΏΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π±Π°Π·ΠΎΠ²ΡΠΌ ΠΊΠ»Π°ΡΡΠΎΠΌ ΠΌΡΡΠ°ΡΠΎΡΠ° ΠΈ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π·Π°ΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΏΠΎΠ»Ρ Ρ ΡΠ΅ΠΌΠΈ ΠΆΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΡΠΌΠΈ ΠΈ ΡΠΈΠΏΠΎΠΌ Π² ΡΠ΅Π»Π΅Π²ΠΎΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠ΅
// Π²Π°ΠΆΠ½ΠΎ ΡΡΠΎΠ±Ρ ΡΠ΅Π»Π΅Π²ΠΎΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Π±ΡΠ» ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ ΡΠΊΠ°Π·Π°Π½Π½ΡΠΌ Π² generic ΠΏΡΠΈ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠΈ ΠΌΡΡΠ°ΡΠΎΡΠ°
payload.fill(foundEntity);
}
}
Π£ Π²Π°Ρ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ Π²ΠΊΠ»ΡΡΠ°ΡΡ Π² ΡΠ΅Π±Ρ ΡΡΡΠ½ΠΎΡΡΠΈ Π΄Π»Ρ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ. ΠΠΎΠ΄ΡΠ»Ρ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΠΈΡ ΡΠ°ΡΠΏΠΎΠ·Π½Π°ΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ, ΠΏΠΎΡΡΠΎΠΌΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΡΠ΅ΡΠΎΠ»Π²Π΅ΡΡ Π΄Π»Ρ ΡΠ°ΠΊΠΈΡ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠ². ΠΡΠΈΠΌΠ΅Ρ ΡΠ΅ΡΠΎΠ»Π²Π΅ΡΠ° ΠΏΠΎΠΊΠ°Π·Π°Π½ Π½ΠΈΠΆΠ΅.
import io.github.asewhy.conversions.ConversionProvider;
import io.github.asewhy.conversions.ResponseResolver;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import paa.coder.noodleCriteriaBuilder.restFilter.payloads.RestPage;
import java.lang.reflect.Type;
@Component
public class RestPageResponseResolver extends ResponseResolver<RestPage<?>> {
@Override
protected RestPage<?> resolveInternalResponse(
@NotNull RestPage<?> restPage,
Class<? extends RestPage<?>> aClass,
@NotNull ConversionProvider conversionProvider,
String mapping
) {
return new RestPage<>(
restPage.getFilter(),
restPage.getContent().parallelStream().map(conversionProvider::createResponse).toList(),
restPage.getTotalElements()
);
}
@Override
protected Class<?> extractInternalExample(@NotNull RestPage<?> from, String mapping, Object globalContextOrPassedContext) {
return from.stream().map(Object::getClass).findFirst().orElse(null);
}
@Override
protected boolean canProcess(Class<?> from, Type generics, ConversionProvider provider, String mapping) {
return RestPage.class.isAssignableFrom(from);
}
}
Π ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π²ΡΡΠ΅ ΡΠ΅ΡΠΎΠ»Π²ΠΈΡΡΡ REST ΡΡΡΠ°Π½ΠΈΡΠ°. ΠΡΠΈΠΌΠ΅Ρ Π²ΡΡΠ΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ Rest ΡΡΡΠ°Π½ΠΈΡΡ. ΠΡΠΈ ΡΡΠΎΠΌ ΠΎΡΡΠ°Π²Π»ΡΡ ΡΠΎΡ ΠΆΠ΅ ΡΠΎΡΠΌΠ°Ρ.