Liferay 6.2上的Spring MVC表单中的Portlet命名空间

时间:2014-02-17 15:08:57

标签: java spring spring-mvc liferay portlet

有没有办法让Spring MVC表单为portlet命名?我不想设置

<requires-namespaced-parameters>false</requires-namespaced-parameters>

为了让Spring mvc表单在Liferay 6.2下运行。

我正在考虑覆盖Spring form-taglib,以便将portlet-namespace前缀放在表单字段名称/ ID之前,而不实际尝试将它们绑定到带有命名空间的bean-properties(这显然不起作用) )但这似乎非常耗时。

有人知道解决这个问题的另一种方法吗?

以下是显示确切问题的表单示例:

<portlet:actionURL var="actionURL">
    <portlet:param name="action" value="search"/>
</portlet:actionURL>

<form:form action="${actionURL}" commandName="searchSettings">
    <form:input path="textField"/>
    <form:input path="anotherTextField"/>
    <input type="submit" value="Search"/>
</form:form>

它的相应bean将是:

public class SearchSettings {

    private String textField;
    private String anotherTextField;

    // .. getters & setters

}

这在Liferay 6.2下不起作用,因为表单输入不是命名空间。它们应该像这样命名空间:

<c:set var="ns"><portlet:namespace/></c:set>

<form:input path="${ns}textField"/>

然而,这不起作用,因为现在Spring将尝试将表单字段绑定到属性

SearchSettings._namespace_portlet_textField

当然不存在。

有没有人遇到过这个问题并找到了除了覆盖Spring MVC Form-Taglib之外的解决方案?我看到它已经记录在Spring的JIRA(https://jira.springsource.org/browse/SPR-11176)上,但我找不到其他的东西。

提前致谢。

2 个答案:

答案 0 :(得分:1)

我现在设法覆盖Spring表单taglib(3.0.7.RELEASE)以支持portlet名称空间。如果你想这样做,你将不得不在Tag-classes中寻找这个方法(例如InputTag):

protected void writeDefaultAttributes(TagWriter tagWriter) throws JspException

你需要覆盖它,所以它在命名空间中工作如下:

@Override
protected void writeDefaultAttributes(TagWriter tagWriter) throws JspException {
    writeOptionalAttribute(tagWriter, "name", getNamespace() + getName());
    writeOptionalAttribute(tagWriter, "id", getNamespace() + resolveId());
    super.writeDefaultAttributes(tagWriter);
}

当然,你需要自己的tagdescriptor来获取命名空间。你还需要覆盖

protected int writeTagContent(TagWriter tagWriter) throws JspException;

方法,因为那是调用writeDefaultAttributes方法的方法。

这暂时有效,但我仍在寻找更好的方法来解决这个问题。

修改

你可以使用jQuery更快地完成它:

$(document).ready(function() {
    // Alle inputs
    $('input').each(function() {
        var pnamespace = '<portlet:namespace/>';
        $(this).attr('id', pnamespace + this.id);
        $(this).attr('name', pnamespace + this.name);
    });
    // alle selects
    $('select').each(function() {
        var pnamespace = '<portlet:namespace/>';
        $(this).attr('id', pnamespace + this.id);
        $(this).attr('name', pnamespace + this.name);
    });
});

这将在每个输入和选择对象上放置名称空间前缀。现在,您的portlet表单已正确命名。

答案 1 :(得分:1)

作为替代方案,您可以使用 aui标记库。 请注意,生成的id将是portlet名称空间,后跟元素的名称。

<%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui" %>
<portlet:actionURL var="saveChartURL" name="saveChart" />
<aui:form action='${saveChartURL}' method='post' name='form'>
<aui:button type='button' name='save' value="Save" />
<aui:input id='json'
            type='textarea'
            name='jsonData'
            label=''
            spellcheck='false'  
            cssClass='json'
            style='disply:none;' />
</aui:form>
<script>
(function(run){run(window.jQuery)}(
    function($){
        $(document).ready(function(){
            var pNS = '<portlet:namespace/>';   
            $('#'+pNS+'save').click(function(){      
                var dataserialized = $('#'+pNS+'form').serialize();
                $.post( "${saveChartURL}", dataserialized );
            });
        }); 
    })
);
</script>

在控制器......

@ActionMapping(value="saveChart")
public void saveChart( 
    @RequestParam(defaultValue="{}") String jsonData, 
    @RequestParam(defaultValue="doughnut2d") String chartType,
    PortletPreferences pp) {

    /* TODO do Action */
}