private Mono<? extends Void> render(List<View> views, Map<String, Object> model, ServerWebExchange exchange) { for (View view : views) { if (view.isRedirectView()) { return view.render(model, null, exchange); } } List<MediaType> mediaTypes = getMediaTypes(views); MediaType bestMediaType = selectMediaType(exchange, () -> mediaTypes); if (bestMediaType != null) { for (View view : views) { for (MediaType mediaType : view.getSupportedMediaTypes()) { if (mediaType.isCompatibleWith(bestMediaType)) { return view.render(model, mediaType, exchange); } } } } throw new NotAcceptableStatusException(mediaTypes); }
@Override protected Mono<Void> writeToInternal(ServerWebExchange exchange, Context context) { MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext()); Stream<ViewResolver> viewResolverStream = context.viewResolvers().stream(); return Flux.fromStream(viewResolverStream) .concatMap(viewResolver -> viewResolver.resolveViewName(name(), locale)) .next() .switchIfEmpty(Mono.error(() -> new IllegalArgumentException("Could not resolve view with name '" + name() + "'"))) .flatMap(view -> { List<MediaType> mediaTypes = view.getSupportedMediaTypes(); return view.render(model(), contentType == null && !mediaTypes.isEmpty() ? mediaTypes.get(0) : contentType, exchange); }); }
private List<MediaType> getMediaTypes(List<View> views) { return views.stream() .flatMap(view -> view.getSupportedMediaTypes().stream()) .collect(Collectors.toList()); }
@Test public void render() { Map<String, Object> model = Collections.singletonMap("foo", "bar"); Mono<RenderingResponse> result = RenderingResponse.create("view").modelAttributes(model).build(); MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("http://localhost")); ViewResolver viewResolver = mock(ViewResolver.class); View view = mock(View.class); when(viewResolver.resolveViewName("view", Locale.ENGLISH)).thenReturn(Mono.just(view)); when(view.render(model, null, exchange)).thenReturn(Mono.empty()); List<ViewResolver> viewResolvers = new ArrayList<>(); viewResolvers.add(viewResolver); HandlerStrategies mockConfig = mock(HandlerStrategies.class); when(mockConfig.viewResolvers()).thenReturn(viewResolvers); StepVerifier.create(result) .expectNextMatches(response -> "view".equals(response.name()) && model.equals(response.model())) .expectComplete() .verify(); }
private Mono<? extends Void> render(List<View> views, Map<String, Object> model, ServerWebExchange exchange) { List<MediaType> mediaTypes = getMediaTypes(views); MediaType bestMediaType = selectMediaType(exchange, () -> mediaTypes); if (bestMediaType != null) { for (View view : views) { for (MediaType mediaType : view.getSupportedMediaTypes()) { if (mediaType.isCompatibleWith(bestMediaType)) { return view.render(model, mediaType, exchange); } } } } throw new NotAcceptableStatusException(mediaTypes); }
@Test public void viewResolutionResultHandler() throws Exception { ApplicationContext context = loadConfig(CustomViewResolverConfig.class); String name = "viewResolutionResultHandler"; ViewResolutionResultHandler handler = context.getBean(name, ViewResolutionResultHandler.class); assertNotNull(handler); assertEquals(Ordered.LOWEST_PRECEDENCE, handler.getOrder()); List<ViewResolver> resolvers = handler.getViewResolvers(); assertEquals(1, resolvers.size()); assertEquals(FreeMarkerViewResolver.class, resolvers.get(0).getClass()); List<View> views = handler.getDefaultViews(); assertEquals(1, views.size()); MimeType type = MimeTypeUtils.parseMimeType("application/json;charset=UTF-8"); assertEquals(type, views.get(0).getSupportedMediaTypes().get(0)); }
@Override public Mono<Void> writeTo(ServerWebExchange exchange, HandlerStrategies strategies) { ServerHttpResponse response = exchange.getResponse(); writeStatusAndHeaders(response); MediaType contentType = exchange.getResponse().getHeaders().getContentType(); Locale acceptLocale = exchange.getRequest().getHeaders().getAcceptLanguageAsLocale(); Locale locale = (acceptLocale != null ? acceptLocale : Locale.getDefault()); Stream<ViewResolver> viewResolverStream = strategies.viewResolvers().get(); return Flux.fromStream(viewResolverStream) .concatMap(viewResolver -> viewResolver.resolveViewName(this.name, locale)) .next() .otherwiseIfEmpty(Mono.error(new IllegalArgumentException("Could not resolve view with name '" + this.name +"'"))) .then(view -> view.render(this.model, contentType, exchange)); }
private List<MediaType> getMediaTypes(List<View> views) { return views.stream() .flatMap(view -> view.getSupportedMediaTypes().stream()) .collect(Collectors.toList()); }