URL url = new URL("http://www.oreilly.com/"); try (InputStream in = url.openStream()) { Files.copy(in, Paths.get("output.txt")); } catch(IOException ex) { ex.printStackTrace(); }이 코드 조각은 현재 HTTP 클라이언트를 구현하는 가장 간단한 방법이다. 불행하게도, 긍정적인 부분만 있는 것은 아니다. 만약 HTTP 연결에 대해 다른 것들을 더 조절하고 싶다면(예를 들어, HTTP 데이터와 헤더를 모두 살펴보는 등), 아래와 같이 구현할 수 있다:
try { URLConnection conn = url.openConnection(); String type = conn.getContentType(); String encoding = conn.getContentEncoding(); Date lastModified = new Date(conn.getLastModified()); int len = conn.getContentLength(); InputStream in = conn.getInputStream(); } catch (IOException e) { // Handle exception }이 경우, URLConnection 클래스가 AutoCloseable 인터페이스를 구현하지 않아서 URLConnection 타입의 변수들은 try-with-resources 구분을 사용할 수 없다. 때문에 HTTP 처리가 개선되어도 우리가 좋아할 정도로 상황이 개선되지는 않았다. 그 사이의 많은 시간 동안, 자바 개발자들은 Apache 같은 곳에서 제공하는 다른 HTTP 라이브러리들을 사용하기 시작했다. 이러한 라이브러리들은 어떤 부분에서는 더 훌륭했으나, 그것들도 완벽하지는 않았다. 그리고 - 이 포스트를 쓰는 현재까지는 - 아무 것도 Java 8 기능의 (람다와 같은) 장점을 활용하지 못하고 있다.
@Path("session") @Produces("application/json") public class SessionService { private static final Logger logger = LoggerFactory.getLogger(SessionService.class); @POST @Consumes("application/json") public Response createSession(AuthData auth) { long start = System.currentTimeMillis(); logger.info("Incoming: " + auth); final Session session = validate(auth); if (session == null) { return Response.notAcceptable(null).build(); } long end = System.currentTimeMillis(); logger.info("Request took: " + (end - start) + " ms"); return Response.ok(session).build(); } public Session validate(AuthData auth) { if (auth == null) { return null; } // Other validation return new Session(auth); } }어노테이션들은 명확해 보인다 - 이것은 애플리케이션 (혹은 WAR 파일의) 루트의 하위 디렉토리인 session에 존재하는 웹 서비스이다. 이것은 JSON 데이터를 생성(송신)하기도 하고, 사용(수진)하기도 하며, HTTP POST 방식으로 데이터를 받는다고 가정한다. 여기에는 자바 객체를 JSON으로 매핑하기 위한 비밀의 마법 같은 것이 있으나, 이 매퍼들은 상대적으로 사용하고 설정하는 것이 직관적이다.
ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine e = m.getEngineByName("nashorn"); try { e.eval("print("Hello World!");"); } catch (ScriptException se) { // ... Handle exception }이 예제는 Java 6에서 소개된 스크립트 엔진 메커니즘을 사용한다. 하지만 자바스크립트의 REPL(Read-Eval-Print-Loop)을 콘솔에서 실행할 수 있기 때문에, Nashorn을 바로 실험해볼 수 있다. 만약 Java 8이 설치되어 있고, path 설정에 JAVA_HOME의 bin 디렉토리가 포함되어 있다면, jjs라고 치면 REPL이 나타날 것이다:
jjs> print("Hello World!"); Hello World!이것은 잘 동작하지만, 너무 간단한 예제다. 좀 더 복잡한 예제를 통해 자바와의 통합이 어떻게 동작하는지 알아보자. 실제로는, 자바스크립트 함수는 람다 표현식과 같이 다루어진다. 그래서 이렇게 코드를 작성할 수 있다:
jjs> var clz = Java.type("java.util.concurrent.Callable"); jjs> var obj = new clz(function () { print("Foo"); } ); jjs> obj.call(); Foo그렇다 - 우리는 자바스크립트 함수를 람다 표현식처럼 다룰 수 있는데, 이 람다 표현식은 Callable로 자동으로 변환이 가능하다. 그래서 우리는 결과 객체에 있는 call 메소드를 사용할 수 있다.
jjs> var me = JSON.parse("{"name":"Ben Evans", "details":{"dob":"1976-05-21", "gender":"Male"}}"); jjs> print(me.name); Ben Evans jjs> print(JSON.stringify(me)); {"name":"Ben Evans","details":{"dob":"1976-05-21","gender":"Male"}}게다가 Nashorn이 Java 8에서 구현되는 동안, 2013년 5월에 배포되어 EE 7에 포함된 (하지만 SE 8의 표준은 되지 못한) JSR 353이 만들어지고 있었다. Java 9은 JSON을 다루는 새롭고 매우 효율적인 API를 제공함으로써 이것을 개선시키고 싶어한다. 오라클은 새로운 JSON API가 JSR 353에서 최우선적으로 구현될지 여부는 발표하지 않았지만, 그 사이에, 여기에 새로운 API를 위한 JEP 페이지가 여기 생겼다: http://openjdk.java.net/jeps/198; 관련된 토론은 OpenJDK core libraries 메일링에서 찾아볼 수 있다.
최신 콘텐츠