[ODOP] 69일차 - AntPathMatcher 도입

[ODOP] 69일차 - AntPathMatcher 도입 기록입니다. 직접 만든 Spring boot framework 에 AntPathMatcher 클래스를 도입합니다.

[ODOP] 69일차 - AntPathMatcher 도입

그간 공부했던 AntPathMatcher 를 도입하는 과정을 기록한다

본인이 만들고 있는 Spring boot 를 보고싶다면 github 에서 직접 확인 할 수 있다

public 으로 열어두었으니 얼마든지 확인 할 수 있을 것이다.

GitHub - pollra/writing-spring-framework-from-scratch: 지식나눔@eddi
지식나눔@eddi. Contribute to pollra/writing-spring-framework-from-scratch development by creating an account on GitHub.

AntPathMatcher 의 모든 기능들은 만들고있는 Spring boot 에 적합한 기능들이므로 특정 기능을 제거한다거나 제외하지 않고 모두 적용하려고 한다

대부분의 코드는 그대로 복사 할 것이다

그 과정에서 Spring 내부에서 사용하는 의존성들이 존재한다

의존성이 존재하는 부분들을 확인하고, 작성된 코드를 공유해본다

...
    public AntPathMatcher(String pathSeparator) {
		Assert.notNull(pathSeparator, "'pathSeparator' must not be null");
		this.pathSeparator = pathSeparator;
		this.pathSeparatorPatternCache = new PathSeparatorPatternCache(pathSeparator);
	}
...

Assert 클래스는 존재하지 않는다

다만 해당 클래스의 구현체에서 실행하고자 하는 비즈니스는 이렇다.

  • pathSeparator 가 null 일 경우, Exception 을 통해 프로그램 실행 흐름을 멈춘다

저 notNull 이라는 함수를 확인해보자

public static void notNull(@Nullable Object object, String message) {
    if (object == null) {
    	throw new IllegalArgumentException(message);
    }
}

null 이면 IllegalArgumentException 을 발생시킨다

하지만 직접 작성한 framework 에서는 IllegalArgumentException 보다는 AntPathMatcher 에 대한 예외임을 나타내는 것이 좋아보인다

public AntPathMatcher(String pathSeparator) {
    if (pathSeparator.isEmpty()) {
        throw new AntPathMatcherException("'"+pathSeparator+"' must not be null");
    }
    this.pathSeparator = pathSeparator;
    this.pathSeparatorPatternCache = new PathSeparatorPatternCache(pathSeparator);
}

StringUtil

직접 제작한 framework 에는 StringUtill 은 존재하지 않는다

protected String[] tokenizePath(String path) {
    return StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
}

따라서 당연히 위의 함수가 동작할리 없다

간단하게 StringUtill 을 만들어 줄 것인데, hasText 함수도 사용하고있다

public String combine(String pattern1, String pattern2) {
    if (!StringUtils.hasText(pattern1) && !StringUtils.hasText(pattern2)) {
        return "";
    }
    if (!StringUtils.hasText(pattern1)) {
        return pattern2;
    }
    if (!StringUtils.hasText(pattern2)) {
        return pattern1;
    }
    ...

같이 만들어주자

만들어진 결과물은 이렇다


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;

public class StringUtils {

    private static final String[] EMPTY_STRING_ARRAY = {};

    public static boolean hasText(@Nullable String str) {
        return (str != null && !str.isEmpty() && containsText(str));
    }

    private static boolean containsText(CharSequence str) {
        int strLen = str.length();
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    private static boolean isBlack(String value) {
        if (value.isEmpty() || value.isBlank()) {
            return true;
        }
        return false;
    }

    public static String[] tokenizeToStringArray(
        @Nullable String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {

        if (str == null) {
            return EMPTY_STRING_ARRAY;
        }

        StringTokenizer st = new StringTokenizer(str, delimiters);
        List<String> tokens = new ArrayList<>();
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            if (trimTokens) {
                token = token.trim();
            }
            if (!ignoreEmptyTokens || token.length() > 0) {
                tokens.add(token);
            }
        }
        return toStringArray(tokens);
    }

    private static String[] toStringArray(@Nullable Collection<String> collection) {
        return (!collection.isEmpty() ? collection.toArray(EMPTY_STRING_ARRAY) : EMPTY_STRING_ARRAY);
    }
}

변경된 AntPathMatcher 도 포함 하려 했으나, 라인이 너무 길어 가독성이 떨어진다.

Github 에 작성 해 둔 파일이 있으니, AntPathMatcher 를 Spring 이 없는 곳에서 사용하고자 한다면 참고하면 좋을 듯 하다

아래는 변경 커밋이다

feat: AntPathMatcher 도입 · pollra/writing-spring-framework-from-scratch@5a906ca
지식나눔@eddi. Contribute to pollra/writing-spring-framework-from-scratch development by creating an account on GitHub.