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
반응형

+ Recent posts