Java 6 has a web server inside

import com.sun.net.httpserver.*

class ExampleHandler implements HttpHandler {
        void handle(HttpExchange exchange) throws IOException {
                def response = "Hello, world!"

                exchange.sendResponseHeaders(200, response.length());
                def outout = exchange.responseBody
                outout.write(response.bytes);
                outout.close();
        }
}

public class ExampleAuthenticator extends BasicAuthenticator {
        static users = [ "john": "john123" ]
 
        public ExampleAuthenticator(String realm) {
                super(realm);
        }

        @Override
        public boolean checkCredentials(String username, String password) {
                return users[username] == password;
        }
}

def server = HttpServer.create(new InetSocketAddress(8000), 0);
def context = server.createContext("/example", new ExampleHandler());
context.authenticator = new ExampleAuthenticator("Example application")
server.executor = null
server.start();

 

Java 7 w jednej krótkiej lekcji

Program w Java 6 (przed zmianami)

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class Test1 {

        static void usage() {
                System.out.println("Usage: <input file>");
        }

        public static void main(String[] args) {
                if (args.length == 0) {
                        usage();
                        return;
                }
        
                for (String i : args) {
                        if (i.equals("-help") || i.equals("--help") || i.equals("-h")) {
                                usage();
                                return;
                        }
                        else if (i.equals("-version") || i.equals("--version") || i.equals("-v")) {
                                System.out.println("Version 1.0  Public Domain");
                                return;
                        }
                        else {
                                if (i.startsWith("-")) {
                                        System.out.println("Unknown argument: " + i);
                                        System.exit(1);
                                }
                        }
                }
                
                BufferedReader reader = null;
                File file = new File(args[0]);
                try {
                        reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
                        String line;
                        while ((line = reader.readLine()) != null) {
                                URI uri = new URI(line);
                                System.out.println(uri.getHost());
                        }
                }
                catch (IOException exception) {
                        exception.printStackTrace();
                }
                catch (URISyntaxException exception) {
                        exception.printStackTrace();
                }
                finally {
                        if (reader != null) {
                                try {
                                        reader.close();
                                }
                                catch (IOException exception) {
                                        exception.printStackTrace();
                                }
                        }
                }
        }

}

String-in-switch

Na rozgrzewkę można zastąpić wszystkie if/else pojedynczym switch/case (dobre IDE zrobi to za Ciebie). Switch dla Stringów działa dokładnie tak jak się tego spodziewamy. Jedyne na co trzeba uważać, to “i” z wartością null, które spowoduje (uwaga: niespodzianka) NullPointerException 🙂

for (String i : args) {
                        switch (i) {
                                case "-help":
                                case "--help":
                                case "-h":
                                        usage();
                                        return;
                                case "-version":
                                case "--version":
                                case "-v":
                                        System.out.println("Version 1.0  Public Domain");
                                        return;
                                default:
                                        if (i.startsWith("-")) {
                                                System.out.println("Unknown argument: " + i);
                                                System.exit(1);
                                        }
                        }
                }

AutoCloseable

Zawsze warto pamiętać o zamykaniu wszystkich nieużywanych “streamów” i innych zasobów systemowych. Od wersji 7 wszystkie autozamykalne obiekty można umieścić w jednej składni try (). Kompilator sam doda niewidzialny blok “finally”, który wywoła odpowiednią metodę “close”.

- BufferedReader reader = null;
                File file = new File(args[0]);
                + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"))) {
                        - reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
                        String line;
                        while ((line = reader.readLine()) != null) {
                                URI uri = new URI(line);
                                System.out.println(uri.getHost());
                        }
                }
                catch (IOException exception) {
                        exception.printStackTrace();
                }
                catch (URISyntaxException exception) {
                        exception.printStackTrace();
                }
                - Sio! finally {
                        if (reader != null) {
                                try {
                                        reader.close();
                                }
                                catch (IOException exception) {
                                        exception.printStackTrace();
                                }
                        }
                }
        }

}

Multi-catch

Kolejną małą nowością jest możliwość łapania paru różnych wyjątków w jednym bloku. Typy wyjątków rozdziela się “|”. Zawsze to trochę mniej klepania i unikniemy pokusie łapania wszystkich pokemonów 😉

File file = new File(args[0]);
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"))) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                                URI uri = new URI(line);
                                System.out.println(uri.getHost());
                        }
                }
                catch (IOException | URISyntaxException exception) {
                        exception.printStackTrace();
                }
                - catch (URISyntaxException exception) {
                        exception.printStackTrace();
                }
        }

}

Nowe New IO

Po zmianach powyższy kod wygląda trochę lepiej, ale obsługa IO nadal ssie… new BufferedReader(new InputStreamReader wygląda strasznie paskudnie. Na szczęście z pomocą przychodzi java.nio.file z licznymi udogodnieniami.

+ import java.nio.charset.StandardCharsets;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.nio.file.Paths;


                - File file = new File(args[0]);
                + Path file = Paths.get(args[0]);
                // Path file = new File(args[0]).toPath(); // wersja dla leniwców
                try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                                URI uri = new URI(line);
                                System.out.println(uri.getHost());
                        }
                }
                catch (IOException | URISyntaxException exception) {
                        exception.printStackTrace();
                }
        }

}

Files.readAllLines

W ramach bonusu, dużo krótsza (i pewnie mniej optymalna przy dużych plikach) metoda wczytywania tekstu:

Path file = Paths.get(args[0]);
                - try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                + try {
                        for (String line : Files.readAllLines(file, StandardCharsets.UTF_8)) {
                                URI uri = new URI(line);
                                System.out.println(uri.getHost());
                        }
                }
                catch (IOException | URISyntaxException exception) {
                        exception.printStackTrace();
                }
        }

}

Program w Java 7

Teraz nasz program wygląda pięknie… I na koniec współczujemy wszystkim użytkownikom JDK 1.4, 1.5 i 1.6 😛

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.net.URI;
import java.net.URISyntaxException;

public class Test6 {

        static void usage() {
                System.out.println("Usage: <input file>");
        }

        public static void main(String[] args) {
                if (args.length == 0) {
                        usage();
                        return;
                }
        
                for (String i : args) {
                        switch (i) {
                                case "-help":
                                case "--help":
                                case "-h":
                                        usage();
                                        return;
                                case "-version":
                                case "--version":
                                case "-v":
                                        System.out.println("Version 1.0  Public Domain");
                                        return;
                                default:
                                        if (i.startsWith("-")) {
                                                System.out.println("Unknown argument: " + i);
                                                System.exit(1);
                                        }
                        }
                }
                
                Path file = Paths.get(args[0]);
                try {
                        for (String line : Files.readAllLines(file, StandardCharsets.UTF_8)) {
                                URI uri = new URI(line);
                                System.out.println(uri.getHost());
                        }
                }
                catch (IOException | URISyntaxException exception) {
                        exception.printStackTrace();
                }
        }

}

*) Nie interesuje nas Scala.