java Spring 5 새로운 기능 함수식 웹 프레임워크 상세 소개
예를 들다
우리는 먼저 예시 응용 프로그램의 일부 발췌문부터 시작한다.다음은 노출된 Person 객체의 응답 정보 라이브러리입니다.전통적인 비응답 정보 라이브러리와 유사하지만 Flux
public interface PersonRepository {
Mono<Person> getPerson(int id);
Flux<Person> allPeople();
Mono<Void> savePerson(Mono<Person> person);
}
다음은 우리가 어떻게 새로운 함수식 웹 프레임워크를 가진 자원 라이브러리를 폭로하는가이다.
RouterFunction<?> route = route(GET("/person/{id}"),
request -> {
Mono<Person> person = Mono.justOrEmpty(request.pathVariable("id"))
.map(Integer::valueOf)
.then(repository::getPerson);
return Response.ok().body(fromPublisher(person, Person.class));
})
.and(route(GET("/person"),
request -> {
Flux<Person> people = repository.allPeople();
return Response.ok().body(fromPublisher(people, Person.class));
}))
.and(route(POST("/person"),
request -> {
Mono<Person> person = request.body(toMono(Person.class));
return Response.ok().build(repository.savePerson(person));
}));
다음은 Reactor Netty에서 실행되는 방법에 대해 설명합니다.
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
ReactorHttpHandlerAdapter adapter =
new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create("localhost", 8080);
server.startAndAwait(adapter);
마지막으로 해야 할 일은 한번 해 보는 것이다.
$ curl 'http://localhost:8080/person/1'
{"name":"John Doe","age":42}
다음은 더 많은 소개가 있습니다. 더 깊이 파헤쳐 봅시다! 핵심 구성 요소
핵심 구성 요소에 대한 철저한 설명을 통해 프레임워크를 소개합니다: HandlerFunction, RouterFunction, 그리고 FilterFunction.이 세 개의 인터페이스와 글에서 기술한 모든 다른 유형은 org에서 사용할 수 있다.springframework.web.reactive.기능 패키지에서 찾았습니다.
HandlerFunction
이 새로운 프레임워크의 출발점은 HandlerFunction
다음은 간단한 "Hello World"처리 함수의 예입니다. 200상태와 body가 String인 응답 메시지를 되돌려줍니다.
HandlerFunction<String> helloWorld =
request -> Response.ok().body(fromObject("Hello World"));
위의 예에서 보듯이 처리 함수는 Reactor에 구축된 기초 위에서 완전한 응답을 한다. 이것은 Flux, Mono, 또는 그 어떠한 상응하는 흐름 Publisher를 응답 형식으로 받아들인다.주의해야 할 점은 HandlerFunction 자체는 부작용이 없습니다. 응답을 매개 변수로 삼지 않기 때문입니다. (Servlet.service (Servlet Request, Servlet Response 참조) 이것은 실질적으로 BiConsumer
RouterFunction
전송된 요청은 RouterFunction
다음은 내장 처리 함수가 있는 루트 함수의 예이다.그것은 좀 지루해 보이지만, 걱정하지 마라. 우리는 그것을 짧게 할 방법을 찾을 것이다.
RouterFunction<String> helloWorldRoute =
request -> {
if (request.path().equals("/hello-world")) {
return Optional.of(r -> Response.ok().body(fromObject("Hello World")));
} else {
return Optional.empty();
}
};
일반적으로 전체 라우팅 방법을 쓰지 않고 RouterFunctions를 정적으로 도입합니다.route (), 이렇게 하면 요청 판단식 (Request Predicate) (즉 Predicate
RouterFunction<String> helloWorldRoute =
RouterFunctions.route(request -> request.path().equals("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")));
RequestPredicates를 (정적으로) 가져올 수 있습니다.*경로, HTTP 방법, 컨텐츠 유형 등을 기준으로 자주 사용되는 용어에 액세스합니다.이를 통해 Hello World Route를 더욱 간단하게 만들 수 있습니다.
RouterFunction<String> helloWorldRoute =
RouterFunctions.route(RequestPredicates.path("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")));
조합 함수두 개의 루트 함수는 하나의 처리 함수로 새로운 루트 함수를 구성할 수 있습니다. 첫 번째 함수가 일치하지 않으면 두 번째 함수를 실행합니다.너는 RouterFunction을 호출할 수 있다.and(), 다음과 같이 두 라우팅 함수를 조합합니다.
RouterFunction<?> route =
route(path("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")))
.and(route(path("/the-answer"),
request -> Response.ok().body(fromObject("42"))));
경로가/hello-world와 일치하면 "Hello World"에 응답하고,/the-answer와 일치하면 "42"로 되돌아옵니다.둘 다 일치하지 않으면 빈 Optional을 반환합니다.조합된 루트 함수는 순서대로 실행되기 때문에 구체적인 함수 전에 범용 함수를 넣는 것은 의미가 있습니다.너도 요구 술어를 조합해서 and나 or를 호출할 수 있다.작업 방식은 다음과 같다. and에 대해 두 개의 주어진 술어가 일치하면 결과의 술어가 일치하고, 두 개의 술어가 일치하면 or가 일치한다.예:
RouterFunction<?> route =
route(method(HttpMethod.GET).and(path("/hello-world")),
request -> Response.ok().body(fromObject("Hello World")))
.and(route(method(HttpMethod.GET).and(path("/the-answer")),
request -> Response.ok().body(fromObject("42"))));
사실 Request Predicates에서 발견된 대부분의 술어는 조합된 것입니다!예를 들어, RequestPredicates.GET(String)는 RequestPredicates입니다.method(HttpMethod) 및 RequestPredicates.path(String)의 구성요소입니다.따라서 위의 코드는 다음과 같이 다시 쓸 수 있습니다.
RouterFunction<?> route =
route(GET("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")))
.and(route(GET("/the-answer"),
request -> Response.ok().body(fromObject(42))));
메소드 참조참고로 지금까지 우리는 모든 처리 함수를 내연의 lambda 표현식으로 작성했다.비록 이것은 시범과 짧은 예에서 양호하지만, 이것은'혼란'을 초래할 수 있는 경향이 있다. 왜냐하면 두 가지 우려를 혼합해야 하기 때문이다. 바로 요청 루트와 요청 처리이다.그래서 우리는 일을 더욱 간결하게 할 수 있는지를 보아야 한다.먼저 처리 코드를 포함하는 클래스를 만듭니다.
class DemoHandler {
public Response<String> helloWorld(Request request) {
return Response.ok().body(fromObject("Hello World"));
}
/* http://www.manongjc.com/article/1590.html */
public Response<String> theAnswer(Request request) {
return Response.ok().body(fromObject("42"));
}
}
두 방법 모두 처리 함수를 호환하는 표지가 있으니 주의하십시오.이렇게 하면 메서드를 참조할 수 있습니다.
DemoHandler handler = new DemoHandler(); // or obtain via DI
RouterFunction<?> route =
route(GET("/hello-world"), handler::helloWorld)
.and(route(GET("/the-answer"), handler::theAnswer));
FilterFunction라우팅 함수에 의해 매핑된 경로는 RouterFunction을 호출할 수 있습니다.Filter(Function
// http://www.manongjc.com
RouterFunction<?> route =
route(GET("/hello-world"), handler::helloWorld)
.and(route(GET("/the-answer"), handler::theAnswer))
.filter((request, next) -> {
System.out.println("Before handler invocation: " + request.path());
Response<?> response = next.handle(request);
Object body = response.body();
System.out.println("After handler invocation: " + body);
return response;
});
주의해야 할 것은 다음 프로세서를 호출할지 말지는 선택할 수 있다는 것이다.이것은 보안과 캐시 방안에서 매우 유용합니다. (예를 들어 사용자가 충분한 권한이 있을 때만 넥스트를 호출합니다.)루트는 무한 루트 함수이기 때문에, 다음 처리 프로그램이 어떤 종류의 응답 정보를 되돌려줄지 알고 있습니다.이것이 바로 우리가 최종적으로 우리의 필터에 Response 를 사용하는 이유이다끝내고 Object로 body에 응답하는 이유.처리 프로그램 클래스에서 두 가지 방법은 모두 Response < String > 로 되돌아오기 때문에 String 응답 주체가 있을 수 있습니다.우리는 RouterFunction을 사용할 수 있습니다.andSame () 를 사용하여 and () 를 대신합니다.이런 조합 방법은 매개 변수 루트 함수가 같은 유형이어야 한다.예를 들어, 우리는 모든 응답을 대문자로 만들 수 있다.
RouterFunction<String> route =
route(GET("/hello-world"), handler::helloWorld)
.andSame(route(GET("/the-answer"), handler::theAnswer))
.filter((request, next) -> {
Response<String> response = next.handle(request);
String newBody = response.body().toUpperCase();
return Response.from(response).body(fromObject(newBody));
});
메모를 사용하면 @ControllerAdvice 및/또는 ServletFilter 와 같은 기능을 사용할 수 있습니다.서버 실행
이 모든 것이 다 좋은데, 한 가지 잊어버린 것이 있다. 우리는 어떻게 해야만 실제 HTTP 서버에서 이 함수를 실행할 수 있습니까?답안은 다른 함수를 호출하는 것을 의심할 필요가 없다.너는 Router Functions를 사용할 수 있다.toHttpHandler()는 라우팅 함수를 HttpHandler로 변환합니다.HttpHandler는 Spring 5.0 M1에 도입된 응답 추상화입니다. 다양한 응답 실행 시 Reactor Netty, Rx Netty, Servlet 3.1+, Undertow를 실행할 수 있습니다.이 예에서, 우리는 Reactor Netty에서route를 실행하는 것이 어떤지 이미 보여 주었다.Tomcat의 경우 다음과 같이 보입니다.
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
Tomcat server = new Tomcat();
Context rootContext = server.addContext("",
System.getProperty("java.io.tmpdir"));
Tomcat.addServlet(rootContext, "servlet", servlet);
rootContext.addServletMapping("/", "servlet");
tomcatServer.start();
한 가지 주의해야 할 것은 위의 코드는 Spring 응용 프로그램의 상하문에 의존하지 않는다는 것이다.JdbcTemplate와 다른 Spring 유틸리티 클래스와 같이 응용 프로그램의 상하문을 사용하면 선택할 수 있습니다. 상하문에서 처리 프로그램과 루트 함수를 연결할 수 있지만 필요하지 않습니다.또한 Dispatcher Handler에서 실행할 수 있도록 Handler Mapping으로 라우팅 함수를 변환할 수도 있습니다. (응답이 필요한 @Controllers가 필요할 수도 있습니다.)
결론
간단한 요약을 통해 결론을 내리겠습니다.
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 기반 Spring 5 의 핵심 중 하나 인 IOC 용기4.Spring 은 IOC 용 기 를 제공 하여 두 가지 방식 을 실현 합 니 다.(두 개의 인터페이스) (1)BeanFactory:IOC 용 기 는 기본적으로 구현 되 며 Spring 내부 의 사용 인터페이스 로 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.