1

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

瓷砖.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>

模板.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.<tiles:importAttribute name="folder"/>在我的 JSP 中使用。完全没有区别 2.<tiles:insertAttribute name="folder"/>在我的JSP中使用。我遇到了一个异常,因为属性不是字符串。3.在JSP中定义属性<tiles:putListAttribute name="folder">FULL_DEFINITION_HERE</tiles:putListAttribute>完全没有区别。

我已经参考了上面提到的文章,以及没有用的特别是OptionsRenderer 文档的平铺文档。谁能告诉我我在这里做错了什么?我相信这与spring MVC无关。

4

2 回答 2

1

我也无法使用 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>

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

这是渲染器的实现。它必须像最终视图文章中所述那样集成到 Apache Tiles 中。也许 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;
    }
}
于 2013-05-16T08:29:34.257 回答
0

$${options.

于 2017-07-05T09:54:04.273 回答