Spring @RequestMapping для всего, кроме / api / или / rest / (отрицать специфицированное c слово в регулярном выражении) - PullRequest
0 голосов
/ 26 мая 2020

Мне нужен Spring @RequestMapping, который я буду использовать для сопоставления всех не- /api/... путей, таких как /products, чтобы перенаправить их на мой / (по return "forward:/";) контроллер представления, который фактически обслуживает index.html содержимое и вызывает обслуживание внешнего (React) приложения, чтобы оно могло обрабатывать этот путь для рендеринга страницы.

Обратите внимание, что неявно этот @RequestMapping не может соответствовать /, так как он закончится бесконечным повторение и StackOverflowError. Возможно, стоит также исключить index.html.

Другими словами, я хочу, чтобы мой /api/products обрабатывался «локально» приложением Spring Boot, где /products/ должен быть перенаправлен для рендеринга приложения React. Нет прокси Apache или Nginx - приложение React обслуживается Spring благодаря сопоставлениям ресурсов stati c.

Я изучил много похожих вопросов по Stackoverflow в этой области, и ни один из них не работает.

Важное примечание : я видел случаи в Stackoverflow, где проблема должна была быть решена только потому, что изначально это выглядело как работающее (/products/ перенаправлено и /api/products обрабатывается контроллером API) , но на самом деле это не так, потому что предлагаемое регулярное выражение соответствовало всему, и /api/products обрабатывались только приоритетами сопоставления Spring (подробнее c "выигрывает"), но тот же путь фактически соответствовал шаблон, если не существует другого контроллера.

Это приводит к несоответствующей обработке ошибок 404 (или отображение не найдено) - вызов любой, даже несуществующей /api/something конечной точки заканчивается переадресацией на индекс. html во всех найденных мной ответах, которые я хочу избежать. Доступ к несуществующей конечной точке /api/something должен скорее закончиться тем, что обработчик не найден Ошибка Spring, а не вперед. Пример такого решения является наиболее популярным, например: @RequestMapping(value = "{_:^(?!api).*$}")

Проблема в том, что какой бы шаблон я ни пробовал, он пересылает все мои тестовые примеры (например, /api /api/ /api/x /page/ /page/2 или ничего.

Просто несколько примеров шаблоны, которые я пробовал:

@RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
@RequestMapping(value = "{x:^(?!api).*$}") 
@RequestMapping(value = "/{path:^(?!api/).*$}")
@RequestMapping(value = "/{dataType:^.*(?!api).*$}")
@RequestMapping(value = "/{arg:(?!sitemap.xml|api|index.html).*$}")
@RequestMapping(value = "{arg:^(?!api|!index.html).*$}/**")
@RequestMapping(value = "{_:^(?!index\\.html|api).*$}")

Ответы [ 2 ]

0 голосов
/ 30 мая 2020

Похоже, что исходное регулярное выражение действительно работает (например, "{_:^(?!index\\.html|api).*$}").

Проблема в том, что Jetty для отображения 404 внутренне перенаправлял на страницу /error, которая также была предметом сопоставления этого контроллера! Эффективная пересылка во внешнее приложение из ресурсов publi c вместо отображения страницы ошибки

0 голосов
/ 26 мая 2020

Вопрос все еще актуален, но для людей, которым нужно решение, я могу предложить направить его на уровне фильтра:

 @Bean
    public FilterRegistrationBean nonApiRequestToRootPathForwarderFilterRegistrationbean() {
        FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
        filterFilterRegistrationBean.setFilter(new Filter() {
            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                HttpServletRequest request1 = (HttpServletRequest) request;
                if (!request1.getRequestURI().startsWith("/api/") && !request1.getRequestURI().equals("/")) {
                    RequestDispatcher requestDispatcher = request.getRequestDispatcher("/");
                    requestDispatcher.forward(request, response);
                    return;
                }

                chain.doFilter(request, response);
            }
        });
        return filterFilterRegistrationBean;
    }
...