728x90
반응형
프로젝트를 진행하다가, DTO 필드들을 파싱하는 함수를 만들게 되었다.
어노테이션을 필드에 선언하여 원하는 로직을 구성할 수도 있다.
예를 들어, 아래 DTO가 있다고 하자
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReadDto {
public static final int MODEL_LENGTH = 35;
private Integer dcv;
private Integer dca;
private Integer dcw;
}
여기서 만약, 필드 별 필요한 데이터의 타입 등이 있을 경우 아래와 같이 어노테이션을 만들어서 Dto 필드에 넣어준다.
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ModbusValue {
int offset();
ModbusValueType type() default UINT_16;
}
바뀐 Dto
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReadDto {
public static final int MODEL_LENGTH = 35;
@ModbusValue(offset = 0, type = INT_16)
private Integer dcv;
@ModbusValue(offset = 1, type = INT_16)
private Integer dca;
@ModbusValue(offset = 2, type = INT_16)
private Integer dcw;
}
특정한 Dto가 아닌, 제네릭으로 받아서 Dto마다의 결과값을 반환하기 위해 제네릭 메소드로 생성한다.
public <T> T getDataObject(T object) {
try {
// Dto의 static 필드값이 필요한 경우
int quantity = object.getClass().getField(MODEL_LENGTH)
.getInt(object);
Class<?> modbusEntity = object.getClass();
Field[] columns = modbusEntity.getDeclaredFields();
// 필드 별 로직 구성
Arrays.stream(columns)
.parallel()
.forEach(column -> {
try {
ModbusValue annotation = column.getAnnotation(ModbusValue.class);
if (annotation == null) {
return;
}
int offset = annotation.offset();
var type = annotation.type();
Object value = getModbusValue(type, offset);
column.setAccessible(true);
column.set(object, castType(value, column.getType().getSimpleName()));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
return object; // 최종 DTO 객체 반환
} catch (Exception e) {
log.error("[ getDtoWithModbusRawData Error ] message: {}", e.getMessage(), e);
throw new RuntimeException(e);
}
}
이렇게 하면, 원하는 Dto의 필드들에 값을 주입하고 다시 Dto를 반환하게 할 수 있다.
아래와 같이 원하는 변수로 선언 후 사용할 수 있다.
ReadDto readDto = getDataObject(new ReadDto());
728x90
반응형