Я использую Spring MVC (3.0) с управляемыми аннотацией контроллерами. Я хотел бы создать УСПОКОИТЕЛЬНЫЕ URL для ресурсов и смочь не потребовать (но все еще дополнительно позволить) расширение файла на конце URL (но предположил бы тип содержимого HTML если никакое расширение). Это работает out-of-the-box с Spring MVC, пока нет никаких точек (период/точка) в части имени файла.
Однако некоторые мои URL требуют идентификатора с точками на имя. Например, как это:
http://company.com/widgets/123.456.789.500
В этом случае Spring ищет тип контента для расширения .500
и не находит ни один так ошибками. Я могу использовать обходные решения как добавление .html
в конец, кодируя идентификатор или добавляя запаздывающую наклонную черту. Я не доволен никем, если они, но могли бы, вероятно, жить с добавлением .html
.
Я неудачно искал способ переопределить обнаружение расширения файла по умолчанию в Spring.
Действительно ли возможно настроить или отключить обнаружение расширения файла для данного метода контроллера или шаблона URL и т.д.?
@PathVariable
Сопоставление рисунка - это немного дергается, когда речь идет о точках в URL (см. SPR-5778 ). Вы можете сделать его менее Thitchy (но более воспитанным) и лучше контролировать URL-адреса, установив свойство USEFAULTSUFFIXPattern
на по умолчаниюнотационному отключению
на false
.
Если вы еще не были явно объявлены DEALKNANDATIONATIONATIONLERMARCE
в вашем контексте (и большинство людей не так, как он неявен неявно для вас), то вы можете добавить его прямо и установить это свойство.
Я не утверждаю, что у меня есть окончательный ответ на все это (это довольно открытый вопрос, который вы должны попытаться разбить на более мелкие части, и это зависит от ваших фактических требований, на самом деле я искушен проголосовать за его закрытие), но я прокомментирую несколько вещей:
Для работы некоторых приложений, таких как BetterKeyboard , необходимо изменить некоторые системные параметры настройки. Вместо того, чтобы изменять его сами, они имеют кнопку, которая отправляет пользователя в точное окно, где информация должна быть изменена. Я думаю, что это сделано с намерением . На твоем месте я бы попытался этого добиться. Если пользователь хочет изменить свой языковой стандарт, отправьте его в настройки языкового стандарта своего телефона.
-121--3391018- Вероятно, это уродливый взлом, я просто хотел изучить расширяемость Spring @ MVC. Вот настраиваемый SunMatcher
. Он использует $
в образец в качестве конечного маркера - если образец заканчивается с ним, маркер удаляется и образец сопоставляется с сопоставителем по умолчанию, но если образец имеет $
посередине (например, ... $. *
), такой образец не сопоставляется.
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;
}
}
}
Config:
<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 »):
@RequestMapping(value = "/hello/{value}$", method = RequestMethod.GET)
public String hello(@PathVariable("value") String value, ModelMap model)
EDIT: : Теперь не нарушается правило« не имеет значения »
У меня была та же проблема, и я также решил ее с помощью настраиваемого PathMatcher. Мое решение несколько проще того, что предлагал axtavt. Мой PathMatcher также имеет частную конечную цель AntPathMatcher, и он делегирует все вызовы ему без изменений, за исключением метода match ():
@Override
public boolean match(String pattern, String path) {
return pattern.endsWith(".*") ? false : target.match(pattern, path);
}
Это работает, потому что Spring пытается сопоставить контроллеры, добавляя «. » в конец. Например, с сопоставлением путей "/ widgets / {id}" и URL "/widgets/1.2.3.4" Spring пытается сначала сопоставить "/ widgets / {id}. ", а затем "/ widgets / { я бы}". Первый будет соответствовать, но для id останется только «1.2.3».
My PatchMatcher специально отклоняет шаблоны, заканчивающиеся на ". *", Поэтому первая попытка не удалась, а вторая соответствует.
Если вы используете ContentNegotiatingViewResolver, вы все равно можете указать тип контента в URL-адресах, используя параметр запроса «формат» (если для параметра FavorParameter установлено значение true).
-jarppe