如何将 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 还是 &lt;another_name&gt;.war 还是该应用程序仅存在于 webapps 下的目录中? @andyb,它被部署到另一个上下文。在我的示例中,我使用“myapp”。我认为这应该有效吗? 不,它绝对应该按预期工作。您使用的是哪个版本的 Spring?另外,你是如何配置Spring的,比如&lt;context:component-scan base-package="..."/&gt; 【参考方案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 中配置的&lt;servlet-name&gt;,在您的情况下为/ui/*

然后 DispatcherServlet 将所有来自 http://localhost/myapp/ui/ 的请求路由到 @Controllers。

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.jspWEB-INF/views/other.jsp 的2 个JSP 文件。

结果:

http://localhost/myapp/ -> 目录列表 http://localhost/myapp/uihttp://localhost/myapp/ui/ -> index.jsp http://localhost/myapp/ui/otherhttp://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 请求的映射

错误:没有找到带有 URI spring mvc 且没有 xml 的 HTTP 请求的映射

从spring mvc控制器返回一个简单的映射结构到ajax