Как сопоставить Spring контроллер MVC с uri с завершающей косой чертой и без нее?
У меня есть контроллер Spring с несколькими RequestMappings для разных URI. Мой сервлет - "ui". URI базы сервлета работает только с завершающей косой чертой. Я бы хотел, чтобы мои пользователи не вводили конечную косую черту.
Этот URI работает:
http://localhost/myapp/ui/
Этого нет:
http://localhost/myapp/ui
Он дает мне сообщение HTTP статуса 404.
Сервлет и отображение из моего web.xml:
<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);
}
}
Ответы
Ответ 1
Если ваше веб-приложение существует в каталоге webapps веб-сервера, например webapps/myapp/
, то к корню этого контекста приложения можно получить доступ в http://localhost:8080/myapp/
, предполагая порт Tomcat по умолчанию. Это должно работать с конечной косой чертой или без нее, я думаю, по умолчанию - конечно, это верно в Jetty v8.1.5
Как только вы нажмете /myapp
, Spring DispatcherServlet возьмет на себя запросы маршрутизации на <servlet-name>
, как указано в web.xml
, который в ваш случай /ui/*
.
Затем DispatcherServlet направляет все запросы от http://localhost/myapp/ui/
к @Controller
s.
В самом контроллере вы можете использовать @RequestMapping(value = "/*")
для метода mainPage(), который приведет к тому, что оба http://localhost/myapp/ui/
и http://localhost/myapp/ui
будут перенаправлены на mainPage().
Примечание: вы также должны использовать Spring >= v3.0.3 из-за SPR-7064
Для полноты, вот файлы, которые я тестировал с помощью:
SRC/основные/Java/контроллеры/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/щ-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.jsp
и WEB-INF/views/other.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
Надеюсь, это поможет!
Ответ 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 для перенаправления запросов /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/
, а затем мой контроллер отображает вводную страницу.
Ответ 4
Другим решением, которое я нашел, является не предоставление сопоставления запросов для mainPage() значение:
@RequestMapping
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
Ответ 5
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
Ура!
Ответ 6
попробуйте добавить
@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