java Spring 5 새로운 기능 함수식 웹 프레임워크 상세 소개

java Spring 5 새로운 기능 함수식 웹 프레임워크
예를 들다
우리는 먼저 예시 응용 프로그램의 일부 발췌문부터 시작한다.다음은 노출된 Person 객체의 응답 정보 라이브러리입니다.전통적인 비응답 정보 라이브러리와 유사하지만 Flux, 전통적인 반환 List, 그리고 Mono으로 돌아가는 곳은 Person으로 돌아간다.Mono는 완료 ID로 사용됩니다. 저장이 완료된 시점을 나타냅니다.

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이다. 기본적으로 Function이다. 그 중에서 Request와 Response는 새로운 정의로 변함없는 인터페이스로 JDK-8 DSL의 최종 HTTP 메시지를 우호적으로 제공한다.Response 실체를 구축하는 것은 Response Entity에서 본 것과 매우 유사한 편리한 구축 도구이다.HandlerFunction 메모에 대응하는 방법은 @RequestMapping이 있는 방법입니다.
다음은 간단한 "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의 처리 함수(즉 Function>)로 라우팅되어 처리 함수에 일치합니다.그렇지 않으면 빈 결과를 되돌려줍니다.라우팅 방법은 @RequestMapping 메모와 유사합니다.그러나 또 하나의 현저한 차이점은 주해를 사용할 때 루트가 주해의value가 표현할 수 있는 범위로 제한되기 때문에 이런 방법의 덮어쓰기를 처리하는 것은 어렵다.루트를 사용할 때 코드가 거기에 있어서 쉽게 덮어쓰거나 바꿀 수 있습니다.
다음은 내장 처리 함수가 있는 루트 함수의 예이다.그것은 좀 지루해 보이지만, 걱정하지 마라. 우리는 그것을 짧게 할 방법을 찾을 것이다.

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 ) 과 처리 방법 (Handler Function) 으로 루트를 만들 수 있습니다.판단식 판단이 성공하면 처리 방법을 되돌려주고 그렇지 않으면 빈 결과를 되돌려줍니다.다음은 루트 방법으로 위의 예를 다시 쓰는 것입니다.

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)를 필터링합니다. 그 중에서 FilterFunction은 본질적으로 BiFunction, Response입니다.함수의 프로세서 (handler) 매개 변수는 전체 체인의 다음 항목을 대표합니다. 이것은 전형적인 HandlerFunction이지만, 여러 개의 필터를 추가하면 다른 FilterFunction이 될 수 있습니다.라우팅에 로그 필터를 추가합니다.

// 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가 필요할 수도 있습니다.)
결론
간단한 요약을 통해 결론을 내리겠습니다.
  • 처리 함수는 응답 처리 요청을 되돌려줍니다
  • 루트 함수 루트에서 처리 함수로 다른 루트 함수와 조합할 수 있습니다
  • 라우팅 함수는 필터를 통해 필터링할 수 있습니다
  • 루트 함수는 응답하는 웹이 실행될 때 실행할 수 있습니다.
  • 여러분들이 더욱 전면적으로 이해할 수 있도록 저는 범용 웹 프레임워크를 사용하는 간단한 예시 프로젝트를 만들었습니다.주소
    읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

    좋은 웹페이지 즐겨찾기