【问题标题】:Class to filter URLs for Spring Boot does not build未构建用于过滤 Spring Boot 的 URL 的类
【发布时间】:2019-10-03 04:51:52
【问题描述】:

这是一个使用 Maven 的 Spring Boot Java 项目。 如果我从 WebConfig 中删除 @Configuration 注释,则应用程序会构建,但该类似乎被忽略了。如果我包含它,应用程序将失败并显示以下消息:

启动 Tomcat 上下文时出错。例外: java.lang.ClassCastException。留言:
org.springframework.boot.web.servlet.DispatcherType 不能强制转换为 javax.servlet.DispatcherType。应用程序运行失败。

如何正确设置 Spring Boot 以使用过滤器?

这是主要的应用程序类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class GetJobDetailsApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(GetJobDetailsApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(GetJobDetailsApplication.class, args);
    }

}

这里是控制器:

import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainRESTController {

    // inject via application.properties
    @Value("${welcome.message:test}")
    private String message = "Hello World";

    @RequestMapping("/")
    public String welcome(Map<String, Object> model) {
        model.put("message", this.message);
        return "welcome";
    }

}

这是我设置过滤器的 WebConfig:

import org.owasp.filters.ClickjackFilter;
import org.springframework.boot.web.servlet.DispatcherType;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.ShallowEtagHeaderFilter;
import java.util.EnumSet;

@Configuration
public class WebConfig {

  @Bean
  public FilterRegistrationBean clickjackFilterRegistration() {

    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(clickjackFilter());
    registration.addUrlPatterns("/");
    registration.addInitParameter("paramName", "paramValue");
    registration.setName("clickjackFilter");
    registration.setOrder(1);
    return registration;
  }

  @Bean(name = "clickjackFilter")
  public ClickjackFilter clickjackFilter() {
    return new ClickjackFilter();
  }

  @Bean
  public FilterRegistrationBean shallowEtagHeaderFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new ShallowEtagHeaderFilter());
    registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
    registration.addUrlPatterns("/");
    return registration;
  }
}

这里是 clickjackFilter 类:

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class ClickjackFilter implements Filter {

  private String mode = "DENY";

  /**
   * Add X-FRAME-OPTIONS response header to tell IE8 (and any other browsers who
   * decide to implement) not to display this content in a frame. For details, please
   * refer to http://blogs.msdn.com/sdl/archive/2009/02/05/clickjacking-defense-in-ie8.aspx.
   */
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    HttpServletResponse res = (HttpServletResponse) response;
    res.addHeader("X-FRAME-OPTIONS", mode);
    chain.doFilter(request, response);
  }

  public void destroy() {
  }

  public void init(FilterConfig filterConfig) {
    String configMode = filterConfig.getInitParameter("mode");
    if (configMode != null) {
      mode = configMode;
    }
  }
}

pom.xml 文件中的依赖关系:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-jaxrs</artifactId>
            <version>1.5.9</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-core</artifactId>
            <version>${apachetiles.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-jsp</artifactId>
            <version>${apachetiles.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-extras</artifactId>
            <version>${apachetiles.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-api</artifactId>
            <version>${apachetiles.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-servlet</artifactId>
            <version>${apachetiles.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

        <!-- Tomcat embedded container-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- JSTL for JSP -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- Need this to compile JSP,
         tomcat-embed-jasper version is not working -->
        <dependency>
            <groupId>org.eclipse.jdt.core.compiler</groupId>
            <artifactId>ecj</artifactId>
            <version>4.6.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- Optional, test for static content, bootstrap CSS-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>
    </dependencies>

【问题讨论】:

  • 可能是 POM 依赖范围。可能感兴趣:stackoverflow.com/questions/17799295/…
  • 谢谢,我会尝试,明天我会发布 pom.xml,但我怀疑我设置过滤器和配置 Spring Boot 的方式是错误的。
  • 我认为导入是错误的。 FilterRegistrationBean 需要 javax.servlet.DispatcherType 而不是 org.springframework.boot.web.servlet.DispatcherType
  • 您知道应该将什么名称和值传递给 addInitParameter 调用吗?只要名字是唯一的就可以了吗? registration.addInitParameter("paramName", "paramValue");

标签: java spring maven spring-boot filter


【解决方案1】:

仔细查看您的堆栈跟踪,您可以尝试将 DispatcherType 设置为

 java.lang.Object
    java.lang.Enum<DispatcherType>
        javax.servlet.DispatcherType 

因为FilterRegistrationBean 需要javax.servlet.DispatcherType 类型的参数用于集合setDispatcherTypes()

或者您可以使用以下注释直接注册过滤器 bean:

@Order(Ordered.LOWEST_PRECEDENCE -1)
@Component
public class ABCFilter implements Filter {
  ------
} 

在 spring boot 中通常你配置过滤器:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  @Autowired 
  HandlerInterceptor customInjectedInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(...)
    ... 
    registry.addInterceptor(customInjectedInterceptor).addPathPatterns("/**");
  }
}

或者如果您使用的是 Spring 5x,那么:

@Configuration
public WebConfig implements WebMvcConfigurer {
    // ...
}

通过这样做,我们实质上是在自定义 spring boot 自动配置 bean,因此 springboot 仍然可以自动配置所有其他的东西。如果您正在使用 springboot,请考虑删除 @EnableWebMvc 并使用 springboot 的自动配置。

【讨论】:

  • 谢谢,我将 pom.xml 文件中的依赖项添加到问题中。我正在使用 Spring Boot 2.1.4.RELEASE。要使用 Spring 5x,我是否需要添加另一个依赖项,例如:mvnrepository.com/artifact/org.springframework/spring-web/…
  • 将导入类型更改为 javax.servlet.DispatcherType 有效!您知道应该将什么名称和值传递给 addInitParameter 调用吗?只要名字是唯一的就可以了吗? registration.addInitParameter("paramName", "paramValue");
  • 深入研究,我看到 AbstractFilterRegistrationBean 中的 setDispatcherTypes 采用 EnumSet 并且枚举 DispatcherType 在包 javax.servlet 中。
猜你喜欢
  • 2017-02-04
  • 2015-05-26
  • 1970-01-01
  • 2021-10-29
  • 2019-01-06
  • 2020-07-27
  • 2014-08-31
  • 2015-04-02
  • 2018-03-09
相关资源
最近更新 更多