1. 程式人生 > >輕輕鬆鬆學習SpringBoot2:第二十四篇: Spring Boot過濾器

輕輕鬆鬆學習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

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 testFilter());
        // 設定過濾器的URL模式
        registration.addUrlPatterns("/*");
        return registration;
    }

}
testC.java
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;
    }
}