輕輕鬆鬆學習SpringBoot2:第二十四篇: Spring Boot過濾器
①攔截器是基於java的反射機制的,而過濾器是基於函式回撥。
②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
④攔截器可以訪問action上下文、值棧裡的物件,而過濾器不能訪問。
⑤在action的生命週期中,攔截器可以多次被呼叫,而過濾器只能在容器初始化時被呼叫一次。
⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器裡注入一個service,可以呼叫業務邏輯。攔截器可以獲取ioc中的service bean實現業務邏輯,攔截器可以獲取ioc中的service bean實現業務邏輯,攔截器可以獲取ioc中的service bean實現業務邏輯,
1.過濾器和攔截器觸發時機不一樣:
過濾器是在請求進入容器後,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完後,返回給前端之前。
1.過濾器和攔截器觸發時間和地點不一樣:
過濾器是在請求進入容器後,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完後,返回給前端之前。
1.過濾器和攔截器觸發時間和地點不一樣:
過濾器是在請求進入容器後,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完後,返回給前端之前。
=================================實戰程式碼==================================
舉例:
定義一個過濾器,當用戶訪問一個頁面時,判斷使用者是否是登入狀態,如果是則跳轉到對應的頁面,如果不是則跳轉到登入頁
這個地方不使用資料庫,直接硬編碼,其中程式碼結構如下
TestFilterConfig.java
testC.javapackage com.example.smybatis.configurer; import com.example.smybatis.filters.testFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TestFilterConfig { @Bean public FilterRegistrationBean someFilterRegistration1() { //新建過濾器註冊類 FilterRegistrationBean registration = new FilterRegistrationBean(); // 新增我們寫好的過濾器 registration.setFilter( new testFilter()); // 設定過濾器的URL模式 registration.addUrlPatterns("/*"); return registration; } }
package com.example.smybatis.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
public class testC {
@GetMapping(value="/test")
public Integer test(){
return 111;
}
@RequestMapping("login")
public String login(String name,String pwd,HttpServletRequest request) {
HttpSession session = request.getSession();
if(name.equals("test")&&pwd.equals("test123")) {
session.setAttribute("user",name);
return "登入成功";
} else {
return "使用者名稱或密碼錯誤!";
}
}
}
testFilter.java
package com.example.smybatis.filters;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class testFilter implements Filter {
//標示符:表示當前使用者未登入(可根據自己專案需要改為json樣式)
String NO_LOGIN = "您還未登入";
//不需要登入就可以訪問的路徑(比如:註冊登入等)
String[] includeUrls = new String[]{"/login","/register","/login.html"};
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession(false);
String uri = request.getRequestURI();
System.out.println("filter url:"+uri);
//是否需要過濾
boolean needFilter = isNeedFilter(uri);
if (!needFilter) { //不需要過濾直接傳給下一個過濾器
filterChain.doFilter(servletRequest, servletResponse);
} else { //需要過濾器
// session中包含user物件,則是登入狀態
if(session!=null&&session.getAttribute("user") != null){
// System.out.println("user:"+session.getAttribute("user"));
filterChain.doFilter(request, response);
}else{
String requestType = request.getHeader("X-Requested-With");
//判斷是否是ajax請求(因為ajax頁面不跳轉,所以這塊需要判斷一下)
if(requestType!=null && "XMLHttpRequest".equals(requestType)){
response.getWriter().write(this.NO_LOGIN);
}else{
//重定向到登入頁(需要在static資料夾下建立此html檔案)
response.sendRedirect(request.getContextPath()+"/login.html");
}
return;
}
}
}
/**
* @Description: 是否需要過濾
*/
public boolean isNeedFilter(String uri) {
for (String includeUrl : includeUrls) {
if(includeUrl.equals(uri)) {
return false;
}
}
return true;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
ceshi.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>測試</title>
</head>
<body>
<h1>這是測試頁面</h1>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登入</title>
</head>
<body>
<h1>這是登入頁面</h1>
</body>
</html>
下面我們做幾個測試
首先在瀏覽器輸入http://localhost:1234/ceshi.html
結果跳轉到了http://localhost:1234/login.html
這是因為攔截器生效了,判斷使用者沒有登入態,則預設跳轉到登入頁面
接下來,我們先登入
1)登入成功了,則有登入態了
我們再訪問http://localhost:1234/ceshi.html
ok,可以
2)我們再次登入,估計輸錯密碼
3)這個時候瀏覽器輸入http://localhost:1234/ceshi.html,我們發現又跳轉到了登入頁,這是因為session中沒有使用者的情況
====================多個過濾器排序=================
需要在配置java類中加入排序即可:registration.setOrder(1);
TestFilterConfig.java
package com.example.smybatis.configurer;
import com.example.smybatis.filters.testFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestFilterConfig {
@Bean
public FilterRegistrationBean someFilterRegistration1() {
//新建過濾器註冊類
FilterRegistrationBean registration = new FilterRegistrationBean();
// 新增我們寫好的過濾器
registration.setFilter( new SessionFilter());
// 設定過濾器的URL模式
registration.addUrlPatterns("/*");
//設定過濾器順序
registration.setOrder(1);
return registration;
}
}