gpt4 book ai didi

java - servlet url 模式匹配实现错误

转载 作者:行者123 更新时间:2023-11-30 11:03:38 25 4
gpt4 key购买 nike

我正在实现遵循 Servlet 规范的 Servlet URL 模式匹配。我的搭配方法:

public static boolean match(String pattern, String str, boolean isCaseSensitive) {
char[] patArr = pattern.toCharArray();
char[] strArr = str.toCharArray();
int patIdxStart = 0;
int patIdxEnd = patArr.length - 1;
int strIdxStart = 0;
int strIdxEnd = strArr.length - 1;

boolean containsStar = false;
for (int i = 0; i < patArr.length; i++) {
if (patArr[i] != '*') {
continue;
}
containsStar = true;
break;
}

if (!containsStar) {
if (patIdxEnd != strIdxEnd) {
return false;
}
for (int i = 0; i <= patIdxEnd; i++) {
char ch = patArr[i];
if (ch == '?')
continue;
if ((isCaseSensitive) && (ch != strArr[i])) {
return false;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[i]))) {
return false;
}
}

return true;
}

if (patIdxEnd == 0) {
return true;
}

char ch;
while (((ch = patArr[patIdxStart]) != '*')
&& (strIdxStart <= strIdxEnd)) {
if (ch != '?') {
if ((isCaseSensitive) && (ch != strArr[strIdxStart])) {
return false;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[strIdxStart]))) {
return false;
}
}
patIdxStart++;
strIdxStart++;
}

if (strIdxStart > strIdxEnd) {
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}

while (((ch = patArr[patIdxEnd]) != '*') && (strIdxStart <= strIdxEnd)) {
if (ch != '?') {
if ((isCaseSensitive) && (ch != strArr[strIdxEnd])) {
return false;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[strIdxEnd]))) {
return false;
}
}
patIdxEnd--;
strIdxEnd--;
}

if (strIdxStart > strIdxEnd) {
for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}

while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
int patIdxTmp = -1;
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
continue;
}
patIdxTmp = i;
break;
}

if (patIdxTmp == patIdxStart + 1) {
patIdxStart++;
continue;
}

int patLength = patIdxTmp - patIdxStart - 1;
int strLength = strIdxEnd - strIdxStart + 1;
int foundIdx = -1;
for (int i = 0; i <= strLength - patLength; i++) {
int j = 0;
while (true)
if (j < patLength) {
ch = patArr[(patIdxStart + j + 1)];
if (ch != '?') {
if ((isCaseSensitive)
&& (ch != strArr[(strIdxStart + i + j)])) {
break;
}
if ((!isCaseSensitive)
&& (Character.toUpperCase(ch) != Character
.toUpperCase(strArr[(strIdxStart
+ i + j)])))
break;
} else {
j++;
continue;
}

} else {
foundIdx = strIdxStart + i;
break;
}
}

if (foundIdx == -1) {
return false;
}

patIdxStart = patIdxTmp;
strIdxStart = foundIdx + patLength;
}

for (int i = patIdxStart; i <= patIdxEnd; i++) {
if (patArr[i] != '*') {
return false;
}
}
return true;
}

但是当我用下面的案例测试时:

String pattern = "*.a*";
String path = "/index.abc";
String matches = match(pattern, path, true) ? "matches" : "unmatches";
System.out.println(path + " " + matches + " " + pattern);

测试用例永远运行,不能停止。我有两个问题:

  1. 模式 "*.a*" 是否对 Servlet URL 模式匹配规范有效?
  2. 如何修复此错误以打破无限循环?

最佳答案

这是我的 Java Servlet 规范 3.1(2013 年 4 月)将请求映射到 Servlet 实现。

/**
* Java Servlet Specification 3.1 (April 2013)
* Mapping Requests to Servlets (Chapter 12) implementation.
*
* This class is thread safe.
*/
public class ServletMappingMatcher {
private final String[] patterns;
private final String[] welcomePages;

public ServletMappingMatcher(String... patterns) {
this(patterns, new String[0]);
}

public ServletMappingMatcher(String[] patterns, String[] welcomePages) {
this.patterns = patterns;
this.welcomePages = welcomePages;
}

public String getPatternForPath(String path) {
for (String pattern : patterns) {
if (matches(pattern, path)) {
return pattern;
}
}

return null;
}

private boolean matches(String pattern, String path) {
if (isPathMapping(pattern)) {
return pathMatches(pattern, path);
} else if (isExtensionPattern(pattern)) {
return extensionMatches(pattern, path);
} else if (isApplicationContextRoot(pattern)) {
return matchesApplicationContextRoot(path);
} else if (isDefaultServlet(pattern)) {
return matchesDefaultServlet(path);
}

return strictlyMatches(pattern, path);
}

private boolean isPathMapping(String pattern) {
return pattern.startsWith("/") && pattern.endsWith("/*");
}

private boolean isExtensionPattern(String pattern) {
return pattern.startsWith("*.");
}

private boolean isApplicationContextRoot(String pattern) {
return pattern.isEmpty();
}

private boolean isDefaultServlet(String pattern) {
return pattern.equals("/");
}

private boolean pathMatches(String pattern, String path) {
return path.startsWith(pattern.substring(0, pattern.length() - 1)) ||
path.equals(pattern.substring(0, pattern.length() - 2));
}

private boolean extensionMatches(String pattern, String path) {
return path.endsWith(pattern.substring(1));
}

private boolean matchesApplicationContextRoot(String path) {
return path.equals("/");
}

private boolean strictlyMatches(String pattern, String path) {
return path.equals(pattern);
}

private boolean matchesDefaultServlet(String path) {
if (path.endsWith("/")) {
return true;
}

for (String welcomePage : welcomePages) {
if (path.endsWith("/" + welcomePage)) {
return true;
}
}

return false;
}
}

和 JUnit 测试:

import org.junit.Assert;
import org.junit.Test;

public class ServletMappingMatcherTest {
@Test
public void testsFromSpec() {
final String servlet1Pattern = "/foo/bar/*";
final String servlet2Pattern = "/baz/*";
final String servlet3Pattern = "/catalog";
final String servlet4Pattern = "*.bop";
final String defaultServlet = "/";

final String[] patterns = {servlet1Pattern, servlet2Pattern, servlet3Pattern, servlet4Pattern, defaultServlet};
final String[] welcomePages = {"index.html"};

final ServletMappingMatcher matcher = new ServletMappingMatcher(patterns, welcomePages);

Assert.assertEquals(servlet1Pattern, matcher.getPatternForPath("/foo/bar/index.html"));
Assert.assertEquals(servlet1Pattern, matcher.getPatternForPath("/foo/bar/index.bop"));
Assert.assertEquals(servlet2Pattern, matcher.getPatternForPath("/baz"));
Assert.assertEquals(servlet2Pattern, matcher.getPatternForPath("/baz/index.html"));
Assert.assertEquals(servlet3Pattern, matcher.getPatternForPath("/catalog"));
Assert.assertEquals(defaultServlet, matcher.getPatternForPath("/catalog/index.html"));
Assert.assertEquals(servlet4Pattern, matcher.getPatternForPath("/catalog/rececar.bop"));
Assert.assertEquals(servlet4Pattern, matcher.getPatternForPath("/index.bop"));
}
}

关于java - servlet url 模式匹配实现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30288048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com