[java] Java SE API 만 사용하는 Java의 단순 HTTP 서버

HTTP 요청을 수동으로 구문 분석하고 HTTP 응답을 수동으로 형식화하는 코드를 작성하지 않고 Java SE API 만 사용하여 Java에서 매우 기본적인 HTTP 서버 (GET / POST 만 지원)를 작성하는 방법이 있습니까? Java SE API는 HttpURLConnection의 HTTP 클라이언트 기능을 훌륭하게 캡슐화하지만 HTTP 서버 기능에 대한 아날로그가 있습니까?

분명히 내가 온라인에서 본 많은 ServerSocket 예제의 문제점은 지루하고 오류가 발생하기 쉽고 포괄적이지 않을 수있는 자체 요청 구문 분석 / 응답 형식 지정 및 오류 처리를 수행한다는 것입니다. 나는 그런 이유로 그것을 피하려고 노력하고 있습니다.

내가 피하려고하는 수동 HTTP 조작의 예 :

http://java.sun.com/developer/technicalArticles/Networking/Webserver/WebServercode.html



답변

Java SE 6부터 Sun Oracle JRE 에 내장 HTTP 서버가 있습니다. com.sun.net.httpserver패키지의 개요는 침범 된 클래스를 설명하고 예제가 포함되어 있습니다.

다음 은 문서에서 복사하여 붙여 넣은 시작 예입니다 (그럼에도 불구하고 편집하려고하는 모든 사람들에게) 원본에서). Java 6 이상에서 복사하여 붙여 넣기를 실행할 수 있습니다.

package com.stackoverflow.q3732109;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class Test {

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
        server.createContext("/test", new MyHandler());
        server.setExecutor(null); // creates a default executor
        server.start();
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            String response = "This is the response";
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }

}

response.length()그들의 예 에서 부분이 나쁘다는 것을 주목해야한다 response.getBytes().length. 그럼에도 불구하고 getBytes()메소드는 명시 적으로 문자 세트를 지정해야하며 응답 헤더에 지정해야합니다. 아아, 초보자에게는 오해가 있지만 결국 기본적인 킥오프 예제입니다.

그것을 실행하고 http : // localhost : 8000 / test 로 이동 하면 다음과 같은 응답이 나타납니다.

이것은 응답입니다


com.sun.*클래스 사용과 관련하여 이는 일부 개발자의 생각과 달리 잘 알려진 FAQ에서 개발자가 ‘sun’패키지를 호출하는 프로그램을 작성해서는 안되는 이유 는 절대로 금지하지 않습니다 . 이 FAQ는 sun.*패키지가 sun.misc.BASE64Encoder아닌 Oracle JRE의 내부 사용을위한 패키지 (예 :)와 관련이 있습니다 (따라서 다른 JRE에서 실행할 때 응용 프로그램이 종료 됨) com.sun.*. Sun / Oracle은 Apache 등과 같은 다른 모든 회사와 마찬가지로 Java SE API 자체에서 소프트웨어를 개발하기 만합니다. GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl) 등과 같은 특정 Java API 구현com.sun.*관련 하여 클래스를 사용하는 것은 권장되지 않지만 금지되지는 않습니다 .


답변

NanoHttpd를 확인하십시오

“NanoHTTPD는 Modified BSD 라이센스하에 릴리스 된 다른 응용 프로그램에 포함되도록 설계된 경량 HTTP 서버입니다.

Github에서 개발 중이며 빌드 및 유닛 테스트에 Apache Maven을 사용합니다. “


답변

com.sun.net.httpserver의의 솔루션은 JRE에 걸쳐 이식 할 수 없습니다. javax.xml.ws 의 공식 웹 서비스 API를 사용하여 최소한의 HTTP 서버를 부트 스트랩하는 것이 좋습니다 …

import java.io._
import javax.xml.ws._
import javax.xml.ws.http._
import javax.xml.transform._
import javax.xml.transform.stream._

@WebServiceProvider
@ServiceMode(value=Service.Mode.PAYLOAD)
class P extends Provider[Source] {
  def invoke(source: Source) = new StreamSource( new StringReader("<p>Hello There!</p>"));
}

val address = "http://127.0.0.1:8080/"
Endpoint.create(HTTPBinding.HTTP_BINDING, new P()).publish(address)

println("Service running at "+address)
println("Type [CTRL]+[C] to quit!")

Thread.sleep(Long.MaxValue)

편집 : 이것은 실제로 작동합니다! 위의 코드는 Groovy 또는 다른 것 같습니다. 테스트 한 Java 로의 번역은 다음과 같습니다.

import java.io.*;
import javax.xml.ws.*;
import javax.xml.ws.http.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

@WebServiceProvider
@ServiceMode(value = Service.Mode.PAYLOAD)
public class Server implements Provider<Source> {

    public Source invoke(Source request) {
        return  new StreamSource(new StringReader("<p>Hello There!</p>"));
    }

    public static void main(String[] args) throws InterruptedException {

        String address = "http://127.0.0.1:8080/";
        Endpoint.create(HTTPBinding.HTTP_BINDING, new Server()).publish(address);

        System.out.println("Service running at " + address);
        System.out.println("Type [CTRL]+[C] to quit!");

        Thread.sleep(Long.MAX_VALUE);
    }
}


답변

이 질문은 지속적인 혁신이 진행되는 영역이며 특히 소형 장치의 내장 서버에 대해 이야기 할 때 항상 가벼운 서버가 필요하기 때문에이 질문이 마음에 듭니다. 답은 두 가지 그룹으로 나뉜다 고 생각합니다.

  1. Thin-server : 최소한의 처리, 컨텍스트 또는 세션 처리로 서버 업 정적 컨텐츠.
  2. 작은 서버 : 표면 상으로는 작은 공간을 차지하는 httpD와 유사한 서버 품질이 많이 있습니다.

Jetty , Apache Http Components , Netty 및 기타와 같은 HTTP 라이브러리 는 원시 HTTP 처리 기능과 비슷하다고 생각할 수 있습니다. 라벨링은 매우 주관적이며 소규모 사이트에 제공하기 위해 전화를 한 종류에 따라 다릅니다. 나는 질문의 정신, 특히 다음에 대한 언급 에서이 구별을합니다 …

  • “… 수동으로 HTTP 요청을 구문 분석하고 HTTP 응답의 형식을 지정하는 코드를 작성하지 않고 …”

이 원시 도구를 사용하면 다른 답변에서 설명한 것처럼 그렇게 할 수 있습니다. 그들은 실제로 소형, 내장형 또는 소형 서버를 만들 준비가 된 스타일에 적합하지 않습니다. 미니 서버는 종소리와 휘파람, 볼륨이 적고 성능이 99 % 인 풀 기능 웹 서버 (예 : Tomcat 등 ) 와 유사한 기능을 제공 할 수있는 기능 입니다. 씬 서버는 원래의 문구에 더 가깝게 보일 것입니다. 아마도 제한된 하위 집합 기능을 사용하여 시간의 90 %를 멋지게 보일 수 있습니다. 생생한 아이디어는 추가 디자인과 코딩 없이도 시간의 75 %-89 %를 멋지게 보이게하는 것입니다. WAR 파일 수준에 도달하면 큰 서버가 작게 만드는 모든 것 같은 Bonsi 서버에 대해 “작은”상태를 유지했다고 생각합니다.

씬 서버 옵션

미니 서버 옵션 :

  • Spark Java … 필터, 템플릿 등과 같은 많은 도우미 구성으로 좋은 일이 가능합니다.
  • MadVoc … 분재를 목표로하고 잘 될 수 있습니다 😉

고려해야 할 사항 중에는 FreeMaker 또는 기타 템플릿 도구를 사용하여 페이지 출력을 렌더링하는 인증, 유효성 검사, 국제화가 포함됩니다 . 그렇지 않으면 HTML 편집 및 매개 변수화를 관리하면 HTTP 작업이 noughts-n-crosses처럼 보일 수 있습니다. 당연히 모든 것이 얼마나 유연해야하는지에 달려 있습니다. 메뉴 방식의 팩스 기기라면 매우 간단 할 수 있습니다. 상호 작용이 많을수록 프레임 워크가 ‘ 두꺼워 ‘져야합니다. 좋은 질문, 행운을 빌어 요!


답변

“Jetty”웹 서버 Jetty를 살펴보십시오 . 모든 요구 사항을 충족하는 것처럼 보이는 훌륭한 오픈 소스 소프트웨어입니다.

당신이 자신의 롤링을 주장한다면 “httpMessage”클래스를 살펴보십시오.


답변

옛날 옛적에 나는 쉽게 포함하고 사용자 정의 할 수있는 가볍지 만 완전한 기능을 갖춘 HTTP 서버와 비슷한 것을 찾고있었습니다. 두 가지 유형의 잠재적 솔루션을 찾았습니다.

  • 가볍거나 단순하지 않은 전체 서버 (가벼운 정의를 위해)
  • HTTP 서버는 아니지만 실제로는 RFC 호환이 아니며 일반적으로 필요한 기본 기능을 지원하지 않는 영광스러운 ServerSocket 예제입니다.

그래서 … 나는 JLHTTP-자바 경량 HTTP 서버 를 쓰기 시작했다 .

하나의 (아주 긴 경우) 소스 파일 또는 종속성이없는 ~ 50K jar (~ 35K stripped)으로 모든 프로젝트에 포함 할 수 있습니다. RFC를 준수하기 위해 노력하고 있으며 부풀림을 최소화하면서 광범위한 문서와 많은 유용한 기능을 포함합니다.

가상 호스트, 디스크에서 파일 제공, 표준 mime.types 파일을 통한 MIME 유형 맵핑, 디렉토리 색인 생성, 환영 파일, 모든 HTTP 메소드 지원, 조건부 ETag 및 If- * 헤더 지원, 청크 분할 전송 인코딩, gzip / deflate 압축, 기본 HTTPS (JVM에서 제공), 부분 컨텐츠 (다운로드 계속), 파일 업로드를위한 다중 파트 / 양식-데이터 처리, API 또는 주석을 통한 다중 컨텍스트 핸들러, 매개 변수 구문 분석 (쿼리 문자열 또는 x-www-form-urlencoded 바디) 등

다른 사람들이 유용하다고 생각하기를 바랍니다 🙂


답변