Java SpringWebFilter映射
我正在尝试在spring应用程序中添加WebFilter。但是,我没有使用.xml文件(甚至不是web.xml,因为我的应用程序不需要它) 因此,我向类中添加了扩展Java SpringWebFilter映射,java,spring,spring-mvc,servlet-filters,Java,Spring,Spring Mvc,Servlet Filters,我正在尝试在spring应用程序中添加WebFilter。但是,我没有使用.xml文件(甚至不是web.xml,因为我的应用程序不需要它) 因此,我向类中添加了扩展AbstractAnnotationConfigDispatcherServletInitializer: @Override protected Filter[] getServletFilters() { return new Filter[]{new RequestFilter()}; } public class S
AbstractAnnotationConfigDispatcherServletInitializer
:
@Override
protected Filter[] getServletFilters() {
return new Filter[]{new RequestFilter()};
}
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);
}
}
还有,my 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() { }
我希望只过滤匹配/test/*
模式的请求,但过滤对任何资源的请求
如何映射我的过滤器
谢谢。
@WebFilter
-不是Spring注释。Spring忽略了它。方法getServletFilters
返回筛选器数组,而不将它们映射到URL。所以每一个请求都会触发。如果不想在web.xml中编写url映射,可以使用而不是过滤器
。可以在DispatcherServletInitializer中以编程方式映射它们:
@Override
protected Filter[] getServletFilters() {
return new Filter[]{new RequestFilter()};
}
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);
}
}
或者您可以定义自己的WebFilter注释
首先,您需要实用程序类来匹配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;
}
}
}
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;
}
}
拦截器:
@WebFilter(urlPatterns = {"/test/*"})
public class SomeInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// ...
return true;
}
}
在上下文配置上有一点变化:
<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添加到主类中。另一个选项是使用FilterRegistrationBean注册自定义过滤器类,而不是将过滤器本身添加为bean。例如:
@Bean
public FilterRegistrationBean<RequestResponseLoggingFilter> loggingFilter(){
FilterRegistrationBean<RequestResponseLoggingFilter> registrationBean
= new FilterRegistrationBean<>();
registrationBean.setFilter(new RequestResponseLoggingFilter());
registrationBean.addUrlPatterns("/users/*");
return registrationBean;
}
@Bean
公共过滤器注册Bean loggingFilter(){
FilterRegistrationBean注册Bean
=新的FilterRegistrationBean();
setFilter(新的RequestResponseLoggingFilter());
registrationBean.addUrlPatterns(“/users/*”);
返回注册bean;
}
摘自:谢谢,谢尔盖。我完全忘了这根线。但最后,我使用了拦截器。仅为了进行注册,如果您使用的是spring security,则HttpSecurity对象中包含的SecurityFilterChain也可能包含一个筛选器。但是,这不允许使用注释urlPatterns字段连接过滤的URL。