如何使用springmvc作为控制器呈现对jsf页面的ajax响应

时间:2011-03-03 23:06:43

标签: java ajax spring jsf spring-mvc

我正在使用Spring-MVC作为控制器的项目,JSF负责渲染。我现在需要在页面中实现一些Ajax功能。我所追求的是这样的:

  1. 用户点击按钮或“其他可点击的内容”
  2. 对控制器进行Ajax调用,直到返回响应,某些带有文本“loading ...”的面板呈现在按钮下面
  3. 控制器将处理请求并将结果作为HTML返回。结果将呈现为与“loading ...”信息相似的面板。
  4. 第3步是我迷路的时候。到目前为止,我发现我必须使用普通的JSP和tile(Handling Ajax Requests with Spring MVC Controllers)来实现“开箱即用”的这种功能。但我需要使用JSF和我的一个XHTML片段作为“模板” 我已经在我的spring配置文件中配置了AJAX解析器,但它用于返回JSON对象。现在我需要返回整个HTML。我想使用服务器进行渲染,而不是从JSON对象模拟它并将HTML粘贴到页面上的正确位置。有没有办法如何“说服”org.springframework.faces.mvc.JsfView在AJAX请求中工作?这是我正常的JSF解析器配置:

    <bean id="jsfViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.faces.mvc.JsfView" />   
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".xhtml" />
    </bean>
    

    这是我的JSON Ajax解析器配置:

    <bean id="ajaxViewResolver" class="com.myproject.web.springmvc.AjaxViewResolver">
        <property name="ajaxView">
            <bean class="com.myproject.web.springmvc.AjaxView" />
        </property>
        <property name="ajaxPrefix" value="ajax_"></property>
    </bean>
    

    以下是我的JSON AjaxViewResolver中的代码:

    public class AjaxViewResolver extends AbstractCachingViewResolver {
    
    private Logger logger = Logger.getLogger(AjaxViewResolver.class);
    
    private String ajaxPrefix;
    
    private View ajaxView;
    
    @Override
    protected View loadView(String viewName, Locale locale) throws Exception {
        logger.debug("loadView - enter");
        logger.debug("loadView - viewName : " + viewName);
        logger.debug("loadView - locale : " + locale);
    
        View view = null;
        if (viewName.startsWith(this.ajaxPrefix)) {
            view = ajaxView;
        }
    
        logger.debug("loadView - returns : " + view);
        return view;
    }
    
    public String getAjaxPrefix() {
        return ajaxPrefix;
    }
    
    public void setAjaxPrefix(String ajaxPrefix) {
        this.ajaxPrefix = ajaxPrefix;
    }
    
    public View getAjaxView() {
        return ajaxView;
    }
    
    public void setAjaxView(View ajaxView) {
        this.ajaxView = ajaxView;
    }
    
    }
    

    这是我的JSON AjaxView类:

    public class AjaxView extends AbstractView {
    private Logger logger = Logger.getLogger(AjaxView.class);
    
    /**
     * Serialises the modelMap into a JSON string and writes the string to the outputStream
     */
    @Override
    protected void renderMergedOutputModel(Map map, HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug("renderMergedOutputModel - enter");
        logger.debug("renderMergedOutputModel - map : " + map);
        logger.debug("renderMergedOutputModel - request : " + request);
        logger.debug("renderMergedOutputModel - response : " + response);
    
        JSONSerializer serializer = new JSONSerializer();
        serializer.exclude("*.class");
        String jsonString = serializer.deepSerialize(map);
        response.setContentType("text/plain; charset=UTF-8");
        response.getOutputStream().write(jsonString.getBytes());
    
        logger.debug("renderMergedOutputModel - response : " + response);
        logger.debug("renderMergedOutputModel - exit");
    }
    

    }

    有什么想法吗?

1 个答案:

答案 0 :(得分:1)

看起来没有人需要这个。我花了最后几个小时浏览JSF和Spring MVC代码,我找到了一个适合我的解决方案。我想在这里介绍它,如果你们可以做一些同行评审。感谢。

解决方案是基于com.myproject.web.springmvc.AjaxViewResolver创建新bean并进入属性ajaxView注入新创建的类nz.co.bnz.olb.ib.web.springmvc.AjaxJsfView,扩展org.springframework.faces.mvc.JsfView
这是剪辑的Spring配置:

<bean id="ajaxJsfViewResolver" class="nz.co.bnz.olb.ib.web.springmvc.AjaxViewResolver">
    <property name="ajaxView">
        <bean class="nz.co.bnz.olb.ib.web.springmvc.AjaxJsfView">
            <property name="prefix" value="/WEB-INF/pages/" />
            <property name="suffix" value=".xhtml" />
        </bean>
    </property>
    <property name="ajaxPrefix" value="ajaxJsf_"></property>
</bean>

正如您所看到的,我必须传递prefixsuffix属性来定义如何形成我的XHTML文件的URL(JsfView所必需的)。我还为此解析器创建了新的前缀ajaxJsf_。这是新课程:

public class AjaxJsfView extends JsfView {
private Logger logger = Logger.getLogger(AjaxJsfView.class);

private String prefix;

private String suffix;

private String viewName;

@Override
protected void renderMergedOutputModel(Map map, HttpServletRequest request, HttpServletResponse response) throws Exception {
    logger.debug("renderMergedOutputModel - enter");
    logger.debug("renderMergedOutputModel - map : " + map);
    logger.debug("renderMergedOutputModel - request : " + request);
    logger.debug("renderMergedOutputModel - response : " + response);

    viewName = (String)map.get("view");

    super.renderMergedOutputModel(map, request, response);

    logger.debug("renderMergedOutputModel - response : " + response);
    logger.debug("renderMergedOutputModel - exit");
}

public String getPrefix() {
    return prefix;
}

public void setPrefix(String prefix) {
    this.prefix = prefix;
}

public String getSuffix() {
    return suffix;
}

public void setSuffix(String suffix) {
    this.suffix = suffix;
}

@Override
public String getUrl() {
    return getPrefix() + viewName + getSuffix();
}

@Override
public void setUrl(String arg0) {
    super.setUrl(arg0);
}
}

renderMergedOutputModel方法中可以看到用作“视图”的实际文件的定义。它取自关键“视图”下的地图中的“模型”。 “视图”的完整路径在重写方法getUrl()中实现。因此,作为最后一步,我必须实现我的控制器方法,以返回具有预期值的地图:

public ModelAndView getSomeTest(HttpServletRequest request, HttpServletResponse response){
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("view", "pathToMyXHTMLFile/someTest");
    map.put("name", "tomik");

    ModelAndView returnModelAndView = new ModelAndView("ajaxJsf_increaseLimit", map);

    return returnModelAndView;
}

最后这是使用的XHTML,最终以带有填充值的HTML格式返回:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core">

    <p>Hello <h:outputText value="#{name}"/></p>
</ui:composition>