2012-03-14 14 views
5

Estoy tratando de devolver varias vistas dentro de una única solicitud, devolviéndolas todas en una cadena JSON.Renderice varias vistas en una única solicitud

Ejemplo:

@RequestMapping(value = "my-request") 
public void myRequest(HttpServletRequest request, HttpServletResponse response) throws Exception 
{ 
    Map<String,Object> model1 = new Hashtable<String,Object>(); 
    model1.put(...); 
    ModelAndView modelAndView1 = new ModelAndView("path/to/view1", model1); 
    // Render modelAndView1 in some way, in order to obtain the rendered HTML as a String 

    Map<String,Object> model2 = new Hashtable<String,Object>(); 
    model2.put(...); 
    ModelAndView modelAndView2 = new ModelAndView("path/to/view2", model2); 
    // Render modelAndView2 in some way, in order to obtain the rendered HTML as a String 

    // Now write a JSON String to the HttpServletResponse containing both the rendered views (strings). 
    // (this is not part of my problem, I'm able to do it as long as I have the two strings) 
} 

estoy usando Spring MVC con azulejos 2.

¿Puede alguien ayudarme?

Actualización 1 - Ver nombres se resuelven usando un ViewResolver:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/tiles/" /> 
    <property name="suffix" value=".jsp" /> 
</bean> 

Actualización 2 - He creado un github repository contiene un ejemplo muy pequeño que reproduce el problema.

+0

Así que, de hecho, usted no desea aparecer cualquier punto de vista, pero pasa una cadena a su cliente? – Stefan

+0

Las cadenas a las que me refiero son el HTML renderizado como cadenas (cambió la pregunta original en consecuencia) – satoshi

+0

Si los mosaicos que utiliza se combinan para formar vistas en una única vista compuesta y redirigir al nombre de la misma. – Stefan

Respuesta

6

ACTUALIZACIÓN: Hay algunos enfoques para resolver su problema. Intentaría este, pero tal vez hay formas más limpias.

@Component 
public class JsonMultipleViewFactory { 

    @Autowired private List<ViewResolver> viewResolverList; 

    public View getView(List<ModelAndView> mavList) { 
     for (ModelAndView mav : mavList) { 
      if (mav.getView()==null) { 
       mav.setView(resolve(mav.getViewName())); 
      } 
     } 
     return new JsonMultipleView(mavList); 
    } 

    private View resolve(String viewName) { 
     for (ViewResolver vr : viewResolverList) { 
      View view = vr.resolve(viewName, LocaleContextHolder.getLocale()); 
      if (view!=null) { 
       return view; 
      } 
     } 
     return null; 
    } 
} 

public class JsonMultipleView implements View { 

    private final List<ModelAndView> mavList; 

    public JsonMultipleView(List<ModelAndView> mavList) { 
     this.mavList = mavList; 
    } 

    public String getContentType() { 
     return "application/json"; 
    } 

    public void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) { 
     Json json = new Json(); // You can use several Json libraries here 
     for (ModelAndView mav : mavList) { 
      MockHttpServletResponse mockResponse = new MockHttpServletResponse(); 
      mav.getView().render(mav.getModel(), request, mockResponse); 
      json.add(mav.getViewName(), mockResponse.getContentAsString()); 
     } 
     json.write(response.getOutputStream()); 
     response.getOutputStream().close(); 
    } 
} 

y se puede utilizar como esto:

@Autowired private JsonMultipleViewFactory jsonMultipleViewFactory; 

@RequestMapping(value = "my-request") 
public View myRequest() { 
    ... 
    List<ModelAndView> mavList = new ArrayList<ModelAndView>(); 
    mavList.add(modelAndView1); 
    mavList.add(modelAndView2); 
    return jsonMultipleViewFactory.getView(mavList); 
} 
+0

¡Gracias! Funciona :) – satoshi

+0

Espera. Obtengo una 'NullPointerException' porque' mav.getView() 'devuelve nulo, ¿sabes por qué? Los 'ModelAndView's se crean exactamente como en mi ejemplo. ¡Gracias! – satoshi

+0

Del 'getView()' doc: "Devuelve el objeto View, o null si estamos usando un nombre de vista para ser resuelto por el DispatcherServlet a través de ViewResolver." ... ¿Cómo puedo evitar esto? – satoshi

Cuestiones relacionadas