简体   繁体   English

Spring WebFilter映射

[英]Spring WebFilter Mapping

I'm trying to add a WebFilter in my spring application. 我试图在我的Spring应用程序中添加WebFilter。 However, I'm not using .xml files (not even a web.xml, because my application does not need it). 但是,我没有使用.xml文件(甚至没有使用web.xml,因为我的应用程序不需要它)。

So, I added to my class that extends AbstractAnnotationConfigDispatcherServletInitializer : 因此,我将添加到扩展AbstractAnnotationConfigDispatcherServletInitializer类中:

@Override
protected Filter[] getServletFilters() {
    return new Filter[]{new RequestFilter()};
}

And, my RequestFilter.java: 而且,我的RequestFilter.java:

@WebFilter("/test/*")
public class RequestFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException { }

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException { }

@Override
public void destroy() { }

I'm expecting that only requests matching /test/* pattern be filtered, but a request to any resource is filtered. 我期望只过滤匹配/test/*模式的请求,但是过滤对任何资源的请求。

How I can mapping my filter? 如何映射过滤器?

Thanks. 谢谢。

@WebFilter - is not a Spring annotation. @WebFilter不是Spring注释。 Spring ignores it. Spring忽略了它。 Method getServletFilters returns an array of filters without mapping them to URLs. 方法getServletFilters返回一个过滤器数组,而不将它们映射到URL。 So they triggered on every request. 因此,它们在每次请求时都会触发。 If you don't want to write url-mappings in web.xml, you can use HandlerInterceptor instead of Filter . 如果您不想在web.xml中编写url映射,则可以使用HandlerInterceptor而不是Filter They can be mapped programmatically in the DispatcherServletInitializer : 可以在DispatcherServletInitializer中以编程方式映射它们:

public class SomeInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        // ...
        return true;
    }
}

@Configuration
@ComponentScan("com.example")
@EnableWebMvc  
public class AppConfig extends WebMvcConfigurerAdapter  {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
          .addInterceptor(new SomeInterceptor())
          .addPathPatterns("/test/*");
    }
}

public class WebAppInitializer implements WebApplicationInitializer {
    public void onStartup(ServletContext servletContext) throws ServletException {  
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(AppConfig.class);  
        ctx.setServletContext(servletContext);    
        Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        dynamic.addMapping("/");  
        dynamic.setLoadOnStartup(1);  
   }  
}

Or you can define you own WebFilter annotation! 或者,您可以定义自己的WebFilter注释!

At first, you need utility class for matching URL patterns: 首先,您需要实用程序类来匹配URL模式:

public class GlobMatcher {
    public static boolean match(String pattern, String text) {
        String rest = null;
        int pos = pattern.indexOf('*');
        if (pos != -1) {
            rest = pattern.substring(pos + 1);
            pattern = pattern.substring(0, pos);
        }

        if (pattern.length() > text.length())
            return false;

        for (int i = 0; i < pattern.length(); i++)
            if (pattern.charAt(i) != '?' 
                    && !pattern.substring(i, i + 1).equalsIgnoreCase(text.substring(i, i + 1)))
                return false;

        if (rest == null) {
            return pattern.length() == text.length();
        } else {
            for (int i = pattern.length(); i <= text.length(); i++) {
                if (match(rest, text.substring(i)))
                    return true;
            }
            return false;
        }
    }
}

Annotation itself: 注释本身:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface WebFilter {
    String[] urlPatterns();
}

Pass-through functionality of URL pattern matching: URL模式匹配的传递功能:

@Aspect
public class WebFilterMatcher {
    @Pointcut("within(@com.example.WebFilter *)")
    public void beanAnnotatedWithWebFilter() {}

    @Pointcut("execution(boolean com.example..preHandle(..))")
    public void preHandleMethod() {}

    @Pointcut("preHandleMethod() && beanAnnotatedWithWebFilter()")
    public void preHandleMethodInsideAClassMarkedWithWebFilter() {}

    @Around("preHandleMethodInsideAClassMarkedWithWebFilter()")
    public Object beforeFilter(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if(args.length > 0) {
            HttpServletRequest request = (HttpServletRequest) args[0];
            Class target = joinPoint.getTarget().getClass();
            if (target.isAnnotationPresent(WebFilter.class)) {
                String[] patterns = ((WebFilter) target.getAnnotation(WebFilter.class)).urlPatterns();
                for (String pattern : patterns) {
                    if (GlobMatcher.match(pattern, request.getRequestURI())) {
                        return joinPoint.proceed();
                    }
                }
            }
        }
        return true;
    }
}

Interceptor: 拦截器:

@WebFilter(urlPatterns = {"/test/*"})
public class SomeInterceptor extends HandlerInterceptorAdapter { 
    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
        // ...
        return true; 
    }
}

And a little change in context configuration: 和上下文配置的一点变化:

<beans> <!-- Namespaces are omitted for brevity -->
  <aop:aspectj-autoproxy />

  <bean id="webFilterMatcher" class="com.example.WebFilterMatcher" />

  <mvc:interceptors>
    <bean class="com.example.SomeInterceptor" />
  </mvc:interceptors>
</beans>

您可以将@Component批注添加到过滤器实现中,如果使用Spring Boot,则可以将@ServletComponentScan添加到主类中。

Another option is to register the custom filter class using a FilterRegistrationBean and NOT adding the filter itself as a bean. 另一个选择是使用FilterRegistrationBean注册自定义过滤器类,而不将过滤器本身添加为Bean。 example: 例:

@Bean
public FilterRegistrationBean<RequestResponseLoggingFilter> loggingFilter(){
    FilterRegistrationBean<RequestResponseLoggingFilter> registrationBean 
      = new FilterRegistrationBean<>();

    registrationBean.setFilter(new RequestResponseLoggingFilter());
    registrationBean.addUrlPatterns("/users/*");            
    return registrationBean;    
}

taken from: https://www.baeldung.com/spring-boot-add-filter 摘自: https : //www.baeldung.com/spring-boot-add-filter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM