尝试在“文件名”部分创建具有多个点的 REST--ful URL - Spring 3.0 MVC

2022-09-03 04:04:14

我正在使用Spring MVC(3.0)和注释驱动的控制器。我想为资源创建REST-ful URL,并且能够在URL的末尾不需要(但仍然可以选择性地允许)文件扩展名(但是如果没有扩展名,则假设HTML内容类型)。这与Spring MVC一起开箱即用,只要文件名部分没有点(句点/句号)。

但是,我的一些URL需要一个名称中带有点的标识符。例如,像这样:

http://company.com/widgets/123.456.789.500

在这种情况下,Spring会查找扩展的内容类型,但没有发现任何错误。我可以使用解决方法,例如添加到末尾,编码标识符或添加尾部斜杠。如果这些,我对任何事情都不满意,但可能会接受添加..500.html.html

我一直在寻找一种在Spring中覆盖默认文件扩展名检测的方法,但没有成功。

是否可以为给定的控制器方法或 URL 模式等自定义或禁用文件扩展名检测?


答案 1

当涉及到URL中的点时,模式匹配有点抽搐(请参阅SPR-5778)。通过将 DefaultAnnotationHandlerMapping 上的 useDefaultSendixPattern 属性设置为 .,可以使其不那么抽搐(但更挑剔),并更好地控制点繁重的 URL。@PathVariablefalse

如果您尚未在上下文中显式声明 a(并且大多数人没有,因为它是为您隐式声明的),则可以显式添加它并设置该属性。DefaultAnnotationHandlerMapping


答案 2

也许,这是一个丑陋的黑客,我只是想探索春季@MVC的可扩展性。这是一个定制的.它在模式中使用作为结束标记 - 如果模式以它结束,则删除标记并由默认匹配器匹配模式,但如果模式在中间(例如),则此类模式不匹配。PathMatcher$$...$.*

public class CustomPathMatcher implements PathMatcher {
    private PathMatcher target;

    public CustomPathMatcher() {
        target = new AntPathMatcher();
    }

    public String combine(String pattern1, String pattern2) {
        return target.combine(pattern1, pattern2); 
    }

    public String extractPathWithinPattern(String pattern, String path) {
        if (isEncoded(pattern)) {
            pattern = resolvePattern(pattern);
            if (pattern == null) return "";
        }
        return target.extractPathWithinPattern(pattern, path);
    }

    public Map<String, String> extractUriTemplateVariables(String pattern,
            String path) {
        if (isEncoded(pattern)) {
            pattern = resolvePattern(pattern);
            if (pattern == null) return Collections.emptyMap();
        }
        return target.extractUriTemplateVariables(pattern, path);
    }

    public Comparator<String> getPatternComparator(String pattern) {
        final Comparator<String> targetComparator = target.getPatternComparator(pattern);
        return new Comparator<String>() {
            public int compare(String o1, String o2) {
                if (isEncoded(o1)) {
                    if (isEncoded(o2)) {
                        return 0;
                    } else {
                        return -1;
                    }
                } else if (isEncoded(o2)) {
                    return 1;
                }
                return targetComparator.compare(o1, o2);
            }        
        };
    }

    public boolean isPattern(String pattern) {
        if (isEncoded(pattern)) {
            pattern = resolvePattern(pattern);
            if (pattern == null) return true;
        }
        return target.isPattern(pattern);
    }

    public boolean match(String pattern, String path) {
        if (isEncoded(pattern)) {
            pattern = resolvePattern(pattern);
            if (pattern == null) return false;
        }
        return target.match(pattern, path);
    }

    public boolean matchStart(String pattern, String path) {
        if (isEncoded(pattern)) {
            pattern = resolvePattern(pattern);
            if (pattern == null) return false;
        }
        return target.match(pattern, path);
    }

    private boolean isEncoded(String pattern) {
        return pattern != null && pattern.contains("$");
    }

    private String resolvePattern(String pattern) {
        int i = pattern.indexOf('$');
        if (i < 0) return pattern;
        else if (i == pattern.length() - 1) {
            return pattern.substring(0, i);
        } else {
            String tail = pattern.substring(i + 1);
            if (tail.startsWith(".")) return null;
            else return pattern.substring(0, i) + tail;
        }
    }
}

配置:

<bean id = "pathMatcher" class = "sample.CustomPathMatcher" />

<bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name = "pathMatcher" ref="pathMatcher" />
</bean>

<bean class = "org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name = "pathMatcher" ref="pathMatcher" />
</bean>

用法(给定“/hello/1.2.3”,是“1.2.3”):value

@RequestMapping(value = "/hello/{value}$", method = RequestMethod.GET)
public String hello(@PathVariable("value") String value, ModelMap model)

编辑::现在不违反“尾部斜杠无关紧要”规则