23

我有一个 Spring 控制器,其中包含用于不同 URI 的多个 RequestMappings。我的 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);
    }

}
4

6 回答 6

18

使用 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();
    }
}
于 2016-12-16T20:49:37.097 回答
14

例如,如果您的 Web 应用程序存在于 Web 服务器的 webapps 目录中,webapps/myapp/则可以在http://localhost:8080/myapp/假定默认 Tomcat 端口时访问此应用程序上下文的根目录。我认为默认情况下,这应该使用或不使用斜杠- 当然在 Jetty v8.1.5 中就是这种情况

一旦您点击/myappSpring DispatcherServlet接管,将请求路由到您的<servlet-name>配置web.xml,在您的情况下是/ui/*.

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

控制器本身中,您可以使用@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>

还有 2 个 JSP 文件位于WEB-INF/views/index.jspWEB-INF/views/other.jsp.

结果:

  • http://localhost/myapp/-> 目录列表
  • http://localhost/myapp/uihttp://localhost/myapp/ui/-> index.jsp
  • http://localhost/myapp/ui/otherhttp://localhost/myapp/ui/other/-> other.jsp

希望这可以帮助!

于 2012-08-22T15:13:58.247 回答
12

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

干杯!

于 2017-07-22T20:02:31.490 回答
3

我最终添加了一个新的 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);
    }

现在 URLhttp://myhost/myapp/ui重定向到http://myhost/myapp/ui/,然后我的控制器显示介绍页面。

于 2012-08-21T16:24:51.333 回答
2

我发现的另一个解决方案是不给 mainPage() 的请求映射一个值:

@RequestMapping
public ModelAndView mainPage() { 
    DataModel model = initModel();
    model.setView("intro");     
    return new ModelAndView("main", "model", model);
}
于 2015-03-24T19:43:01.410 回答
1

尝试添加

@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";
    }  

** 学分:

高级@RequestMapping技巧——控制器根和URI模板

于 2014-05-14T14:06:53.273 回答