如何将 Spring MVC 控制器映射到带有和不带有斜杠的 uri?
Posted
技术标签:
【中文标题】如何将 Spring MVC 控制器映射到带有和不带有斜杠的 uri?【英文标题】:How do I map Spring MVC controller to a uri with and without trailing slash? 【发布时间】:2012-08-16 03:14:20 【问题描述】:我有一个 Spring 控制器,其中包含用于不同 URI 的多个 RequestMapping。我的 servlet 是“ui”。 servlet 的基本 URI 仅适用于尾部斜杠。我希望我的用户不必输入斜杠。
此 URI 有效:
http://localhost/myapp/ui/
这个没有:
http://localhost/myapp/ui
它给了我一个 HTTP 状态 404 消息。
我的 web.xml 中的 servlet 和映射是:
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
我的控制器:
@Controller
public class UiRootController
@RequestMapping(value="","/")
public ModelAndView mainPage()
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
@RequestMapping(value="/other")
public ModelAndView otherPage()
DataModel model = initModel();
model.setView("otherPage");
return new ModelAndView("other", "model", model);
【问题讨论】:
将 web xml 中的 url 模式从 /ui/* 更改为 /ui @Sajan,我应该包括其他 RequestMappings。 (请参阅编辑)将模式从 /ui/* 更改为 /ui 会破坏所有映射,对于 URI /ui、/ui/ 和 /ui/other,我得到 404 webapp 在 Tomcat 中部署到什么上下文?您的应用程序是名为ROOT.war
还是 <another_name>.war
还是该应用程序仅存在于 webapps 下的目录中?
@andyb,它被部署到另一个上下文。在我的示例中,我使用“myapp”。我认为这应该有效吗?
不,它绝对应该按预期工作。您使用的是哪个版本的 Spring?另外,你是如何配置Spring的,比如<context:component-scan base-package="..."/>
?
【参考方案1】:
PathMatchConfigurer api 允许您配置各种设置 与 URL 映射和路径匹配有关。根据最新版本的 spring,默认启用路径匹配。如需自定义,请查看以下示例。
对于基于 Java 的配置
@Configuration
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter
@Override
public void configurePathMatch(PathMatchConfigurer configurer)
configurer.setUseTrailingSlashMatch(true);
对于基于 XML 的配置
<mvc:annotation-driven>
<mvc:path-matching trailing-slash="true"/>
</mvc:annotation-driven>
对于 @RequestMapping("/foo"),如果尾部斜杠匹配设置为 false,example.com/foo/ != example.com/foo 并且如果它设置为 true(默认),example.com/foo/ == example.com/foo
干杯!
【讨论】:
不知道这个属性。谢谢!【参考方案2】:使用 Springboot,我的应用程序可以通过将 @RequestMapping 的“值”选项设置为空字符串来回复带有和不带有斜杠:
@RestController
@RequestMapping("/some")
public class SomeController
// value = "/" (default) ,
// would limit valid url to that with trailing slash.
@RequestMapping(value = "", method = RequestMethod.GET)
public Collection<Student> getAllStudents()
String msg = "getting all Students";
out.println(msg);
return StudentService.getAllStudents();
【讨论】:
【参考方案3】:尝试添加
@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
【讨论】:
高级 @RequestMapping 技巧 - 这是一个损坏的链接。请更新新的或删除链接。【参考方案4】:我找到的另一个解决方案是不给 mainPage() 的请求映射一个值:
@RequestMapping
public ModelAndView mainPage()
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
【讨论】:
迄今为止唯一适用于 mi 的解决方案,谢谢!【参考方案5】:如果您的 Web 应用程序存在于 Web 服务器的 webapps 目录中,例如 webapps/myapp/
,则可以在 http://localhost:8080/myapp/
访问此应用程序上下文的根,假设默认 Tomcat 端口。这应该可以使用或不使用斜杠,我认为默认情况下 - 当然在 Jetty v8.1.5 中就是这种情况
一旦您点击/myapp
,Spring DispatcherServlet 就会接管,将请求路由到您在web.xml
中配置的<servlet-name>
,在您的情况下为/ui/*
。
然后 DispatcherServlet 将所有来自 http://localhost/myapp/ui/
的请求路由到 @Controller
s。
在 Controller 本身中,您可以将 @RequestMapping(value = "/*")
用于 mainPage() 方法,这将导致 http://localhost/myapp/ui/
和http://localhost/myapp/ui
被路由到 mainPage()。
注意:由于SPR-7064,您还应该使用 Spring >= v3.0.3
为了完整起见,以下是我测试过的文件:
src/main/java/controllers/UIRootController.java
package controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class UiRootController
@RequestMapping(value = "/*")
public ModelAndView mainPage()
return new ModelAndView("index");
@RequestMapping(value="/other")
public ModelAndView otherPage()
return new ModelAndView("other");
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" metadata-complete="false">
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml -->
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
</web-app>
WEB-INF/ui-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="controllers" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:order="2"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
</beans>
还有WEB-INF/views/index.jsp
和WEB-INF/views/other.jsp
的2 个JSP 文件。
结果:
http://localhost/myapp/
-> 目录列表
http://localhost/myapp/ui
和 http://localhost/myapp/ui/
-> index.jsp
http://localhost/myapp/ui/other
和 http://localhost/myapp/ui/other/
-> other.jsp
希望这会有所帮助!
【讨论】:
【参考方案6】:我最终添加了一个新的 RequestMapping 来将 /ui 请求重定向到 /ui/。 还从 mainPage 的 RequestMapping 中删除了空字符串映射。 无需对 web.xml 进行编辑。
在我的控制器中结束了这样的事情:
@RequestMapping(value="/ui")
public ModelAndView redirectToMainPage()
return new ModelAndView("redirect:/ui/");
@RequestMapping(value="/")
public ModelAndView mainPage()
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
@RequestMapping(value="/other")
public ModelAndView otherPage()
DataModel model = initModel();
model.setView("otherPage");
return new ModelAndView("other", "model", model);
现在 URL http://myhost/myapp/ui
重定向到 http://myhost/myapp/ui/
,然后我的控制器显示介绍页面。
【讨论】:
以上是关于如何将 Spring MVC 控制器映射到带有和不带有斜杠的 uri?的主要内容,如果未能解决你的问题,请参考以下文章
Spring 3 MVC - 将带有前缀的请求参数映射到单个 bean
带有 @PathVariable 的 Spring MVC 带注释的控制器接口
Ajax 将“映射”对象传递给 Spring MVC 控制器
Spring MVC 控制器问题:找不到带有 URI 的 HTTP 请求的映射