JDK6のHttpServerで簡単なWebサーバーを作る

日付があしただけど気にするな。
(今は11/23)


JDK6にHTTPサーバークラスが用意されてるということで、これを使って静的ファイル専用の簡単なWebサーバー作ってみました。

package webserver;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

public class SimpleWebServer {
    private static final int PORT = 8880;
    private static final String DOCUMENT_ROOT =
            "C:\\Users\\kishida\\Documents\\web";

    public static void main(String[] args) throws IOException{
        //contenttypeを登録しておく
        final Map<String, String> contentTypes = new HashMap<String, String>();
        contentTypes.put("html", "text/html");
        contentTypes.put("jpg", "image/jpeg");
        contentTypes.put("png", "image/png");
        contentTypes.put("gif", "image/gif");
        contentTypes.put("css", "text/css");
        
        //ドキュメントルート
        final File root = new File(DOCUMENT_ROOT);

        //サーバー準備
        HttpServer server = HttpServer.create(
                new InetSocketAddress("localhost", PORT), 0);

        //応答処理
        server.createContext("/", new HttpHandler() {
            public void handle(HttpExchange he) throws IOException {
                String path = he.getRequestURI().getPath();
                File f = new File(root, path);
                if(!f.exists()){
                    //ファイルがない
                    he.sendResponseHeaders(404, 0);
                    sendMessage(he.getResponseBody(), "not found.");
                    return;
                }
                if(f.isDirectory()){
                    File indexFile = new File(f, "index.html");
                    if(!indexFile.exists()){
                        //ディレクトリは見れない
                        he.sendResponseHeaders(403, 0);
                        sendMessage(he.getResponseBody(), "fobbiden.");
                        return;
                    }
                    f = indexFile;
                }

                int idx = path.lastIndexOf(".");
                if(idx >= 0){
                    //拡張子からmimeタイプを出力
                    String ext = path.substring(idx + 1);
                    if(contentTypes.containsKey(ext)){
                        he.getResponseHeaders().add(
                                "Content-Type", contentTypes.get(ext));
                    }
                }

                he.sendResponseHeaders(200, f.length());
                //ファイル内容を返す
                InputStream is = new FileInputStream(f);
                OutputStream res = he.getResponseBody();
                try{
                    byte[] buf = new byte[1024];
                    int len;
                    while((len = is.read(buf)) >= 0){
                        res.write(buf, 0, len);
                    }
                }finally{
                    res.close();
                    is.close();
                }
            }
        });
        server.start();
    }

    private static void sendMessage(OutputStream res, String message) throws IOException{
        try{
            PrintWriter pw = new PrintWriter(res);
            pw.println(message);
            pw.close();
        }finally{
            res.close();
        }
    }
}


これだけです。
結構まともに動くので笑ってしまいます。
Socketを直接使うのにくらべて、ヘッダーの扱いなんかをやってくれるのが楽です。HTTPプロトコルを調べる必要がありません。