API 요약
이 장은 API 표면 전체를 나열하며, 각 항목은 해당 내용을 설명하는 장을 가리킨다.
공개된 모든 패키지는 JSpecify로 @NullMarked되어 있으므로, 시그니처에 @Nullable이 명시되지 않은 한 파라미터나 반환값은 null을 배제한다.
NullAway나 IntelliJ IDEA처럼 JSpecify를 읽는 도구는 non-null 파라미터에 도달하는 null을 보고한다.
App이 제공하는 것
-
라우트:
get,post,put,patch,delete,head,options, 각각(path, description, handler)형태로도 제공되며,path(prefix, group → …)가 있다; 패턴과 매칭 순서는 라우팅에서 다룬다 -
인트로스펙션:
routes()는 등록된 모든 라우트를Route(method, path, description)로 등록 순서대로 보고한다.hooks()는 그 곁에서 동작하는 필터와 상태 페이지를Hook.BeforeRequest(path),Hook.BeforeRoute(path),Hook.AfterRoute(path),Hook.StatusPage(status),Hook.EveryResponse()로 보고한다.spider-silk-openapi는 라우트 목록을 OpenAPI 3.1 문서로 바꾼다 -
필터: 라우팅 전의
beforeRequest(filter)/beforeRequest(path, filter),beforeRoute(filter)/beforeRoute(path, filter), 같은 형태의afterRoute, 그리고 after 필터가 보지 못하는 응답까지 포함해 모든 응답에 적용되는responseFilter(filter) -
로깅:
requestLogger((request, completion) → …),RequestCompletion에는 서블릿 상태, 경과 시간, 응답 정의, 전송 실패, 그리고 요청에 응답하게 된 예외가 담긴다; 요청 로깅을 참고한다 -
에러:
exception(Type, handler), 등록된 타입 중 가장 구체적인 것이 이기고HttpException은 자신의 타입이나 하위 타입의 핸들러에만 도달한다,statusPage(HttpStatus, handler) -
응답 전반에 걸친 관심사:
cors(Cors),gzip()/gzip(Gzip),securityHeaders()/securityHeaders(SecurityHeaders). 각각은 호출하기 전까지 꺼져 있고, 정적 파일과 에러를 포함한 모든 응답에 적용되므로 필터가 아니다; CORS, 압축, 보안을 참고한다 -
본문 한도:
bodyLimits(BodyLimits)이며,BodyLimits.defaults()는body()에 1MB,bodyNdjson의 한 줄에 1MB를 두고,BodyLimits.unlimited()는 둘 다 없앤다. 기본값은 호출하지 않아도 적용되며, 한도를 넘는 본문은 413으로 응답한다; 요청을 참고한다 -
렌더링과 자산:
templates(renderer),staticFiles(classpathRoot),staticFiles(StaticFiles…).classpath:/jte위의 jte와 루트의classpath:/public이 기본값이므로 둘 다 호출하지 않아도 된다.StaticFiles.classpath(root)는 클래스패스 루트를,StaticFiles.directory(path)는 디스크의 디렉터리를 제공하고, 한 번에 주어진 여러 루트는 순서대로 읽히며,precompressed()는 빌드가 남겨둔.br이나.gz형제 파일이 있으면 그 파일로 응답한다.FreeMarkerTemplates,HandlebarsTemplates,ThymeleafTemplates는 각자의 모듈에 있는TemplateRenderer구현체다 -
서버:
start()/start(port),stop(),join(),port(),server(factory). 어떤 방식으로 시작했든AppServlet이 애플리케이션을 서비스하는 동안 등록은 닫힌다: 그때 추가되는 라우트, 필터, 설정은IllegalStateException을 던지고,stop()이 등록을 다시 연다.Cors,Gzip,SecurityHeaders,StaticFiles,BodyLimits는 등록될 때 복사된다
WebRequest가 제공하는 것
-
요청 정보:
method(),path(),header(name), 반복된 헤더를 위한headers(name), 전체를 위한headers(),contentType(),queryString(),isSecure(),scheme(),host(),remoteAddress(), 그리고 서블릿 요청 자체를 위한raw().host()는 포트가 스킴의 기본값이 아닐 때 포트를 함께 담으므로,scheme(),host(),path()로 절대 URL을 다시 만들 수 있다 -
매칭된 라우트:
route(), 응답한Route로 그 패턴과 설명을 담는다; 라우팅 전과 매칭된 라우트가 없는 곳에서는 null이며, 라우트 인트로스펙션을 참고한다 -
경로 변수:
pathParam,pathParamLong,pathParamEnum, 그리고 그 밖의 타입을 위한pathParam(name, parser). 패턴이 선언한 적 없는 이름은 400이 아니라IllegalStateException을 던진다.\{name*}꼬리는 경로의 나머지를 슬래시까지 포함해 바인딩하고, 아무것도 매칭하지 않았을 때는""가 된다 -
파라미터:
param(없으면 400),paramOrNull(없으면 null),paramLong,paramBoolean(true또는false만),paramEnum, 각각 선택 파라미터를 위한(…, default)형태가 있다; 반복된 값을 위한params(name) -
그 밖의 타입:
param(name, parser)와param(name, parser, default), 파서는UUID::fromString이나LocalDate::parse같은Function<String, T>다.IllegalArgumentException이나DateTimeException을 던지는 파서는 파라미터 이름을 밝히며 400으로 응답한다 -
한 출처만:
queryParam(name)과formParam(name)은 값을 요구하며 없으면 400으로 응답한다.queryParamOrNull(name)과formParamOrNull(name)은 없으면 null을 반환한다. 파서 오버로드도(…, parser, default)형태로 기본값을 주지 않는 한 값을 요구한다 -
쿼리 대 폼:
queryParam,queryParams,formParam,formParams -
콘텐츠 협상:
accepts(types…)는 제시된 타입 중 호출자가 선호하는 타입으로 응답하고, 어느 것도 받지 않으면 406이다; 파싱된Accept헤더를 위한acceptedTypes() -
클라이언트가 보낸 쿠키:
cookie(name),cookies() -
본문:
body(),bodyJson(),bodyJson(reader)(리더가 거부하는 본문에는 400, 한도를 넘는 본문에는 413). 바이트는 한 번 읽어 보관하므로 모든 호출이 본문 전체를 답하며,bodyJson은 그 바이트를 도착한 그대로 파싱한다 -
멀티파트 업로드:
file(name)(없으면 400),fileOrNull(name)(없으면 null), 여러 파일을 담은 필드를 위한files(name), 그리고 컨테이너가 거부한 업로드에는 셋 모두 413이나 400.UploadedFile은fileName(),contentType(),size(),bytes(),text(),inputStream(),writeTo(path)를 제공한다 -
읽지 않은 본문:
bodyStream()과bodyReader()는 다른 라이브러리의 파서를 위해 본문을 넘겨주며, 둘 다 보관된 텍스트와 섞이지 않는다: 나중에 호출된 쪽이IllegalStateException을 던진다.bodyNdjson(reader)는 줄 단위로 구분된 JSON을 지연 읽기하고, 줄 번호를 밝히며 400으로 응답하거나, 한도를 넘는 줄에는 413으로 응답한다; 대용량 JSON과 NDJSON과 외부 JSON 바인딩을 참고한다 -
세션:
session()은WebSession을 돌려주며, 그get(key, Class<T>)는 지정한 타입으로 읽고 실패하면 그 줄에서 키와 두 타입을 밝히고,get(key)는 캐스트를 호출 지점에 맡기고,set(key, value)는 쓰고,remove(key)는 하나를 제거하고,invalidate()는 세션을 끝낸다 -
플래시:
flash(key, value), 리다이렉트 뒤의 요청에서flashed(key)로 정확히 한 번 읽히며, null 값은 세션 속성에서와 마찬가지로 키를 제거한다 -
에러:
statusPage(status, handler)핸들러 안의errorMessage()
WebResponse가 제공하는 것
-
본문:
html,text,rawJson(text),json(JsonValue),json(value, writer),bytes(contentType, data),template(name),template(name, model),stream(contentType, out → …),file(path),sse(stream → …),raw((req, res) → …) -
Model.of(…)는 `template(name, model)`이 받는 불변Model을 null 값을 담을 수 있는 항목 열 개까지로 만든다; 템플릿을 참고한다 -
model.with(key, value)는 항목 하나를 더한 모델을,model.asMap()은 렌더러를 위한 읽기 전용 맵을 답한다 -
jte-models가 생성한 메서드로 부르는 jte 템플릿은
html(templates.deck(deck).render())로 보낸다; 템플릿을 참고한다 -
file(path)는 콘텐츠 타입을 이름에서, 길이를 파일에서 읽는다. 읽을 수 있는 일반 파일이 아닌 경로는UncheckedIOException을 던지므로, 없는 파일에 대한 404는 핸들러가 직접 작성한다 -
값을 하나씩 쓰는 본문: 담아 두기에 너무 큰 배열을 위한
jsonArray(sink → …), 한 줄에 값 하나를 쓰는ndjson(sink → …). 둘 다 내부적으로는stream본문이며, 라이터는 핸들러 예외 처리 밖에서 실행된다. 싱크는JsonSink이며, 그write(value)와write(value, writer)는 각각 값 하나를 쓴다; 대용량 JSON과 NDJSON을 참고한다 -
상태:
empty(),empty(HttpStatus),noContent(),redirect(location),redirect(location, HttpStatus) -
덧붙이기:
status,header,withoutHeader(name),contentType,vary(field),attachment,body,cookie(name, value),cookie(name, value, maxAge),cookie(Cookie),expireCookie -
되읽기:
status(),header(name),headers(),cookies(),body(). 헤더 이름은 대소문자를 구분하지 않고 비교되며, 어떤 표기로 몇 번을 설정하든 한 필드는 하나의 값을 가진다. 두 번 보내야 하는 헤더는raw를 통해 쓴다; 헤더를 참고한다
body()의 형태와 람다 계열에 대해서는 응답을 참고한다.
net.benelog.silkjson이 제공하는 것
이 패키지는 코어가 그 위에 지어진 JSON 라이브러리인 silk-json의 것이다.
-
트리:
Json.object(),Json.array(),Json.parse(text),Json.parse(utf8), 그리고JsonObject,JsonArray,JsonPrimitive를 가진JsonValue; JSON을 참고한다 -
매핑:
JsonOutput을 상대로 하는 람다(value, out) → …`인 `JsonWriter<T>;JsonInput을 상대로 하는 람다인JsonReader<T>; 그리고 둘을 한꺼번에 가진JsonCodec<T>.JsonWriter.list,JsonWriter.tree,JsonReader.object,JsonReader.list,JsonReader.tree,JsonCodec.of,JsonCodec.list가 이들을 만든다.writer.toJson(value),writer.toJsonBytes(value),reader.fromJson(text),reader.fromJsonBytes(utf8)는 요청 밖에서 하나를 실행한다 -
JsonOutput:object(),array(),end(),name(key),put(key, …),putNull(key),value(…),nullValue(),values(strings),newline().JsonOutput.inMemory()는toBytes()와toJson()을, 또는length()와writeTo(stream)에 이은release()를 답하고,JsonOutput.to(stream)은flush()에서 버퍼를 보낸다 -
JsonInput:object(),array(),nextKey(),nextKeyIs(key),keyHead(),nextElement(),keyIs(key),key(),readString(),readLong(),readInt(),readDouble(),readFloat(),readNumber(),readOneOf(names),readBoolean(),readNull(),readValue(),readValueBytes(),skipValue(),end(),error(message), 그 바탕은JsonInput.of(utf8)이나JsonInput.of(text)다 -
JsonKey.of(name):put,name,keyIs를 위해 한 번만 인코딩한 멤버 이름 -
JsonKey.names(constants):put(key, name),value(name),readOneOf를 위해 한 번만 인코딩한 enum 상수 이름들 -
@JsonBound: 애너테이션이 붙은 타입이나 그것이 지명한 타입의 코덱을silk-json-processor가 컴파일 시점에<Type>Json.CODEC으로 생성한다; 생성되는 JSON 코덱을 참고한다