본문 바로가기
Java

자바 Rest api2

by NaHyungMin 2020. 7. 16.

자바를 처음보고 작업한지 2주정도 지났다. 일수로는 9일정도.

2010년도에는 자바가 확실히 참고할 자료도 많고 좋다고 느꼈는데, 현재 내린 결론은 요즘 자바는 예전 자바만 못한거 같다.

파이썬, C#은 기본이고 자바스크립트보다 어렵지 않나 싶다. (아마 버전이 최신으로 나와도 쉽게 종속성을 못 올리는게 가장 큰 이유 같다.)

 

Rest api를 만들면서 C#에서 사용했던 구조를 적용해봤다.

프로젝트 구조는 현재 이렇다. 아직 전부 구현된 상태가 아니기에.. 스프링으로 약속된 구조가 맞나? 확인하는게 코딩보다 어려웠다.

 

interface 패키지 안에는 커스텀 어노테이션(애트리뷰트)와 Dto 전용 인터페이스 껍데기를 구현해놨다.

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface IColumn {
    String Name();
}
public interface IDtoSelector {
}

 

얘낸 제네릭 제약용 껍대기.

 

다음은 nice 전용 모듈

 

private static final String authType = "M"; // 없으면 기본 선택화면, M: 핸드폰, C: 신용카드, X: 공인인증서
    private static final String popupButton = "N"; //Y : 취소버튼 있음 / N : 취소버튼 없음
    private static final String customize = "Mobile"; //없으면 기본 웹페이지 / Mobile : 모바일페이지
    private static final String gender = ""; //0 : 여자, 1 : 남자
    private static final String returnUrl = "http://app.superpay.systems/api/checkplus_success";
    private static final String errorUrl = "http://app.superpay.systems/api/checkplus_fail";

    public static boolean checkPlus(AtomicReference<Integer> resultCode
            , AtomicReference<String> resultEncode) {

        try{
            CPClient client = new CPClient();
            String requestSequence = client.getRequestNO(Constants.niceCode);

            // 입력될 plain 데이타를 만든다.
            String palin = "7:REQ_SEQ" + requestSequence.getBytes().length + ":" + requestSequence +
                    "8:SITECODE" + Constants.niceCode.getBytes().length + ":" + Constants.niceCode +
                    "9:AUTH_TYPE" + authType.getBytes().length + ":" + authType +
                    "7:RTN_URL" + returnUrl.getBytes().length + ":" + returnUrl +
                    "7:ERR_URL" + errorUrl.getBytes().length + ":" + errorUrl +
                    "11:POPUP_GUBUN" + popupButton.getBytes().length + ":" + popupButton +
                    "9:CUSTOMIZE" + customize.getBytes().length + ":" + customize +
                    "6:GENDER" + gender.getBytes().length + ":" + gender;

            resultCode.set(client.fnEncode(Constants.niceCode, Constants.nicePassword, palin));
            resultEncode.set(client.getCipherData());
        }catch (Exception ex){
            return false;
        }

        return true;
    }

자바는 닷넷과 다르게 ref나 out 키워드가 없다. 그래서 AtomicReference 클래스에 데이터를 넣어서 사용했다.

checkPlus는 아직 테스트를 못 했다. 나중에 테스트 해야 함.

 

AtomicReference<Integer> resultCode = new AtomicReference();
AtomicReference<String> resultEncode = new AtomicReference();

boolean result = NiceModule.checkPlus(resultCode, resultEncode);

 

response/Exception 패키지(글 쓰다보니 e가 대문자라 소문자로 변경했다. -..-)

다른 사람 블로그에 오류 처리하는 내용이 있어서 가져다가 Code를 추가하는 식으로 변경했다.

양형이 쓴 내용과 살짝 합침.

 

import org.springframework.http.HttpStatus;

public abstract class AbstractRestapiBaseException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public AbstractRestapiBaseException() {
        super();
    }

    public AbstractRestapiBaseException(String msg) {
        super(msg);
    }

    public AbstractRestapiBaseException(Throwable e) {
        super(e);
    }

    public AbstractRestapiBaseException(String errorMessge, Throwable e) {
        super(errorMessge, e);
    }

    public abstract HttpStatus getHttpStatus();
}

import org.springframework.http.HttpStatus;

public class RestapiBindingException extends AbstractRestapiBaseException {

    private static final long serialVersionUID = 1L;

    public RestapiBindingException() {
        super();
    }

    public RestapiBindingException(Throwable e) {
        super(e);
    }

    public RestapiBindingException(String errorMessge) {
        super(errorMessge);
    }

    public RestapiBindingException(String errorMessge, Throwable e) {
        super(errorMessge, e);
    }

    public HttpStatus getHttpStatus() {
        return HttpStatus.BAD_REQUEST;
    }
}

import lombok.Getter;
import org.springframework.http.HttpStatus;

public class RestapiInvalidRequestException extends AbstractRestapiBaseException {

    private static final long serialVersionUID = 1L;

    @Getter
    private int errorCode;

    public int getErrorCode() { return errorCode; }

    public RestapiInvalidRequestException() {
        super();
    }

    public RestapiInvalidRequestException(Throwable e) {
        super(e);
    }

    public RestapiInvalidRequestException(String errorMessge) {
        super(errorMessge);
    }

    public RestapiInvalidRequestException(String errorMessge, Throwable e) {
        super(errorMessge, e);
    }

    public RestapiInvalidRequestException(int errorCode, String errorMessge, Throwable e) {
        super(errorMessge, e);
        this.errorCode = errorCode;
    }

    public RestapiInvalidRequestException(int errorCode, String errorMessge) {
        super(errorMessge);
        this.errorCode = errorCode;
    }

    public HttpStatus getHttpStatus() {
        return HttpStatus.BAD_REQUEST;
    }
}

import org.springframework.http.HttpStatus;

public class RestapiNotFoundException extends AbstractRestapiBaseException {

    private static final long serialVersionUID = 1L;

    public RestapiNotFoundException() {
        super();
    }

    public RestapiNotFoundException(Throwable e) {
        super(e);
    }

    public RestapiNotFoundException(String errorMessge) {
        super(errorMessge);
    }

    public RestapiNotFoundException(String errorMessge, Throwable e) {
        super(errorMessge, e);
    }

    public HttpStatus getHttpStatus() {
        return HttpStatus.NOT_FOUND;
    }
}


import org.springframework.http.HttpStatus;

public class RestapiUnknownException extends AbstractRestapiBaseException {

    private static final long serialVersionUID = 1L;

    public RestapiUnknownException() {
        super();
    }

    public RestapiUnknownException(Throwable e) {
        super(e);
    }

    public RestapiUnknownException(String errorMessge) {
        super(errorMessge);
    }

    public RestapiUnknownException(String errorMessge, Throwable e) {
        super(errorMessge, e);
    }

    public HttpStatus getHttpStatus() {
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }
}

com.package에는 자신의 중간 package명을 넣으면 된다.

 

import com.package.commonlib.util.response.exception.AbstractRestapiBaseException;
import com.package.commonlib.util.response.exception.RestapiBindingException;
import com.package.commonlib.util.response.exception.RestapiInvalidRequestException;
import com.package.commonlib.util.response.exception.RestapiUnknownException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//@Slf4j
@EnableWebMvc
@ControllerAdvice
@ResponseBody
public class AbstractBaseRestController {

    @ExceptionHandler(AbstractRestapiBaseException.class)
    public ResponseMessage abstractBaseException(HttpServletRequest req, HttpServletResponse res, final AbstractRestapiBaseException exception){
        
        //log.error("AbstractEbloBaseException : "+exception.getMessage());
        res.setStatus(exception.getHttpStatus().value());
        return new ResponseMessage(CustomErrorCode.Base_Error, exception, req.getRequestURL().toString());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(value= HttpStatus.BAD_REQUEST)
    public ResponseMessage illegalArgumentException(HttpServletRequest req, final IllegalArgumentException exception){
        //log.error("IllegalArgumentException : "+exception.getMessage());
        return new ResponseMessage(CustomErrorCode.IllegalArgument, new RestapiInvalidRequestException(exception.getMessage(), exception), req.getRequestURL().toString());
    }

    @ExceptionHandler(Throwable.class)
    @ResponseBody
    ResponseEntity<Object> handleControllerException(HttpServletRequest req, Throwable ex) {
        String internalMessage = "서버에 오류가 발생했습니다.";
        ResponseMessage message = new ResponseMessage(CustomErrorCode.Throwable, new RestapiUnknownException(internalMessage, ex), req.getRequestURL().toString());
        return new ResponseEntity<Object>(message, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(RestapiInvalidRequestException.class)
    @ResponseStatus(value= HttpStatus.BAD_REQUEST)
    public ResponseMessage RestapiInvalidRequestException(HttpServletRequest req, final RestapiInvalidRequestException exception){
        //log.error("IllegalArgumentException : "+exception.getMessage());
        return new ResponseMessage(exception.getErrorCode(), new RestapiInvalidRequestException(exception.getMessage(), exception), req.getRequestURL().toString());
    }

    @ExceptionHandler(RestapiBindingException.class)
    @ResponseStatus(value=HttpStatus.BAD_REQUEST)
    public ResponseMessage bindingErrors(final HttpServletRequest req, final RestapiBindingException exception) {
        return new ResponseMessage(CustomErrorCode.Binding, new RestapiBindingException(exception.getMessage(), exception), req.getRequestURL().toString());
    }
}

처음에 enum으로 하려다가 자바는 C#과 다르게 enum class? 형식으로 사용하는 듯 싶어, 그냥 enum patten을 사용했다. 내가 에러 코드를 추가할거라 상관없지만 다른 사람과 쓸 경우 string을 넣지 않게 숙지시켜야 한다.

 

public class CustomErrorCode {
    public static final int None = 0;
    public static final int Base_Error = 1;
    public static final int IllegalArgument = 2;
    public static final int Throwable = 3;
    public static final int Binding = 4;

    //Controller Error
    public static final int Email_Blank = 50;
    public static final int .... = 50;
    public static final int ..... = 51;
    public static final int ..... = 52;

    public static final int ....... = 100;

    CustomErrorCode(int value) { this.value = value; }

    private final int value;
    public int value() { return value; }
}


/*
enum ErrorTypes{
    Temp(100);

    ErrorTypes(int value) { this.value = value; }

    private final int value;
    public int value() { return value; }
}
*/

 

문자열을 하드코딩하지않고 나중에 재활용하려고 미리 메모리에 올려놨다.

 

public class CustomErrorMessgae {
    public static final String emailBlank = "Email은 공백일 수 없습니다.";
    public static final String ...... = "비밀번호는 공백일 수 없습니다.";
    public static final String ..... = "이름은 공백일 수 없습니다.";
    public static final String ..... = "전화번호는 공백일 수 없습니다.";
    public static final String ..... = "전화번호는 공백일 수 없습니다.";
    public static final String ..... = "이미 존재하는 회원입니다.";
    public static final String ..... = "계정 생성에 실패했습니다.";

    public static final int Base_Error = 1;
    public static final int IllegalArgument = 2;
    public static final int Throwable = 3;
}

 

import lombok.Getter;
import lombok.Setter;
import org.apache.commons.pool2.BaseObject;

@Getter
@Setter
public class ErrorMessage extends BaseObject {

    private static final long serialVersionUID = 1L;

    private final int code;
    private final String errorMessage;
    private final String referedUrl;

    public ErrorMessage(int code, String errorMessage, String referedUrl) {
        super();
        this.code = code;
        this.errorMessage = errorMessage;
        this.referedUrl = referedUrl;
    }
}

 

Gson을 사용하면 json으로 만들 때, Expose 어노테이션을 통해 출력하고 싶은 내용만 할 수 있다.

 

import com.google.gson.annotations.Expose;
import com.package.commonlib.util.response.exception.AbstractRestapiBaseException;
import lombok.Getter;
import org.apache.commons.pool2.BaseObject;
import org.springframework.http.HttpStatus;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
@Getter
public class ResponseMessage extends BaseObject {

    private static final long serialVersionUID = 1L;
    private static final String DEFAULT_KEY = "result";

    @Expose
    private int code;

    @Expose
    private boolean status;

    @Expose
    private String message;

    @Expose
    private Date timestamp;

    @Expose
    //private Object data;
    private List<Object> data;
    /*private Map<String, Object> data;*/

    @Expose
    private ErrorMessage error;

    public ResponseMessage() {
        this(HttpStatus.OK);
    }

    public ResponseMessage(HttpStatus httpStatus) {
        //this.data = new HashMap<>();
        this.data = new ArrayList<Object>();
        InitResponseMessage(httpStatus);
    }

    public ResponseMessage(int errorCode, AbstractRestapiBaseException ex, String referedUrl) {
        HttpStatus httpStatus = ex.getHttpStatus();
        //this.data = new HashMap<>();
        this.error = new ErrorMessage(errorCode, ex.getMessage(), referedUrl);
        this.data = new ArrayList<Object>();
        InitResponseMessage(httpStatus);
    }

    private void InitResponseMessage(HttpStatus httpStatus){
        this.code = httpStatus.value();
        this.status = httpStatus.is2xxSuccessful(); //(httpStatus.isError())? false:true;
        this.message = httpStatus.getReasonPhrase();
        this.timestamp = new Date();
    }

    public ResponseMessage(HttpStatus status, Object result) {
        this(status);
        this.data.add(result);
        //this.data = result.toString();
        //this.data.put(DEFAULT_KEY, result);
    }

    public void add(Object data) {
        this.data.add(data);
        //this.data = Singleton.<JsonConvert>Instance(JsonConvert.class).Convert(cls);
    }

    public void remove(int index) {
        this.data.remove(index);
    }

   /* public void add(String key, Object result) {
        this.data.put(key, result);
    }

    public void remove(String key) {
        this.data.remove(key);
    }*/
}

 

package com.package.commonlib.util;

import com.package.commonlib.util.response.exception.AbstractRestapiBaseException;
import com.package.commonlib.util.response.exception.RestapiInvalidRequestException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Map;

public class CustomAssert extends Assert {
    private static final String NUMBER_ALPHABET_PATTERN = "^[a-zA-Z\\d]+$";
    private static final String NUMERIC_PATTERN = "^[\\+\\-]{0,1}[\\d]+$";
    private static final String FLOAT_PATTERN = "^[\\+\\-]{0,1}[\\d]+[\\.][0-9]+$";

    /**
     * Assert a boolean expression, TRUE가 아닌 경우 사용자가 정의한 예외를 던진다.
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.state(id == null, "The id property must not already be initialized", RestApiInvalidRequestException.class);</pre>
     * @param expression a boolean expression
     * @param message the exception message to use if the assertion fails
     * @param exceptionClass
     * @throws IllegalStateException if {@code expression} is {@code false}
     */
    public static void state(boolean expression, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (!expression) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * Assert a boolean expression, TRUE가 아닌 경우 사용자가 정의한 예외를 던진다.
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.isTrue(user != null, "사용자 정보가 존재하지 않습니다.", RestApiNotFoundException.class);</pre>
     * @param expression a boolean expression
     * @param message the exception message to use if the assertion fails
     * @param exceptionClass
     * @throws IllegalStateException if {@code expression} is {@code false}
     */
    public static void isTrue(boolean expression, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (!expression) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * Assert that an object is {@code null}. 객체가 null이 아닌 경우 사용자가 정의한 예외를 던진다.
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.isNull(user, "기존 사용자 정보가 존재합니다.", RestApiInvalidRequestException.class);</pre>
     * @param object a boolean expression
     * @param message the exception message to use if the assertion fails
     * @param exceptionClass
     * @throws IllegalStateException if {@code expression} is {@code false}
     */
    public static void isNull(@Nullable Object object, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (object != null) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * null인 경우 사용자 정의 예외 발생
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.notNull(user, "사용자 정보가 존재하지 않습니다.", RestApiNotFoundException.class);</pre>
     * @param object
     * @param message
     * @param exceptionClass
     */
    public static void notNull(@Nullable Object object, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (object == null) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * 전달받은 값이 null이 거나 빈값인 경우 사용자 정의 예외 발생
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.hasLength(value, "전달 받은 값이 빈값입니다.", RestApiInvalidRequestException.class);</pre>
     * @param text
     * @param message
     * @param exceptionClass
     */
    public static void hasLength(@Nullable String text, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * 전달받은 값이 null이 거나 빈값인 경우 사용자 정의 예외 발생
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.hasText(value, "전달 받은 값이 빈값입니다.", RestApiInvalidRequestException.class);</pre>
     * @param text
     * @param message
     * @param exceptionClass
     */
    public static void hasText(@Nullable String text, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * 전달받은 값이 null이 거나 빈값인 경우 사용자 정의 예외 발생
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.notEmpty(array, "전달 받은 값이 빈값입니다.", RestApiInvalidRequestException.class);</pre>
     * @param array
     * @param message
     * @param exceptionClass
     */
    public static void notEmpty(@Nullable Object[] array, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * 전달받은 값이 null이 거나 빈값인 경우 사용자 정의 예외 발생
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.notEmpty(collection, "전달 받은 값이 빈값입니다.", RestApiInvalidRequestException.class);</pre>
     * @param collection
     * @param message
     * @param exceptionClass
     */
    public static void notEmpty(@Nullable Collection<?> collection, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * 전달받은 값이 null이 거나 빈값인 경우 사용자 정의 예외 발생
     * 사용자 정의 예외는 AbstractRestApiBaseException.class를 상속 받아 구현해야 한다.
     * <pre class="code">Assert.notEmpty(map, "전달 받은 값이 빈값입니다.", RestApiInvalidRequestException.class);</pre>
     * @param map
     * @param message
     * @param exceptionClass
     */
    public static void notEmpty(@Nullable Map<?, ?> map, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            throwException(message, exceptionClass);
        }
    }

    private static void throwException(String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        try {
            throw exceptionClass.getDeclaredConstructor( String.class ).newInstance( message );
        } catch (Exception e) {
            e.printStackTrace();
            //throw new RestapiSystemException("예외 처리 중 오류가 발생했습니다. "+e.getMessage());
        }
    }

    /**
     * 값이 영문 알파벳, 숫자가 아닌 경우 예외 발생
     * @param object
     * @param message
     */
    public static void isAlphaNumber(String object, String message) {
        isMatched(object, NUMBER_ALPHABET_PATTERN, message, RestapiInvalidRequestException.class);
    }

    /**
     * 값이 영문 알파벳, 숫자가 아닌 경우 사용자 정의 예외 발생
     * @param object
     * @param message
     * @param exceptionClass
     */
    public static void isAlphaNumber(String object, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        isMatched(object, NUMBER_ALPHABET_PATTERN, message, exceptionClass);
    }

    /**
     * 값이 숫자가 아닌 경우 예외 발생
     * @param object
     * @param message
     */
    public static void isNumeric(String object, String message) {
        isMatched(object, NUMERIC_PATTERN, message, RestapiInvalidRequestException.class);
    }

    /**
     * 값이 숫자가 아닌 경우 사용자 정의 예외 발생
     * @param object
     * @param message
     * @param exceptionClass
     */
    public static void isNumeric(String object, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        isMatched(object, NUMERIC_PATTERN, message, exceptionClass);
    }

    /**
     * 값이 float, double이 아닌 경우 예외 발생
     * @param object
     * @param message
     */
    public static void isFloat(String object, String message) {
        isMatched(object, FLOAT_PATTERN, message, RestapiInvalidRequestException.class);
    }

    /**
     * 값이 float, double이 아닌 경우 사용자 정의 예외 발생
     * @param object
     * @param message
     * @param exceptionClass
     */
    public static void isFloat(String object, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        isMatched(object, FLOAT_PATTERN, message, exceptionClass);
    }

    /**
     * 패턴 매치, 해당 패턴과 일치 하지 않는 경우 사용자 정의 예외 발생
     * @param object
     * @param pattern
     * @param message
     * @param exceptionClass
     */
    public static void isMatched(String object, String pattern, String message, final Class<? extends AbstractRestapiBaseException> exceptionClass) {
        if(object == null || "".equalsIgnoreCase(object)) return;

        if(!object.matches(pattern)) {
            throwException(message, exceptionClass);
        }
    }

    /**
     * 패턴 매치, 해당 패턴과 일치 하지 않는 경우 예외 발생
     * @param object
     * @param pattern
     * @param message
     */
    public static void isMatched(String object, String pattern, String message) {
        if(object == null || "".equalsIgnoreCase(object)) return;

        if(!object.matches(pattern)) {
            throwException(message, RestapiInvalidRequestException.class);
        }
    }

  /*  public static void notNullAndEmpty(@Nullable String text, String message, int code) {
        if (text == null || 1 > text.length())
            throwException(message, RestapiInvalidRequestException.class);
        }
    }*/
}

 

날짜 변환 클래스

 

package com.package.commonlib.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {
    public static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");

    public static final SimpleDateFormat yyyyMM = new SimpleDateFormat("yyyyMM");
    public static final SimpleDateFormat HHmmss = new SimpleDateFormat("HH:mm:ss");

    public static Date getDate() {
        return new Date(System.currentTimeMillis());
    }

    public static Date getDate(int field, int amount) {
        Calendar c = Calendar.getInstance();
        c.add(field, amount);
        return c.getTime();
    }

    public static String getDateString(String format, int field, int amount) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        Calendar c = Calendar.getInstance();
        c.add(field, amount);
        return sf.format(c.getTime());
    }

    public static String getDateString(SimpleDateFormat format, int field, int amount) {
        Calendar c = Calendar.getInstance();
        c.add(field, amount);
        return format.format(c.getTime());
    }

    public static String getDateString(String format) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(DateUtil.getDate());
    }

    public static String getDateString(Date date, String format) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(date);
    }

    public static Date parseDate(String str, String format) throws ParseException {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.parse(str);
    }

    public static Date parseDate(String str, String format, int field, int amount) throws ParseException {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        Date date = sf.parse(str);
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(field, amount);
        return c.getTime();
    }
}

 

Json으로 변경하는 클래스

 

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class JsonConvert {
    Gson gson = null;

    public JsonConvert(){
        gson = new GsonBuilder()
                .disableHtmlEscaping()
                .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
                .setPrettyPrinting()
                .serializeNulls()
                .excludeFieldsWithoutExposeAnnotation()
                .create();
    }

    public String convert(Object obj)
    {
        String json = gson.toJson(obj);

        if(log.isDebugEnabled())
            log.debug("select result json [{}]", json.length() > 0 ? json : "NULL");

        return json;
    }
}

 

싱글턴 모음 클래스

 

package com.package.commonlib.util;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class Singleton {
    private static Map<String, Object> instances = new HashMap<String, Object>();
    private Singleton(){}

    public static <T> T Instance(Class<T> cls, Object... args){
        Class<T> c = null;
        String name = cls.getName();
        
        synchronized (Singleton.class){
            try {
                c = (Class<T>)Class.forName(name);

                if (!instances.containsKey(name)) {
                    T inst;
                    try {
                        Class<?>[] parameterTypes = new Class<?>[args.length];
                        for (int i = 0; i < args.length; i++) {
                            parameterTypes[i] = args[i].getClass();
                        }
                        inst = c.getConstructor(parameterTypes).newInstance(args);
                    } catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException
                            | InstantiationException | IllegalAccessException e) {
                        System.err.println("Can't get or call constructor");
                        e.printStackTrace();
                        return null;
                    }
                    instances.put(name, inst);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        return c.cast(instances.get(name));
    }
}

 

마이바티스에서 조회할 때, 결과 맵으로 만들어야 하는게 귀찮아서 만듬. 이건 성능 테스트 좀 해봐야 한다.

자바 리플렉션에 속도 체크.

 

import com.package.commonlib.interfaces.IColumn;
import com.package.commonlib.interfaces.IDtoSelector;

import java.lang.reflect.Field;
import java.util.HashMap;

public class DtoWrapper {
    public static void BindData(HashMap<String, Object> hashmap, IDtoSelector dtoClass)
    {
        for(Field filed : dtoClass.getClass().getDeclaredFields())
        {
            IColumn annotation = filed.getAnnotation(IColumn.class);

            if(annotation != null)
            {
                if(hashmap.containsKey(annotation.Name()) == true)
                {
                    try {
                        filed.setAccessible(true);
                        filed.set(dtoClass, hashmap.get(annotation.Name()));
                        filed.setAccessible(false);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

 

글이 너무 길어져 나머지 구조는 다음 글에서 정리.

'Java' 카테고리의 다른 글

자바 스프링 기본 구조  (0) 2020.07.16
자바 Rest api3  (0) 2020.07.16
자바 Rest api  (0) 2020.07.06
자바 싱글턴 테스트  (0) 2020.07.06
인텔리제이 톰캣 연결  (0) 2020.07.01