@Bean public ViewResolutionResultHandler viewResolutionResultHandler() { ViewResolverRegistry registry = getViewResolverRegistry(); List<ViewResolver> resolvers = registry.getViewResolvers(); ViewResolutionResultHandler handler = new ViewResolutionResultHandler( resolvers, webFluxContentTypeResolver(), webFluxAdapterRegistry()); handler.setDefaultViews(registry.getDefaultViews()); handler.setOrder(registry.getOrder()); return handler; }
private Mono<List<View>> resolveViews(String viewName, Locale locale) { return Flux.fromIterable(getViewResolvers()) .concatMap(resolver -> resolver.resolveViewName(viewName, locale)) .collectList() .map(views -> { if (views.isEmpty()) { throw new IllegalStateException( "Could not resolve view with name '" + viewName + "'."); } views.addAll(getDefaultViews()); return views; }); }
Mono<Object> valueMono; ResolvableType valueType; ReactiveAdapter adapter = getAdapter(result); viewsMono = resolveViews(getDefaultViewName(exchange), locale); else if (CharSequence.class.isAssignableFrom(clazz) && !hasModelAnnotation(parameter)) { viewsMono = resolveViews(returnValue.toString(), locale); Object view = render.view(); if (view == null) { view = getDefaultViewName(exchange); viewsMono = (view instanceof String ? resolveViews((String) view, locale) : Mono.just(Collections.singletonList((View) view))); viewsMono = resolveViews(getDefaultViewName(exchange), locale); else if (Map.class.isAssignableFrom(clazz) && !hasModelAnnotation(parameter)) { model.addAllAttributes((Map<String, ?>) returnValue); viewsMono = resolveViews(getDefaultViewName(exchange), locale); String name = getNameForReturnValue(parameter); model.addAttribute(name, returnValue); viewsMono = resolveViews(getDefaultViewName(exchange), locale); updateBindingContext(result.getBindingContext(), exchange); return viewsMono.flatMap(views -> render(views, model.asMap(), exchange));
private ViewResolutionResultHandler resultHandler(List<View> defaultViews, ViewResolver... resolvers) { List<ViewResolver> resolverList = Arrays.asList(resolvers); RequestedContentTypeResolver contentTypeResolver = new HeaderContentTypeResolver(); ViewResolutionResultHandler handler = new ViewResolutionResultHandler(resolverList, contentTypeResolver); handler.setDefaultViews(defaultViews); return handler; }
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameterType.getRawClass(), optional); .then(returnValue -> { updateResponseStatus(result.getReturnTypeSource(), exchange); viewsMono = resolveViews(getDefaultViewName(result, exchange), locale); viewsMono = resolveViews(getDefaultViewName(result, exchange), locale); viewsMono = resolveViews(getDefaultViewName(result, exchange), locale); else if (CharSequence.class.isAssignableFrom(clazz) && !hasModelAttributeAnnotation(result)) { viewsMono = resolveViews(returnValue.toString(), locale); String name = getNameForReturnValue(clazz, result.getReturnTypeSource()); model.addAttribute(name, returnValue); viewsMono = resolveViews(getDefaultViewName(result, exchange), locale); return resolveAsyncAttributes(model.asMap()) .doOnSuccess(aVoid -> addBindingResult(result, exchange)) .then(viewsMono) .then(views -> render(views, model.asMap(), exchange)); });
@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)); }
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); }
@Test public void viewResolverOrder() { TestViewResolver resolver1 = new TestViewResolver("account"); TestViewResolver resolver2 = new TestViewResolver("profile"); resolver1.setOrder(2); resolver2.setOrder(1); List<ViewResolver> resolvers = resultHandler(resolver1, resolver2).getViewResolvers(); assertEquals(Arrays.asList(resolver2, resolver1), resolvers); }
private void updateBindingContext(BindingContext context, ServerWebExchange exchange) { Map<String, Object> model = context.getModel().asMap(); model.keySet().stream() .filter(name -> isBindingCandidate(name, model.get(name))) .filter(name -> !model.containsKey(BindingResult.MODEL_KEY_PREFIX + name)) .forEach(name -> { WebExchangeDataBinder binder = context.createDataBinder(exchange, model.get(name), name); model.put(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); }); }
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); }
private void addBindingResult(HandlerResult result, ServerWebExchange exchange) { BindingContext context = result.getBindingContext(); Map<String, Object> model = context.getModel().asMap(); model.keySet().stream() .filter(name -> isBindingCandidate(name, model.get(name))) .filter(name -> !model.containsKey(BindingResult.MODEL_KEY_PREFIX + name)) .forEach(name -> { WebExchangeDataBinder binder = context.createDataBinder(exchange, model.get(name), name); model.put(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); }); }
@Bean public ViewResolutionResultHandler viewResolutionResultHandler() { ViewResolverRegistry registry = new ViewResolverRegistry(getApplicationContext()); configureViewResolvers(registry); List<ViewResolver> resolvers = registry.getViewResolvers(); ViewResolutionResultHandler handler = new ViewResolutionResultHandler( resolvers, webReactiveContentTypeResolver(), webReactiveAdapterRegistry()); handler.setDefaultViews(registry.getDefaultViews()); handler.setOrder(registry.getOrder()); return handler; }
private Mono<List<View>> resolveViews(String viewName, Locale locale) { return Flux.fromIterable(getViewResolvers()) .concatMap(resolver -> resolver.resolveViewName(viewName, locale)) .collectList() .map(views -> { if (views.isEmpty()) { throw new IllegalStateException( "Could not resolve view with name '" + viewName + "'."); } views.addAll(getDefaultViews()); return views; }); }