Tiles 3 List属性无法正常工作

时间:2013-01-28 10:34:42

标签: spring spring-mvc tiles

我的spring MVC项目和tile 3面临几个问题,其中一个主要问题是list属性。我想要做的是使用OptionsRenderer创建一个通用的tile定义,就像在the ultimate view article中一样(文章中有一个错误,因为lit属性是在定义之外定义的,这是错误的)。当我使用${options[myoptions]}表达式创建一些属性时,我总是在模板JSP中获得IllegalStateException因为缺少名为myoptions的列表属性,即使我定义了此列表属性。我的代码如下:

tiles.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>

    <definition name="WILDCARD:*/*" template="/WEB-INF/view/template.jsp">
        <put-attribute name="meta" value="/WEB-INF/view/${options[folder]}/meta.jsp" />
        <put-attribute name="header" value="/WEB-INF/view/${options[folder]}/header.jsp" />
        <put-attribute name="body" value="/WEB-INF/view/${options[folder]}/{2}.jsp" />
        <put-attribute name="footer" value="/WEB-INF/view/${options[folder]}/footer.jsp" />

        <put-list-attribute name="folder">
            <add-list-attribute>
                <add-attribute value="{1}" />
                <add-attribute value="common" />
            </add-list-attribute>
        </put-list-attribute>
    </definition>
</tiles-definitions>

template.jsp

<%@ page language="java" pageEncoding="UTF-8"
    contentType="text/html; charset=utf-8" trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<html>
<head>
<title>${dynamicTitle} - <fmt:message key="common.siteName" /></title>
<tiles:insertAttribute name="meta" />
</head>
<body>
    <div id="header">
        <tiles:insertAttribute name="header" />
    </div>
    <div id="body">
        <tiles:insertAttribute name="body" />
    </div>
    <div id="footer">
        <tiles:insertAttribute name="footer" />
    </div>
</body>
</html>

我尝试了几种没有结果的解决方案。我的试验如下: 1.在我的JSP中使用<tiles:importAttribute name="folder"/>。绝对没有区别 2.在我的JSP中使用<tiles:insertAttribute name="folder"/>。我有一个例外,因为属性不是字符串。 3.使用<tiles:putListAttribute name="folder">FULL_DEFINITION_HERE</tiles:putListAttribute>在JSP中定义属性,没有任何区别。

我已经提到了上面提到的文章,tiles documentation特别是OptionsRenderer documentation没有用。谁能告诉我这里我做错了什么?我相信这与春季MVC无关。

2 个答案:

答案 0 :(得分:0)

我也无法使用OptionsRender,但喜欢能够在目录层次结构中选择我的模板的想法。所以我编写了自己的渲染器,它似乎运行得很好。我已经实现了路径语法“[CHOICE_1 | CHOICE_2 | ... | CHOICE_n]”,它选择了导致有效路径的第一个选择。一个例子是:

  <definition name="main/*/*" template="/WEB-INF/tiles/layout_main.jsp">
      <put-attribute name="top" value="/WEB-INF/tiles/[{1}/{2}|{1}|common]/top.jsp"/>
      <put-attribute name="content" value="/WEB-INF/tiles/[{1}/{2}|{1}|common]/content.jsp"/>
      <put-attribute name="footer" value="/WEB-INF/tiles/[{1}/{2}|{1}|common]/footer.jsp"/>
    </definition>

我的渲染器实现也应该能够替换选择模式的几个出现。 OptionsRender似乎无法处理这种情况。

这是渲染器的实现。它必须集成到Apache Tiles中,如ultimate view article中所述。也许来自Apache Tiles的人将其整合到官方版本中。 : - )

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tiles.request.Request;
import org.apache.tiles.request.render.Renderer;

public final class ChoiceRenderer implements Renderer {

    private static final Pattern CHOICE_PATTERN = Pattern.compile("\\[([^\\]]+)\\]");

    private final Renderer renderer;

    public ChoiceRenderer(Renderer renderer) {
        this.renderer = renderer;
    }

    @Override
    public boolean isRenderable(String path, Request request) {
        // only the overall format is checked, so no extra handling here
        return this.renderer.isRenderable(path, request);
    }

    @Override
    public void render(String path, Request request) throws IOException {
        Matcher matcher = CHOICE_PATTERN.matcher(path);
        List<String[]> groups = new ArrayList<String[]>();
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "{[" + groups.size() + "]}");
            groups.add(matcher.group(1).split("\\|"));
        }
        matcher.appendTail(sb);
        if (groups.isEmpty()) {
            this.renderer.render(path, request);
        } else {
            backtrackPaths(sb.toString(), request, groups, 0);
        }
    }

    private String backtrackPaths(String pathPattern, Request request, List<String[]> groups, int depth)
            throws IOException {
        String matchPath = null;
        String[] parts = groups.get(depth);
        for (int i = 0; i < parts.length; ++i) {
            String path = pathPattern.replace("{[" + depth + "]}", parts[i]);
            if (depth == groups.size() - 1) {
                if (isPathValid(path, request)) {
                    this.renderer.render(path, request);
                    matchPath = path;
                    break;
                }
            } else {
                matchPath = backtrackPaths(path, request, groups, depth + 1);
            }
        }
        return matchPath;
    }

    // TODO should we use caching here?
    private boolean isPathValid(String path, Request request) {
        boolean rtn = false;
        // apparently the corresponding Renderer method seems to check the
        // path's format only
        if (this.renderer.isRenderable(path, request)) {
            try {
                rtn = request.getApplicationContext().getResource(path) != null;
            } catch (IllegalArgumentException e) {
                // TODO the javadoc states that null will be returned, but
                // instead of it an exception is thrown.
                // Seems to be a bug?!
                boolean throwException = true;
                if (e.getCause() instanceof FileNotFoundException) {
                    FileNotFoundException fex = (FileNotFoundException) e.getCause();
                    throwException = fex.getMessage().indexOf(path) == -1;
                }
                if (throwException) {
                    // seems to be a different reason as our searched path
                    throw e;
                }
            }
        }
        return rtn;
    }
}

答案 1 :(得分:0)

请从$删除${options