SpringBoot基於註解方式配置Filter
Filter在Web應用中是一個很常見的元件,在Spring應用中Filter的建立方式有最簡單和常用的方式有兩種(可能還有其他,若有其他優秀的建立方式,歡迎交流學習):
- 實現javax.servlet.Filter介面
- 繼承org.springframework.web.filter.OncePerRequestFilter類
在傳統Web應用中,每個Web應用都有一個web.xml檔案,方便我們配置各種Servlet、Filter、Listener等。在SpringBoot應用中大多推崇零XML配置的方式,所以在沒有web.xml的情況下如何配置Filter呢?這裡先介紹使用@WebFilter註解配置的方式。
- 採用繼承org.springframework.web.filter.OncePerRequestFilter的方式建立一個Filter
package com.jackson.spring.boot.filters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = {"/*"})
@Order(value = 2)
@Slf4j
public class UrlFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
FilterChain filterChain) throws ServletException, IOException {
logger.info("urlFilter .....");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
- 使用實現javax.servlet.Filter建立一個Filter
package com.jackson.spring.boot.filters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = {"/*"},
initParams = {@WebInitParam(name = "fileTypes", value = "doc;xls;zip")})
@Order(value = 3)
@Slf4j
public class ParamFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("---------" + filterConfig.getInitParameter("fileTypes"));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("ParamFilter.doFilter ...");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
在程式碼中我們可以看到使用@WebFilter註解去宣告一個Filter在一個Web應用中。其官方描述如下:
The @WebFilter annotation is used to declare a filter in a web application. The annotated class must extend the javax.servlet.Filter interface
我們知道過濾器的執行順序是按照web.xml中是配置順序決定的,那麼在沒有web.xml檔案的時候,如何指定Filter的執行順序呢?程式碼中@Order註解就是指定過濾器的執行順序的。
使用上述配置啟動後訪問,過濾器可按照預期的執行順序執行,但是有一個問題,細心的朋友就會發現上述例子中的ParamFilter在執行init()方法的時候,日誌列印獲取init-param引數時為空。這是為何?我們對於的initParam引數配置如下:
initParams = {@WebInitParam(name = "fileTypes", value = "doc;xls;zip")})
翻了好久的資料,在這篇部落格中得到解決:https://www.liangzl.com/get-article-detail-129981.html 。在使用@WebServlet、@WebFilter、@WebListener、@WebInitParam等servlet註解時需要在SpringBoot的啟動類上新增@ServletComponentScan註解,否則不會生效。這裡我試了一下不使用@ServletComponentScan註解而使用@Component註解情況下發現@WebInitParam註解會失效,大家也可以嘗試一下。為了安全起見還是把@ServletComponentScan註解加到啟動類上(注意沒有刪除@Component註解)啟動的時候發現同一個Filter被載入了兩個到Spring容器中。若配置了filterName屬性,還有可能出現如下提示資訊,啟動失敗:
A bean with that name has already been defined
這裡其實很容易就可以知道是@ServletComponentScan和@Component註解都建立了一個物件到Spring容器中,為了可以使用Servlet的特性,所以推薦使用@ServletComponentScan註解。最終其中一個Filter的配置修改為如下配置:
package com.jackson.spring.boot.filters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(urlPatterns = {"/*"}, filterName = "paramFilter",
initParams = {@WebInitParam(name = "fileTypes", value = "doc;xls;zip")})
@Order(value = 3)
@Slf4j
public class ParamFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("---------" + filterConfig.getInitParameter("fileTypes"));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("ParamFilter.doFilter ...");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
啟動類的配置為:
package com.jackson.spring.boot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication(scanBasePackages = {"com.jackson.spring.boot"})
@ServletComponentScan
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main( String[] args ) {
logger.info("application starting ....");
SpringApplication.run(Application.class);
}
}
相關文章
- 基於Springboot+Dubbo+Nacos 註解方式實現微服務呼叫Spring Boot微服務
- Spring基於註解的IoC配置Spring
- Spring基於註解的aop配置Spring
- Spring中基於註解方式的AOP操作Spring
- SpringBoot主配置和註解Spring Boot
- Mybatis基於註解的方式訪問資料庫MyBatis資料庫
- SpringBoot 全域性日期格式化(基於註解)Spring Boot
- SpringBoot如何註冊Servlet、Filter、ListenerSpring BootServletFilter
- springboot註解方式使用redis快取Spring BootRedis快取
- spring基於註解配置實現事務控制Spring
- 基於SpringBoot 、AOP與自定義註解轉義字典值Spring Boot
- 【SpringBoot實戰】核心配置和註解Spring Boot
- SpringBoot2 基礎案例(13):基於Cache註解,管理Redis快取Spring BootRedis快取
- SpringBoot+Dubbo的註解方式整合例項Spring Boot
- 基於註解的方式使用spring-integration-redis分散式鎖SpringRedis分散式
- 基於Annotation註解整合SSH框架和基於XML檔案配置Bean整合SSH框架框架XMLBean
- Java Web之基於註解的Spring MVC環境配置JavaWebSpringMVC
- 基於Maven建立SpringBoot的2種方式MavenSpring Boot
- Spring定時器的配置(註解+xml)方式Spring定時器XML
- Spring Boot 基於註解驅動原始碼分析--自動配置Spring Boot原始碼
- 基於註解的Spring多資料來源配置和使用Spring
- spring上 -基於註解配置bean,動態代理,AOP筆記SpringBean筆記
- SpringBoot註解Spring Boot
- Springboot+Aop註解的方式實現分散式鎖Spring Boot分散式
- Spring(三):IoC容器裝配Bean(xml配置方式和註解方式)SpringBeanXML
- 基於SpringBoot的後臺管理系統(異常、註解、node、page)(二)Spring Boot
- 詳解Nginx 虛擬主機配置的三種方式(基於埠)Nginx
- 詳解Nginx 虛擬主機配置的三種方式(基於IP)Nginx
- 基於註解的 Spring MVC詳解SpringMVC
- 【SpringBoot】使用Java配置方式Spring BootJava
- springboot整合kafka配置方式Spring BootKafka
- 基於MyBatis註解擴充套件,實現無需配置即可使用MyBatis套件
- 【SpringBoot系列】SpringBoot註解詳解Spring Boot
- Redis詳解 - SpringBoot整合Redis,RedisTemplate和註解兩種方式的使用RedisSpring Boot
- 請問為什麼越來越多的技術偏向於基於註解的實現方式?
- Springboot 常用註解Spring Boot
- Spring(5、基於註解的事物)Spring
- 3_基於註解管理Bean物件Bean物件