haben Ich habe Mappings kommentiert gut funktioniert durch meine Frühjahr mvc Web-App, aber sie sind Groß-und Kleinschreibung. Ich finde keinen Weg, um sie von der Groß-/Kleinschreibung abzuhalten. (Ich würde gerne diese eher in Spring MVC, passieren als Verkehr umleiten irgendwie)Wie kann ich Groß-und Kleinschreibung URLs in Spring MVC mit annotierten Zuordnungen
Antwort
Nun, ich kann Ihre Frage nicht beantworten (Ich habe versucht, ich dachte, dass ich es heraus könnte out). Aber da Sie alle Antworten in 2 Tagen nicht erhalten haben, sind hier einige Leitungen mindestens:
Dieses Beispiel scheint darauf hinzudeuten, es ist möglich:
Es verweist auf diese Klasse im Frühjahr
Meine Vermutung (und es ist nur, dass eine Vermutung), ist, dass Sie <mvc:annotation-driven/>
und Umsetzung der einzelnen Bohnen mit den richtigen Parametern erweitern müssen mak e es case-insensitive. Siehe:
http://rapid-web.tumblr.com/post/296916668/what-does-annotation-driven-do
Ein letzter Hinweis, bemerkte ich woanders in der Lektüre, dass es, dass alle Pfade Standardfall zu senken, haben Sie festgestellt, dass /MyPath
nicht von @RequestMapping("/mypath")
behandelt wird?
Noch einmal, nur zum Nachdenken, so gut ich kann. Vielleicht bringt es Sie weit genug, um eine spezifischere Frage zu stellen, die Sie zur Antwort führt - so funktionieren diese Dinge manchmal. Viel Glück!
Nach this webpost müssen Sie sowohl eine HandlerMapping als auch eine HandlerAdapter in Spring MVC hinzufügen. Das Mapping ordnet die Anforderung einem entsprechenden Controller zu, und der Adapter ist dafür verantwortlich, die Anforderung mithilfe des Controllers auszuführen.
Sie müssen daher die PathMatcher für den Mapper und Adapter beide außer Kraft zu setzen.
Ex (alle @Controllers Groß- und Kleinschreibung machen):
New Matcher:
public class CaseInsenseticePathMatcher extends AntPathMatcher {
@Override
protected boolean doMatch(String pattern, String path, boolean fullMatch, Map<String, String> uriTemplateVariables) {
System.err.println(pattern + " -- " + path);
return super.doMatch(pattern.toLowerCase(), path.toLowerCase(), fullMatch, uriTemplateVariables);
}
}
applicationContext.xml:
<bean id="matcher" class="test.CaseInsenseticePathMatcher"/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="pathMatcher" ref="matcher"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="pathMatcher" ref="matcher"/>
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"/>
</property>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
hinzugefügt etwa gleich, dass < mvc:annotation-driven> würde machen. (Danke an David Parks für den Link)
Problem Bericht für solution by smat
In solution by smat gibt es einen kleinen Nebeneffekt (ich würde feder mvc die Schuld geben).
Zuerst scheint AntPathMatcher.doMatch()
wahr/falsch zurückzugeben, abhängig von der Anforderungszuordnungszeichenfolge der angeforderten URL und Controller-Methode (das ist das einzige, was hier getan werden sollte).Aber diese Methode wird auch für einen anderen Zweck verwendet (der nicht in documentation geschrieben wird!). Ein weiterer Zweck besteht darin, entsprechende Werte für @PathVariable
in der Controller-Methode zu sammeln. Diese Werte werden in Map<String, String> uriTemplateVariables
(letzter Parameter) gesammelt. Diese gesammelten Werte werden verwendet, um als Parameterwert an die Controller-Methode zu übergeben.
Zum Beispiel haben wir Controller-Methode wie folgt,
@RequestMapping("/code/{userCode}")
public String getCode(@PathVariable("userCode") String userCode) {
System.out.println(userCode);
}
und wenn wir mit URL zugreifen, /code/AbD
dann mit solution by smatAntPathMatcher.doMatch()
wird @PathVariable
Wert in Map<String, String> uriTemplateVariables
als userCode->abd
sammeln. Da wir die Pfadzeichenfolge untergeordnet haben, sind die gesammelten Werte auch kleiner. Und dieser tiefer gelegte userCode-Wert wird an unseren Controller übergeben.
Aber ich bin dankbar solution by smat, die mir bisher ohne weitere Probleme gut gedient hat.
Lösung
dieses Problem gelöst, indem Arbeit um solution by smat tun. Ohne den Pfad des unteren Gehäuses oder die Musterzeichenfolge in der erweiterten Klasse AntPathMatcher
habe ich meine erweiterte AntPathMatcher
gezwungen, meine benutzerdefinierte AntPathStringMatcher
zu verwenden. Meine benutzerdefinierte AntPathStringMatcher
tut Case-Insitive-Matching, ohne den Fall der tatsächlichen Zeichenfolge zu ändern.
Im folgenden Lösungscode wird der Großteil des Codes aus dem ursprünglichen Klassencode kopiert (Code, den ich anpassen wollte, wurde wegen des privaten Zugriffs für die Unterklasse ausgeblendet).
Individuelle AntPathMatcher,
public class CaseInsensitivePathMatcher extends AntPathMatcher {
private final Map<String, CaseInsensitiveAntPathStringMatcher> stringMatcherCache = new ConcurrentHashMap<String, CaseInsensitiveAntPathStringMatcher>();
/**
* Actually match the given <code>path</code> against the given
* <code>pattern</code>.
*
* @param pattern
* the pattern to match against
* @param path
* the path String to test
* @param fullMatch
* whether a full pattern match is required (else a pattern match
* as far as the given base path goes is sufficient)
* @return <code>true</code> if the supplied <code>path</code> matched,
* <code>false</code> if it didn't
*/
protected boolean doMatch(String pattern, String path, boolean fullMatch, Map<String, String> uriTemplateVariables) {
if (path.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR) != pattern.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)) {
return false;
}
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, AntPathMatcher.DEFAULT_PATH_SEPARATOR);
String[] pathDirs = StringUtils.tokenizeToStringArray(path, AntPathMatcher.DEFAULT_PATH_SEPARATOR);
int pattIdxStart = 0;
int pattIdxEnd = pattDirs.length - 1;
int pathIdxStart = 0;
int pathIdxEnd = pathDirs.length - 1;
// Match all elements up to the first **
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
String patDir = pattDirs[pattIdxStart];
if ("**".equals(patDir)) {
break;
}
if (!matchStrings(patDir, pathDirs[pathIdxStart], uriTemplateVariables)) {
return false;
}
pattIdxStart++;
pathIdxStart++;
}
if (pathIdxStart > pathIdxEnd) {
// Path is exhausted, only match if rest of pattern is * or **'s
if (pattIdxStart > pattIdxEnd) {
return (pattern.endsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR) ? path.endsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR) : !path
.endsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR));
}
if (!fullMatch) {
return true;
}
if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && path.endsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)) {
return true;
}
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!pattDirs[i].equals("**")) {
return false;
}
}
return true;
} else if (pattIdxStart > pattIdxEnd) {
// String not exhausted, but pattern is. Failure.
return false;
} else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
// Path start definitely matches due to "**" part in pattern.
return true;
}
// up to last '**'
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
String patDir = pattDirs[pattIdxEnd];
if (patDir.equals("**")) {
break;
}
if (!matchStrings(patDir, pathDirs[pathIdxEnd], uriTemplateVariables)) {
return false;
}
pattIdxEnd--;
pathIdxEnd--;
}
if (pathIdxStart > pathIdxEnd) {
// String is exhausted
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!pattDirs[i].equals("**")) {
return false;
}
}
return true;
}
while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
int patIdxTmp = -1;
for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
if (pattDirs[i].equals("**")) {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == pattIdxStart + 1) {
// '**/**' situation, so skip one
pattIdxStart++;
continue;
}
// Find the pattern between padIdxStart & padIdxTmp in str between
// strIdxStart & strIdxEnd
int patLength = (patIdxTmp - pattIdxStart - 1);
int strLength = (pathIdxEnd - pathIdxStart + 1);
int foundIdx = -1;
strLoop: for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
String subPat = pattDirs[pattIdxStart + j + 1];
String subStr = pathDirs[pathIdxStart + i + j];
if (!matchStrings(subPat, subStr, uriTemplateVariables)) {
continue strLoop;
}
}
foundIdx = pathIdxStart + i;
break;
}
if (foundIdx == -1) {
return false;
}
pattIdxStart = patIdxTmp;
pathIdxStart = foundIdx + patLength;
}
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
if (!pattDirs[i].equals("**")) {
return false;
}
}
return true;
}
/**
* Tests whether or not a string matches against a pattern. The pattern may
* contain two special characters:<br>
* '*' means zero or more characters<br>
* '?' means one and only one character
*
* @param pattern
* pattern to match against. Must not be <code>null</code>.
* @param str
* string which must be matched against the pattern. Must not be
* <code>null</code>.
* @return <code>true</code> if the string matches against the pattern, or
* <code>false</code> otherwise.
*/
private boolean matchStrings(String pattern, String str, Map<String, String> uriTemplateVariables) {
CaseInsensitiveAntPathStringMatcher matcher = this.stringMatcherCache.get(pattern);
if (matcher == null) {
matcher = new CaseInsensitiveAntPathStringMatcher(pattern);
this.stringMatcherCache.put(pattern, matcher);
}
return matcher.matchStrings(str, uriTemplateVariables);
}
}
Individuelle AntPathStringMatcher,
public class CaseInsensitiveAntPathStringMatcher {
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
private final Pattern pattern;
private final List<String> variableNames = new LinkedList<String>();
/** Construct a new instance of the <code>AntPatchStringMatcher</code>. */
CaseInsensitiveAntPathStringMatcher(String pattern) {
this.pattern = createPattern(pattern);
}
private Pattern createPattern(String pattern) {
StringBuilder patternBuilder = new StringBuilder();
Matcher m = GLOB_PATTERN.matcher(pattern);
int end = 0;
while (m.find()) {
patternBuilder.append(quote(pattern, end, m.start()));
String match = m.group();
if ("?".equals(match)) {
patternBuilder.append('.');
}
else if ("*".equals(match)) {
patternBuilder.append(".*");
}
else if (match.startsWith("{") && match.endsWith("}")) {
int colonIdx = match.indexOf(':');
if (colonIdx == -1) {
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
variableNames.add(m.group(1));
}
else {
String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
patternBuilder.append('(');
patternBuilder.append(variablePattern);
patternBuilder.append(')');
String variableName = match.substring(1, colonIdx);
variableNames.add(variableName);
}
}
end = m.end();
}
patternBuilder.append(quote(pattern, end, pattern.length()));
return Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE); // this line is updated to create case-insensitive pattern object
}
private String quote(String s, int start, int end) {
if (start == end) {
return "";
}
return Pattern.quote(s.substring(start, end));
}
/**
* Main entry point.
*
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
*/
public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
Matcher matcher = pattern.matcher(str);
if (matcher.matches()) {
if (uriTemplateVariables != null) {
// SPR-8455
Assert.isTrue(variableNames.size() == matcher.groupCount(),
"The number of capturing groups in the pattern segment " + pattern +
" does not match the number of URI template variables it defines, which can occur if " +
" capturing groups are used in a URI template regex. Use non-capturing groups instead.");
for (int i = 1; i <= matcher.groupCount(); i++) {
String name = this.variableNames.get(i - 1);
String value = matcher.group(i);
uriTemplateVariables.put(name, value);
}
}
return true;
}
else {
return false;
}
}
Im Frühjahr 3.2+/Frühjahr-Boot können Sie jetzt Groß- und Kleinschreibung URL-Zuordnung einrichten Verwenden der vereinfachten Java-Konfiguration.
Zuerst müssen Sie die CaseInsensitivePathMatcher.groovy oder Java-Klasse erstellen:
import org.springframework.util.AntPathMatcher
class CaseInsensitivePathMatcher extends AntPathMatcher{
@Override
protected boolean doMatch(String pattern, String path, boolean fullMatch, Map<String, String> uriTemplateVariables) {
super.doMatch(pattern.toLowerCase(), path.toLowerCase(), fullMatch, uriTemplateVariables)
}
}
Als nächstes, damit dies geschieht, Sie eine Klasse haben sollte, mit Federn @Configuration kommentierten, die die WebMvcConfigurerAdapter-Klasse erweitert, wie unten dargestellt (Beachten Sie, dass mein Code darin enthalten ist.groovy Klassen):
@Configuration
public class ApplicationConfig extends WebMvcConfigurerAdapter
dann die folgenden zwei Methoden zur Klasse hinzufügen:
/**
* Creates a patchMatcher bean that matches case insensitively
* @return PathMatcher
*/
@Bean
public PathMatcher pathMatcher() {
new CaseInsensitivePathMatcher()
}
/**
* Overrides the configurePathMatch() method in WebMvcConfigurerAdapter
* <br/>Allows us to set a custom path matcher, used by the MVC for @RequestMapping's
* @param configurer
*/
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.pathMatcher = pathMatcher()
}
}
, dass es, sollten Sie jetzt mit minimaler Konfiguration
Zwei Jahre später, aber immer noch ... 'WebMvcConfigurerAdapter' in Frühling 3.2 hat nicht die Methode' configurePathMatch'. Die minimale Spring-Version ist nicht korrekt, wahrscheinlich 4,2 wie in den Antworten oben angegeben. Weitere Informationen über http://docs.spring.io/spring/docs/3.2.13.RELEASE/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.html – Alf
die alle Setup für Groß- und Kleinschreibung URL sein Spring 4.2 will support case-insensitive path matching. Sie können es wie folgt konfigurieren:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
AntPathMatcher matcher = new AntPathMatcher();
matcher.setCaseSensitive(false);
configurer.setPathMatcher(matcher);
}
}
Beispiel aus einer Bean-Datei in Spring 4.2 und dies wird nur dann unterstützt v4.2 +:
<mvc:annotation-driven validator="validator">
<mvc:path-matching path-matcher="pathMatcher" />
</mvc:annotation-driven>
...
<!--Set endpoints case insensitive, spring is case-sensitive by default-->
<bean id="pathMatcher" class="org.springframework.util.AntPathMatcher">
<property name="caseSensitive" value="false" />
</bean>
- 1. Spring Web: Controller mit annotierten Zuordnungen - Getting HttpServletRequest/Formulardaten
- 2. URLs in Groß- und Kleinschreibung mit mod_rewrite
- 3. Wie mache ich URLs Groß-und Kleinschreibung in Linux-Server
- 4. Wie benutze ich Comet mit Spring MVC?
- 5. Ist der Protokollname in URLs Groß-/Kleinschreibung?
- 6. Spring MVC Request Mapping, kann dies dynamisch/konfigurierbar sein?
- 7. Wie kann ich das Attribut "required" in Spring-MVC hinzufügen?
- 8. Wie kann ich Whitespace von Anforderungsparametern in Spring MVC
- 9. Wie kann ich eine 403 Forbidden in Spring MVC zurückgeben?
- 10. CXF und mehrere Servlet-Zuordnungen
- 11. Helicon Isapi Rewrite - kann nicht URLs zu Groß-und Kleinschreibung
- 12. Apache mod_speling Groß- und Kleinschreibung URLs Problem
- 13. Wie übergebe ich Argumente an Spring AOP-Ratschläge mit annotierten Parametern?
- 14. Wie entspricht das URL-Muster eines Servlets den MVC-Zuordnungen von Spring?
- 15. Spring MVC: Mapping mehrere URLs zu gleichen Controller
- 16. Wie erstellt man URLs in MVC?
- 17. Wie erstelle ich SEO-Friendly URLs in ASP.Net-MVC
- 18. Spring MVC Interceptor wird für Ressourcenhandler-URLs nicht ausgeführt
- 19. Wo kann ich AutoMapper-Zuordnungen in einem Orchard-Modul initialisieren?
- 20. Rails-App Groß- und Kleinschreibung beachten URLs
- 21. Anmerkungen in Spring MVC
- 22. Wie kann ich alle URLs in "/" umschreiben?
- 23. Wie soll ich einen mit zusätzlichen Informationen annotierten AST darstellen?
- 24. Cookies. Groß- und Kleinschreibung sensible Pfade. Wie man URLs umschreibt
- 25. Wie @RefreshScope mit @ EnableBinding-annotierten Klassen verwenden?
- 26. Spring WEB security: Liste der verfügbaren URLs
- 27. Optionale Pfadsegmente in Spring MVC
- 28. Wie setze ich Priorität auf Spring MVC Mapping?
- 29. Wie kann ich verhindern, dass Spring MVC eine Umleitung ausführt?
- 30. Spring MVC: Wie bekomme ich aktuelle URL in Thymeleaf
Fügen Sie außerdem den Tag ‚Java‘ es wird Ihnen viel mehr Seitenaufrufe ergeben, die in der Regel mehr Antworten bedeutet. –
ähnliche Frage mit detaillierter Antwort zu diesem Problem habe ich nach dem Sehen dieser Frage gefragt. http://stackoverflow.com/questions/12684183/case-insensitive-mapping-for-spring-mvc-requestmapping-annotations/12732550 –