我正在使用带有默认注释映射的Spring 3.2.2 Web MVC。我使用这样的servlet映射:
<servlet>
<servlet-name>profil</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>de.kicktipp.web.config.servlets.ProfilServletConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>profil</servlet-name>
<url-pattern>/info/profil/*</url-pattern>
</servlet-mapping>
这是我们的servlet配置:
@Configuration
@ComponentScan("de.kicktipp.controller")
@EnableWebMvc
public class ProfilServletConfig extends WebMvcConfigurerAdapter
{
@Override
public void addInterceptors ( InterceptorRegistry registry )
{
// we add a few interceptors here
}
@Bean
public DefaultRequestToViewNameTranslator viewNameTranslator ( )
{
DefaultRequestToViewNameTranslator defaultRequestToViewNameTranslator = new DefaultRequestToViewNameTranslator();
defaultRequestToViewNameTranslator.setStripExtension(false);
defaultRequestToViewNameTranslator.setAlwaysUseFullPath(false);
defaultRequestToViewNameTranslator.setPrefix("profil/");
return defaultRequestToViewNameTranslator;
}
}
通配符匹配非常重要,因为我们希望将许多网址与/info/profil/page1
,/info/profil/page2
等此模式匹配。
当我想匹配“基础”URL /info/profil
而没有尾部斜杠时,它会被servlet“profil”选中。
现在我尝试了三种控制器方法来匹配/info/profil
和处理程序方法:
@RequestMapping("/")
protected void get1 () {}
@RequestMapping("")
protected void get2 () {}
@RequestMapping("/info/profil")
protected void get3 () {}
只有最后一个有效。这是因为如果servlet中的路径是空字符串,则UrlPathHelper#getLookupPathForRequest(javax.servlet.http.HttpServletRequest)将返回应用程序中的完整路径:
public String getLookupPathForRequest(HttpServletRequest request) {
// Always use full path within current servlet context?
if (this.alwaysUseFullPath) {
return getPathWithinApplication(request);
}
// Else, use path within current servlet mapping if applicable
String rest = getPathWithinServletMapping(request);
if (!"".equals(rest)) {
return rest;
}
else {
return getPathWithinApplication(request);
}
}
对于“/ info / profil /”的请求,该方法将返回“/”,但对于“/ info / profil”(没有尾随斜杠),它将返回“/ info / profil”,因为其余变量为空string和teherfore方法返回pathWithinApplication。
其他路径通常与servlet映射内的路径匹配(因为alwaysUseFullPath默认为false)。但是“根”路径与应用程序内部的完整路径匹配(就像alwaysUseFullPath为true时一样)。
为什么会这样?为什么spring没有尝试匹配空字符串,而是尝试匹配应用程序中的路径?
答案 0 :(得分:2)
尝试添加
@RequestMapping(method = RequestMethod.GET)
public String list() {
return "redirect:/strategy/list";
}
结果:
@RequestMapping(value = "/strategy")
public class StrategyController {
static Logger logger = LoggerFactory.getLogger(StrategyController.class);
@Autowired
private StrategyService strategyService;
@Autowired
private MessageSource messageSource;
@RequestMapping(method = RequestMethod.GET)
public String list() {
return "redirect:/strategy/list";
}
@RequestMapping(value = {"/", "/list"}, method = RequestMethod.GET)
public String listOfStrategies(Model model) {
logger.info("IN: Strategy/list-GET");
List<Strategy> strategies = strategyService.getStrategies();
model.addAttribute("strategies", strategies);
// if there was an error in /add, we do not want to overwrite
// the existing strategy object containing the errors.
if (!model.containsAttribute("strategy")) {
logger.info("Adding Strategy object to model");
Strategy strategy = new Strategy();
model.addAttribute("strategy", strategy);
}
return "strategy-list";
}
**学分:
Advanced @RequestMapping tricks – Controller root and URI Template
和
答案 1 :(得分:0)
<强> [编辑] 强>
我看到你正在使用注释mvc配置。默认映射在应用程序中配置为“/”路径。要更改这些默认设置,您可以将web.xml编辑为此模板:
<web-app>
<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>de.kicktipp.controller.ProfilAppConfig</param-value>
</context-param>
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>de.kicktipp.controller.ProfilServletConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /info/profil/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/info/profil/*</url-pattern>
</servlet-mapping>
</web-app>
因此,您的应用程序中有de.kicktipp.controller.ProfilServletConfig
。只需检查de.kicktipp.controller.ProfilAppConfig
(contextClass)的第一个代码块是否真的有必要。
来源:Spring Docs