티스토리 뷰

donaricano-btn
반응형

지난번 포스팅에서 클래스로더를 알아본다고 했는데 순서를 좀 바꾸겠습니다.

 

어떤 url을 입력 받았을 때 어떤 서블릿을 동작해야 하는지 어떻게 알 수 있을까요? 서블릿은 배포서술자(물론 애너테이션을 사용하는 방법도 있지만 이 프로젝트에서는 고려하지 않도록 하겠습니다)를 통해서 매핑됩니다. 컨테이너는 이 배포서술자 파일을 통해 url과 일치하는 클래스를 찾아서 로드하게 됩니다.

 

배포서술자는 보통 xml 파일로 만들어지고 다음과 같은 구조를 하고 있습니다.

web.xml 이라는 이름을 가진 xml 파일에 배포와 관련된 여러가지 설정 정보들을 담게 됩니다. 사실 이 배포서술자 안에 기술될 수 있는 정보는 매우 많지만 이 프로젝트에서는 서블릿 매핑 부분만 구현해 보도록 하겠습니다. 이 배포서술자나 애너테이션에 대해서는 이 페이지를 참고 부탁드립니다.


일단 web-app 태그 내부에 서블릿을 정의합니다.  태그 안에 등록된 서블릿들이 컨테이너가 관리하는 서블릿을 의미합니다. 이 때 사용하는 은 오로지 배포서술자 안에서 구분을 위해서 사용하는 이름으로 실제 클래스명이나 클라이언트에서 호출한 URL 이름과는 다릅니다. 그리고 클래스의 위치를 이름과 매핑합니다.

servlet-mapping 태그를 통해 클라이언트에서 URL을 통해 요청받은 이름과 servlet-name을 매핑합니다. 이 때 URL은 클라이언트 에서 사용하는 서블릿의 이름으로 실제 클래스 이름과는 다릅니다.

이렇게 배포서술자를 이용하면 하나의 서블릿이 세가지의 이름을 가지게 됩니다. 이렇게 함으로서 유연성, 보안성이 증대되는 효과를 얻을 수 있습니다. 클래스의 위치나 이름이 바뀌었을 때 배포서술자의 해당 부분만 바꿔 주면 쉽게 수정할 수 있고, 클라이언트에 실제 클래스 위치를 숨겨 주기 때문에 보안성이 증대된다고 볼 수 있습니다.

단순히 서블릿을 매핑하는 용도 외에도 배포서술자를 통해 웹 앱에 필요한 다양한 정보를 서술할 수 있습니다. 배포서술자를 활용했을 때 가장 큰 장점은 작성한 소스코드를 바꾸지 않고 중요한 부분을 수정할 수 있다는 점입니다.

 

이제 이 배포서술자를 실제로 읽어들이는 코드를 한 번 만들어 보도록 하겠습니다.

 

1) 배포서술자 읽기

    public String getDeploymentDescriptor(String filePath) {
        String xml = "";
        File file = new File(filePath);
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
            String line;
            while ((line = reader.readLine()) != null) {
                xml += line.trim();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return xml;
    }

 

2) 요소(element) 찾기

    public ArrayList<String> getElements(String elementName, String deploymentDescriptor) {
        ArrayList<String> elements = new ArrayList<>();
        String startTag = getStartTag(elementName);
        String endTag = getEndTag(elementName);
        int startIdx = 0;
        int endIdx = 0;
        while ((startIdx = deploymentDescriptor.indexOf(startTag, endIdx)) != -1) {
            startIdx += startTag.length();
            endIdx = deploymentDescriptor.indexOf(endTag, startIdx);
            String element = deploymentDescriptor.substring(startIdx, endIdx);
            elements.add(element);
        }
        return elements;
    }
    
    public String getElement(String elementName, String deploymentDescriptor) {
        String startTag = getStartTag(elementName);
        String endTag = getEndTag(elementName);
        return deploymentDescriptor.substring(deploymentDescriptor.indexOf(startTag) + startTag.length()
                , deploymentDescriptor.indexOf(endTag));
    }

 

위 코드는 배포서술자가 있는 경로에서 문자열 형태로 배포서술자의 내용을 가져온 뒤, 입력받은 요소 값을 찾아서 리턴하는 코드입니다. getElements() 메소드는 배포서술자 상에 있는 모든 elements를 문자열 리스트 형태로 반환하고 getElement() 메소드는 가장 처음 나타나는 요소를 문자열로 반환합니다.

 

3) 서블릿 매핑

    private void setElementMap(DeploymentDescriptorReader reader, String element) {
        ArrayList<String> servlets = reader.getElements(element);
        for (String servlet : servlets) {
            String key = reader.getAppName() + SLASH + reader.getElement(getKey(element), servlet);
            String value = reader.getAppName() + SLASH + reader.getElement(getValue(element), servlet);
            putElementMap(element, key, value);
        }
    }

서블릿 매핑의 기본적인 원리는 서블릿의 이름과 url, class 를 저장하는 맵을 만들어서 직접 mapping 하는 것입니다. DeploymentDescriptorReader 를 이용해 요소의 문자열을 리턴받아 서블릿 맵에 저장합니다.

 

이제 이 was는 요청받은 정적파일을 전송할 수 있고 url에 따라 어떤 클래스를 로드해야 할 지도 알고 있습니다. 그럼 이제 진짜 클래스를 로드해 봐야 겠지요. 다음 포스팅에서는 로드해야 할 클래스를 한 번 만들어 보도록 하겠습니다.

반응형
donaricano-btn
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함