Tuckey URL Rewrite Filter Конфигурация класса Java

Я исследовал, как выполнить перезапись URL-адресов на Tomcat 8, и продолжаю сталкиваться с одними и теми же двумя предложениями.

1) Используйте Tukey URLRewriteFilter. 2) Запустите Apache поверх Tomcat, чтобы использовать mod_rewrite.

Что касается первого, URLRewriteFilter, похоже, не имеет документации о том, как настроить в формате Java, а не в формате XML. Мое приложение Spring MVC не использует файл web.xml - вся конфигурация выполняется с помощью классов Java, поэтому я не могу настроить с помощью XML.

Есть ли способ настроить таким образом или есть ли хорошие альтернативы, кроме попытки запустить Apache поверх Tomcat?

Например, есть ли способ добиться этого в Java, а не в XML:

<filter>
   <filter-name>UrlRewriteFilter</filter-name>
   <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

Это мой класс WebApplicationInitializer:

public class Initializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext container) {
  // Create the 'root' Spring application context
  AnnotationConfigWebApplicationContext rootContext =
    new AnnotationConfigWebApplicationContext();
  rootContext.register(RootConfig.class);

  // Manage the lifecycle of the root application context
  container.addListener(new ContextLoaderListener(rootContext));

  // Create the dispatcher servlet's Spring application context
  AnnotationConfigWebApplicationContext dispatcherContext =
    new AnnotationConfigWebApplicationContext();
  dispatcherContext.register(WebAppConfig.class);

  // Register and map the dispatcher servlet
  ServletRegistration.Dynamic dispatcher =
    container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
  dispatcher.setLoadOnStartup(1);
  dispatcher.addMapping("/*");
  dispatcher.addMapping("*.html");
} 

}

Моя корневая конфигурация

@Configuration
@ComponentScan(basePackages={"com.ucrisko.*"},
    excludeFilters={
      @ComponentScan.Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
    })
public class RootConfig {

}

И мой WebAppConfig

@Configuration
@EnableWebMvc
@ComponentScan(basePackages={"com.ucrisko.*"})
public class WebAppConfig extends WebMvcConfigurerAdapter{

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}

...various other beans
}

person Ravioli87    schedule 02.10.2015    source источник


Ответы (1)


В Spring Boot вы можете просто определить фильтр как bean-компонент в своей конфигурации. Я не уверен, что это работает в простом Spring MVC, но вы можете попробовать. Одна неудобная вещь — настройка фильтра из java-кода — вам придется реализовать FilterConfig. Рабочий пример Spring Boot выглядит так (фрагмент из класса конфигурации):

@Bean
public UrlRewriteFilter urlRewriteFilter(final ServletContext servletContext) throws ServletException {
    UrlRewriteFilter urlRewriteFilter = new UrlRewriteFilter();
    urlRewriteFilter.init(new FilterConfig() {
        private final Map<String, String> params = new HashMap<String, String>();
        {
            params.put("confPath", "urlrewrite.xml");
        }

        @Override
        public String getFilterName() {
            return "UrlReriteFilter";
        }

        @Override
        public ServletContext getServletContext() {
            return servletContext;
        }

        @Override
        public String getInitParameter(String name) {
            return params.get(name);
        }

        @Override
        public Enumeration<String> getInitParameterNames() {
            return Collections.enumeration(params.keySet());
        }
    });

    return urlRewriteFilter;
}

Что касается обычного Spring MVC, кажется, вам следует реализовать WebApplicationInitializer. WebApplicationInitializer — это код Java, эквивалентный конфигурации web.xml. Согласно документации, Spring должен брать реализации из пути к классам и запускать их. Пример реализации может выглядеть так (Примечание: я не проверял, работает ли это, но это должно направить вас на правильный путь):

public class Initalizer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {WebAppConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {"/*", "*.html"};
    }

    @Override
    protected Filter[] getServletFilters() {
        UrlRewriteFilter urlRewriteFilter = new UrlRewriteFilter();
        /*
         * Add filter configuration here if necessary
         */
        return new Filter[] {urlRewriteFilter};
    }
}

AbstractAnnotationConfigDispatcherServletInitializer — это реализация Spring интерфейса WebApplicationInitializer с намерением упростить инициализацию DispcherServlet (которая является точкой входа Spring MVC). В этом примере WebAppConfig.class — ваш основной класс конфигурации Java Spring.

ИЗМЕНИТЬ

Если вы предпочитаете сохранить текущий код инициализатора, также можно добавить следующие строки в метод onStartup:

FilterRegistration.Dynamic urlRewriteFilter = servletContext.addFilter("urlRewriteFilter",  new UrlRewriteFilter());
urlRewriteFilter.setInitParameter("confPath", "urlrewrite.xml");
urlRewriteFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD), false, "/*");

Этот отрывок основан на ответе, доступном здесь: Как выполнить сопоставление фильтров в AbstractAnnotationConfigDispatcherServletInitializer Spring

person Krešimir Nesek    schedule 03.10.2015
comment
Верхняя часть вашего ответа, похоже, работает хотя бы частично. В моем журнале сервера я получаю org.apache.catalina.core.ApplicationContext.log org.tuckey.web.filters.urlrewrite.UrlRewriteFilter INFO: загружен (conf ok), и, похоже, он может найти мой файл urlrewrite.xml. Тем не менее, я не переписываю URL-адреса. Например, следующее не заканчивается попыткой перенаправления на страницу index.html. ‹rule› ‹from›^users‹/from› ‹to type=redirect›index.html‹/to› ‹/rule› - person Ravioli87; 05.10.2015
comment
Если ничего не происходит, то Spring, вероятно, просто создает экземпляр класса UrlRewriteFilter (вызывая сообщения журнала, которые вы видите), но фактически не регистрирует фильтр (другими словами, он не работает). Что произойдет, если вы попробуете с подходом снизу? Как вы начинаете свое приложение Spring MVC? (например, у вас есть класс, который реализует интерфейс WebApplicationInitializer? Где вы указываете свой основной класс конфигурации javaconfig?) - person Krešimir Nesek; 05.10.2015
comment
Да, у меня есть WebApplicationInitializer, но он немного отличается от вашего. Я добавлю это к моему вопросу выше. - person Ravioli87; 05.10.2015
comment
Я отредактировал пример кода, чтобы он соответствовал вашему текущему WebApplicationInitializer. AbstractAnnotationConfigDispatcherServletInitializer кажется предпочтительным способом инициализации DispatcherServlet в Spring, а также упрощает регистрацию фильтров. Если вы предпочитаете использовать собственную реализацию, взгляните на исходный код AbstractAnnotationConfigDispatcherServletInitializer и посмотрите, как он регистрирует фильтры с помощью getServletFilters. - person Krešimir Nesek; 05.10.2015
comment
Я также отредактировал свой ответ, включив в него код, который должен применяться к вашему текущему WebApplicationInitializer - person Krešimir Nesek; 05.10.2015
comment
Потрясающий! Оба они работают. На самом деле я довольно близко подобрался к решению с помощью FilterRegistration.Dynamic, но изначально не настроил его должным образом. Я воспользуюсь вашим советом и переключу свой класс Initializer на формат, который у вас есть здесь. Спасибо за вашу помощь! - person Ravioli87; 05.10.2015