【问题标题】:Render multiple views within a single request在单个请求中呈现多个视图
【发布时间】:2012-03-14 15:50:16
【问题描述】:

我正在尝试在单个请求中返回多个视图,并将它们全部返回到 JSON 字符串中。

例子:

@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)
}

我正在使用带有 Tiles 2 的 Spring MVC。

谁能帮帮我?

更新 1 - 使用 ViewResolver 解析视图名称:

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

更新 2 - 我创建了一个 github repository,其中包含一个重现问题的非常小的示例。

【问题讨论】:

  • 所以实际上您不想显示任何视图,而是将字符串传递给您的客户?
  • 我所说的字符串是呈现为字符串的 HTML(相应地更改了原始问题)
  • 如果您使用磁贴将视图平铺成单个复合视图并重定向到它的名称。
  • 我不想使用单个复合视图,我需要视图保持独立。 JSON 响应将由 JavaScript 管理,该 JavaScript 将在此处放置一个视图并在此处放置一个视图

标签: json spring spring-mvc tiles


【解决方案1】:

更新:有一些方法可以解决您的问题。我会尝试这个,但也许有更清洁的方法。

@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();
    }
}

并且可以这样使用:

@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);
}

【讨论】:

  • 等一下。我得到一个NullPointerException 因为mav.getView() 返回null,你知道为什么吗? ModelAndViews 的创建与我的示例完全相同。谢谢!
  • 来自getView() doc:“返回 View 对象,如果我们使用由 DispatcherServlet 通过 ViewResolver 解析的视图名称,则返回 null。”... 我怎样才能避免这种情况?
  • 谢谢@sinuhepop - 我想做类似的事情。您的解决方案引发异常:“org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项 [org.springframework.web.servlet.ViewResolver 的集合] 找到类型为 [org.springframework.web.servlet.ViewResolver] 的匹配 bean” .我有两个 servlet,它们都在 *-servlet.xml 文件中包含 ViewResolver。 IntelliJ IDEA 在输入 @Autowiring 时不会给出任何警告,而在自动装配不存在的 bean 时通常会给出警告......
  • 你如何/在哪里加载你的 JsonMultipleViewFactory bean?如果通过 XML,在什么文件中?您确定将 Spring 上下文加载到您为两个 servlet 创建的 Web 应用程序上下文之一中,其中创建了 ViewResolver bean?另外,为什么你有两个 servlet,每个都有自己的 *-servlet.xml 文件?这似乎不寻常。
  • 您好@sdouglass,抱歉回复晚了。 JsonMultipleViewFactory 在控制器中自动接线。我有一个用于正常请求的 servlet,我在其中配置图块、映射静态资源(CSS/图像/脚本等)并使用“/WEB-INF/jsp/”作为前缀和“.jsp”作为后缀配置视图解析器。然后我有另一个用于 ajax 请求的 servlet,我唯一配置的是视图解析器,前缀为“/WEB-INF/tiles/”,后缀为“.jsp”。我真的不明白为什么ViewResolver 没有自动连线..
猜你喜欢
  • 1970-01-01
  • 2018-09-29
  • 2014-11-26
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多