elevne's Study Note

Java HttpServer 사용해보기 본문

Backend/Java

Java HttpServer 사용해보기

elevne 2023. 2. 23. 17:30

Java 에서 Spring 프레임워크를 사용하지 않고 서버를 생성하는 방법에 대해 알아보았다. 이러한 경우에는 HttpServer 클래스를 사용할 수 있다. 우선 아래와 같이 main 함수를 구성하였다.

 

 

 

public static void main(String[] args) throws Exception{
    HttpServer server = HttpServer.create(new InetSocketAddress(8090), 0);
    server.createContext("/", new MyRequestHandler());
    server.setExecutor(null);
    server.start();
    System.out.println("================================================================");
    System.out.println("test server started");
    System.out.println("================================================================");
}

 

 

 

HttpServer.create() 메서드에 인자로 InetSocketAddress(원하는포트번호) 를 넣어서 서버를 만들어준다. 그 후 createContext 메서드에 HttpHandler 을 활용하여 요청처리를 진행해줄 수 있는 것이다. 또한, HttpServer 클래스는 수신 요청을 처리하는데 사용할 Executor 인스턴스를 지정할 수 있는 setExecutor 메서드를 제공한다. (여기서 Executor 은 작업을 비동기적으로 실행하는 방법을 제공하는 Java 의 인터페이스이다)

 

 

 

아래는 위 createContext 메서드의 인자로 활용된 MyRequestHandler 클래스이다.

 

 

 

    private static class MyRequestHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String requestUri = exchange.getRequestURI().toString();
            switch (requestUri) {
                case "/hello":
                    handleHelloRequest(exchange);
                    break;
                case "/bye":
                    handleByeRequest(exchange);
                    break;
                default:
                    handleUnknownRequest(exchange);
                    break;
            }
        }
        private void handleHelloRequest(HttpExchange exchange) throws IOException {
            String response = "Hello, World!";
            sendResponse(exchange, response);
        }
        private void handleByeRequest(HttpExchange exchange) throws IOException {
            String response = "Goodbye, World!";
            sendResponse(exchange, response);
        }
        private void handleUnknownRequest(HttpExchange exchange) throws IOException {
            String response = "Unknown request";
            sendResponse(exchange, response);
        }
        private void sendResponse(HttpExchange exchange, String response) throws IOException {
            exchange.sendResponseHeaders(200, response.getBytes().length);
            exchange.getResponseBody().write(response.getBytes());
            exchange.close();
        }
    }

 

 

 

handle 메서드를 오버라이딩하여 들어오는 요청들을 분기하여 처리해줄 수 있다. handle 메서드에서는 HttpExchange 클래스를 인자로 사용하는데, 이는 HttpServer 에서 처리 중인 현재 HTTP 요청 및 응답 교환을 나타내는 것이다.  HttpExchange 클래스는 수신 요청 헤더에 액세스하고, 요청 바디를 읽고, 응답 헤더를 보내고, 응답 바디를 작성하는 방법들을 제공한다. 또한 응답 상태 코드 및 응답 헤더를 설정하는 방법도 제공한다.

 

 

이를 실행시켜 postman 을 통해 확인해보았다.

 

 

 

 

 

result

 

 

 

동시에 여러 개의 서버를 실행시키는 것 또한 가능하다. 또, 아래와 같은 코드를 통해서 웹 브라우저에서 html 파일을 열어볼 수도 있다.

 

 

 

public static void main(String[] args) throws IOException {
    HttpServer server = HttpServer.create(new InetSocketAddress(8090), 0);
    server.createContext("/", new RootHandler());
    server.setExecutor(Executors.newCachedThreadPool());
    server.start();
}

static class RootHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        if ("GET".equals(exchange.getRequestMethod())) {
            String uri = exchange.getRequestURI().toString();
            System.out.println(uri);
            if ("/test".equals(uri)) {
                File file = new File("src/index.html");
                BufferedReader reader = new BufferedReader(new FileReader(file));
                StringBuilder builder = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    builder.append(line);
                    builder.append("\n");
                }
                reader.close();
                String response = builder.toString();
                System.out.println(response);
                exchange.sendResponseHeaders(200, response.getBytes().length);
                OutputStream output = exchange.getResponseBody();
                output.write(response.getBytes());
                output.flush();
                output.close();
            } else {
                String response = "404 (Not Found)";
                exchange.sendResponseHeaders(404, response.length());
                OutputStream output = exchange.getResponseBody();
                output.write(response.getBytes());
                output.flush();
                output.close();
            }
        }
    }
}

 

 

 

server.setExecutor(Executors.newCachedThreadPool())는 HTTP 서버 인스턴스의 실행자를 Executors.newCachedThreadPool() 메서드에서 만든 캐시된 스레드 풀로 설정하기 위한 메서드 호출이다. 다중 스레드 서버에서 실행자는 수신 요청을 처리하는 스레드를 관리하고 예약한다. Executors.newCachedThreadPool() 메서드는 필요에 따라 새 스레드를 만들고 유휴 스레드를 사용할 수 있을 때 재사용하는 스레드 풀을 만든다. 이 유형의 실행기는 빠른 처리가 가능한 단기 요청이 많은 서버에 적합하다고 한다. HttpServer 인스턴스의 실행자를 캐시된 스레드 풀로 설정하면 수신 요청이 풀의 사용 가능한 스레드에 의해 효율적으로 처리된다. 요청이 들어오면 사용 가능한 유휴 스레드가 없는 경우 이를 처리하기 위해 새 스레드가 생성되고, 요청이 완료되면 이후 요청을 처리할 때 재사용할 수 있도록 스레드가 풀로 반환되는 것이다.

 

 

index.html 파일은 아래와 같이 작성하였고, 이를 웹 브라우저에서 확인해보았다.

 

 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        document.addEventListener("DOMContentLoaded", function(){
            document.getElementById("testNum").value = 1;
            document.getElementById("showTestNum").textContent = 1;
        })
        const changeNum = () => {
            let num = Number(document.getElementById("testNum").value) * 2;
            document.getElementById("testNum").value = num;
            document.getElementById("showTestNum").textContent = num;
        }
    </script>

</head>

<body>
<button type="button" onclick="changeNum()">
TEST
</button>
<input type="hidden" id="testNum"/>
<span id="showTestNum"></span>
</body>
</html>

 

 

result

 

 

 

위 사진이 localhost:8090/test 로 웹 브라우저에서 접속한 결과 화면이다. 

'Backend > Java' 카테고리의 다른 글

Java Keywords ...  (0) 2023.04.12
Cache 에 대하여  (0) 2023.03.27
Java 공부 (File 다운로드)  (0) 2023.02.16
Java의정석 공부 - (10: I/O, File)  (0) 2023.02.15
Java의정석 공부 - (9: Optional)  (0) 2023.02.07