若在開發時想要在請求到達Controller 前或回應離開Controller 後執行一些業務邏輯,比如進入Controller 前判斷是否已經登入或是是否有請求路徑的訪問權限等功能,可以使用過濾器或攔截器兩個方法進行處理。
Filter 是Web Server 的一部份,不是Spring 框架自帶的,所以我們可以HTTP 請求到達Servlet 前或在HTTP 回應回傳給Client 端前進行攔截,攔截成功就可以實作一些自定義的業務邏輯或對回應資料進行修改,而Spring Security 就是一個很好的Filter 實作方法,可以透過Spring Security 配置進行授權與認證等功能。
@Order
: 表示過濾順序,其值越小越優先執行。@WebFilter
: 宣告這是一個過濾器類別,Spring 會根據其屬性配置過濾器,主要屬性如下。
filterName
: 指定Filter 名稱。value
: 指定攔截路徑,與urlPatterns 擇一使用。urlPatterns
: 指定攔截路徑,與value 擇一使用。servletNames
: 設定Filter 過濾哪些Servlet 的請求。dispatcherTypes
: 設定Filter 過濾哪種請求方式,屬性有ASYNC、ERROR、FORWARD、INCLUDE、REQUEST,預設為全選。initParams
: 設定Filter 初始化參數。asyncSupported
: 設定Filter 是否支援異步模式,預設為false。description
: 描述Filter 用途。displayName
: 指定Filter 顯示名稱。要建立一個Filter 有兩種常見的方法,一種是實作javax.servlet.Filter 介面,另一種則是繼承org.springframework.web.filter.OncePerRequestFilter 類別,使用方法上基本差不多,這邊就僅展示實作javax.servlet.Filter 介面的方法。
package com.example.iThomeIronMan.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.example.iThomeIronMan.model.Member;
@Component
@WebFilter(filterName = "", urlPatterns = {"/*"})
@Order(value = 1)
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession();
Member member = (Member) session.getAttribute("MemberSession");
String uri = new String(req.getRequestURI());
// 放行所有靜態檔案
if(uri.contains("/css") || uri.contains("/images") || uri.contains("/js")) {
chain.doFilter(request, response);
return ;
}
// 已登入
if(member != null) {
System.err.println("Been Login");
if(uri.contains("/login") || uri.contains("/register")) {
res.sendRedirect("/information");
}
else {
chain.doFilter(request, response);
}
}
// 未登入
else {
System.err.println("No Login");
if(uri.contains("/login") || uri.contains("/register")) {
chain.doFilter(request, response);
}
else {
res.sendRedirect("/login");
}
}
}
}
注意使用@WebServlet、@WebFilter、@WebListener 等Servlet 註釋時需要在Spring Boot 的啟動類別上添加@ServletComponentScan 註釋,否則不會生效。
package com.example.iThomeIronMan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class IThomeIronManApplication {
public static void main(String[] args) {
SpringApplication.run(IThomeIronManApplication.class, args);
}
}
spring-boot實現增加自定義filter(新)
SpringBoot基於註解方式配置Filter
SpringBoot中使用Filter丶Java教程网-IT开发者们的技术天堂