如何在Spring Boot中添加一个filter类?
我想知道,如果在Spring Boot中有一个Filter
类(用于Web应用程序)的注释吗? 也许@Filter
?
我想在我的项目中添加一个自定义filter。
Spring Boot Reference Guide提到了FilterRegistrationBean
,但是我不确定如何使用它。
如果你想设置第三方filter,你可以使用FilterRegistrationBean
。 例如相当于web.xml
<filter> <filter-name>SomeFilter</filter-name> <filter-class>com.somecompany.SomeFilter</filter-class> </filter> <filter-mapping> <filter-name>SomeFilter</filter-name> <url-pattern>/url/*</url-pattern> <init-param> <param-name>paramName</param-name> <param-value>paramValue</param-value> </init-param> </filter-mapping>
这些将是@Configuration
文件中的两个bean
@Bean public FilterRegistrationBean someFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(someFilter()); registration.addUrlPatterns("/url/*"); registration.addInitParameter("paramName", "paramValue"); registration.setName("someFilter"); registration.setOrder(1); return registration; } public Filter someFilter() { return new SomeFilter(); }
以上是用spring-boot 1.2.3testing的
下面是一个在Spring Boot MVC应用程序中包含自定义filter的方法示例。 确保在包含扫描的组件中包含该软件包:
package com.dearheart.gtsc.filters; 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; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @Component public class XClacksOverhead implements Filter { public static final String X_CLACKS_OVERHEAD = "X-Clacks-Overhead"; @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader(X_CLACKS_OVERHEAD, "GNU Terry Pratchett"); chain.doFilter(req, res); } @Override public void destroy() {} @Override public void init(FilterConfig arg0) throws ServletException {} }
没有特别的注释来表示一个servletfilter。 您只需声明Filter
(或FilterRegistrationBean
)types的@Bean
。 一个例子(为所有响应添加一个自定义标题)在Boot自己的EndpointWebMvcAutoConfiguration中 ;
如果你只声明一个Filter
,它将被应用于所有请求。 如果您还添加了FilterRegistrationBean
,则可以额外指定要应用的单个servlet和url模式。
注意:
从Spring Boot 1.4开始, FilterRegistrationBean
不被弃用,只需将org.springframework.boot.context.embedded.FilterRegistrationBean
包移动到org.springframework.boot.web.servlet.FilterRegistrationBean
有三种方法来添加你的filter,
- 使用
@Component
的Spring@Component
型来注释你的filter - 在Spring
@Configuration
注册一个Filter
types的@Bean
- 在Spring
@Configuration
使用FilterRegistrationBean
types注册一个@Bean
如果您希望您的filter适用于所有请求而无需自定义,请使用#1或#2,否则请使用#3。 只要将filter类放在SpringApplication
类的相同或子包中,就不需要为#1指定组件扫描。 对于#3,只有当你希望Springpipe理你的filter类,比如拥有自动连接的依赖关系时,才需要使用#2。 它对我来说工作得很好,我的新filter不需要任何依赖自动assembly/注入。
尽pipe#2和#3的组合工作正常,我很惊讶,它不会结束两个filter应用两次。 我的猜测是,当Spring调用相同的方法来创build它们时,Spring将这两个bean合并为一个。 如果你想单独使用#3自动显示,你可以AutowireCapableBeanFactory
。 以下是一个例子,
private @Autowired AutowireCapableBeanFactory beanFactory; @Bean public FilterRegistrationBean myFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); Filter myFilter = new MyFilter(); beanFactory.autowireBean(myFilter); registration.setFilter(myFilter); registration.addUrlPatterns("/myfilterpath/*"); return registration; }
从春季文档,
embedded式servlet容器 – 将Servlet,Filter或Listener添加到应用程序中
要添加Servlet,Filter或Servlet * Listener,请为其提供@Bean定义。
例如:
@Bean public Filter compressFilter() { CompressingFilter compressFilter = new CompressingFilter(); return compressFilter; }
将这个@Bean
configuration添加到你的@Configuration
类中,filter将在启动时注册。
也可以使用类path扫描来添加Servlet,filter和监听器,
@WebServlet,@WebFilter和@WebListener带批注的类可以通过使用@ServletComponentScan注释@Configuration类并指定包含要注册的组件的包来自动向embedded式servlet容器注册。 默认情况下,@ServletComponentScan将从注释类的包中扫描。
以下是我的自定义Filter类的示例:
package com.dawson.controller.filter; import org.springframework.stereotype.Component; import org.springframework.web.filter.GenericFilterBean; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class DawsonApiFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; if (req.getHeader("x-dawson-nonce") == null || req.getHeader("x-dawson-signature") == null) { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setContentType("application/json"); httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Required headers not specified in the request"); return; } chain.doFilter(request, response); } }
我通过将它添加到Configuration类中来将它添加到Spring引导configuration中,如下所示:
package com.lyrahealth.configuration; import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; import com.dawson.controller.filter.DawsonApiFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @SpringBootApplication public class ApplicationConfiguration { @Bean public FilterRegistrationBean dawsonApiFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new DawsonApiFilter()); // In case you want the filter to apply to specific URL patterns only registration.addUrlPatterns("/dawson/*"); return registration; } }
使用@WebFilter注释,可以按如下方式完成:
@WebFilter(urlPatterns = {"/*" }) public class AuthenticationFilter implements Filter{ private static Logger logger = Logger.getLogger(AuthenticationFilter.class); @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain) throws IOException, ServletException { logger.info("checking client id in filter"); HttpServletRequest request = (HttpServletRequest) arg0; String clientId = request.getHeader("clientId"); if (StringUtils.isNotEmpty(clientId)) { chain.doFilter(request, response); } else { logger.error("client id missing."); } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
您可以对实现javax.servlet.Filter的类使用@WebFilter javax.servlet.annotation.WebFilter
@WebFilter(urlPatterns = "/*") public class MyFilter implements Filter {}
然后使用@ServletComponentScan进行注册
如果您使用Spring Boot + Spring Security,则可以在安全configuration中执行此操作。
在下面的示例中,我在UsernamePasswordAuthenticationFilter之前添加了一个自定义filter(请参阅所有默认的Spring Securityfilter及其顺序 )。
@EnableWebSecurity class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired FilterDependency filterDependency; @Override protected void configure(HttpSecurity http) throws Exception { http .addFilterBefore( new MyFilter(filterDependency), UsernamePasswordAuthenticationFilter.class); } }
和filter类
class MyFilter extends OncePerRequestFilter { private final FilterDependency filterDependency; public MyFilter(FilterDependency filterDependency) { this.filterDependency = filterDependency; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // filter filterChain.doFilter(request, response); } }
filter主要用于logging器文件,它根据您在项目中使用的logging器而有所不同Lemme解释为log4j2:
<Filters> <!-- It prevents error --> <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/> <!-- It prevents debug --> <ThresholdFilter level="debug" onMatch="DENY" onMismatch="NEUTRAL" /> <!-- It allows all levels except debug/trace --> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> </Filters>
filter用于限制数据,我使用阈值filter进一步限制stream量中的数据级别,我提到了可以在那里限制的级别。 为了进一步参考,请参阅log4j2的级别顺序 – Log4J级别:ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF
- Eclipsetypes的层次结构…与@Configurable注释不一致
- 如果“blah”不存在,ConfigurationManager.AppSettings 会抛出exception吗?
- 缺less推送通知权利
- 如何从iPhone Provisioning Portal中删除应用程序ID
- 如果使用maven,通常你把java或资源下的log4j.properties?
- 如何在几个Maven项目之间共享公共属性?
- 在Python的命令行中,允许configuration选项被覆盖的最佳方法是什么?
- Heroku错误:“权限被拒绝(公钥)”
- 当string保证不会改变时,string比较是否真的可以根据文化而不同?