1. 程式人生 > 其它 >38.1 Filter過濾器(配置、生命週期、路徑配置、攔截方式配置)、登入驗證案例配置過濾器、敏感詞彙過濾、設計模式:裝飾模式

38.1 Filter過濾器(配置、生命週期、路徑配置、攔截方式配置)、登入驗證案例配置過濾器、敏感詞彙過濾、設計模式:裝飾模式

技術標籤:02 javaee

目錄

1 Filter:過濾器

2過濾器配置

2.1web.xml方式實現過濾器

2.2註解方式實現過濾器

3過濾器生命週期方法

4 過濾器配置詳解

4.1Filter路徑配置

4.2Filter攔截方式配置

4.2.1列:註解方式實現過濾器

4.2.2 web.xml方式實現過濾器

5配置多個過濾器

6 列:登入驗證案例配置過濾器

7敏感詞彙過濾

8設計模式:裝飾模式

8.1實現方式:

8.1.1 靜態代理:有一個類檔案描述代理模式

8.1.2 動態代理:在記憶體中形成代理類


1 Filter:過濾器

生活中的過濾器:淨水器,空氣淨化器,土匪

web中的過濾器:當訪問伺服器的資源時,過濾器可以將請求攔截下來,完成一些特殊的功能。

過濾器的作用:一般用於完成通用的操作。如:登入驗證、統一編碼處理、敏感字元過濾...

過濾器執行流程:1. 執行過濾器 2. 執行放行後的資源 3. 回來執行過濾器放行程式碼下邊的程式碼

2過濾器配置

2.1web.xml方式實現過濾器

java程式碼實現過濾器介面(import javax.servlet.*;)

import javax.servlet.*;
import java.io.IOException;
public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo1執行了... ...");
        filterChain.doFilter(servletRequest,servletResponse);//放行
    }

    @Override
    public void destroy() {

    }
}

web.xml中書寫程式碼

<filter>
        <filter-name>demo1</filter-name>
        <filter-class>cn.lws.demo.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
        <filter-name>demo1</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>

2.2註解方式實現過濾器

import javax.servlet.*;
import java.io.IOException;
@WebFilter("/*")//攔截所有資源
public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo1執行了... ...");
        filterChain.doFilter(servletRequest,servletResponse);//放行
    }

    @Override
    public void destroy() {

    }
}

3過濾器生命週期方法

  1. init:在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次。用於載入資源
  2. doFilter:每一次請求被攔截資源時,會執行。執行多次
  3. destroy:在伺服器關閉後,Filter物件被銷燬。如果伺服器是正常關閉,則會執行destroy方法。只執行一次。用於釋放資源
@WebFilter("/*")
public class FilterDemo3 implements Filter {
    /**
     * 在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次。用於載入資源
     * @param config
     * @throws ServletException
     */
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init....");
    }
    /**
     * 在伺服器關閉後,Filter物件被銷燬。如果伺服器是正常關閉,則會執行destroy方法。只執行一次。用於釋放資源
     */
    public void destroy() {
        System.out.println("destroy....");
    }

    /**
     * 每一次請求被攔截資源時,會執行。執行多次
     * @param request
     * @param response
     * @param chain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("doFilter。。。 。。。");
        chain.doFilter(request, response);
    }
}

4 過濾器配置詳解

4.1Filter路徑配置

//@WebFilter("/index.jsp")     //只有訪問index.jsp資源時,過濾器才會被執行
//@WebFilter("/user/*")     //訪問/user下的所有資源時,過濾器都會被執行
//@WebFilter("/*.jsp")     //訪問所有後綴名為jsp資源時,過濾器都會被執行
//@WebFilter("/*")       //訪問所有資源時,過濾器都會被執行
public class FilterDemo4 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo4... ...");
        chain.doFilter(request, response);
    }
}

4.2Filter攔截方式配置

攔截方式配置:資源被訪問的方式
註解配置:設定dispatcherTypes屬性。如:@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
1. REQUEST:預設值。瀏覽器直接請求資源
2. FORWARD:轉發訪問資源
3. INCLUDE:包含訪問資源
4. ERROR:錯誤跳轉資源
5. ASYNC:非同步訪問資源
web.xml配置設定<dispatcher></dispatcher>標籤即可

4.2.1列:註解方式實現過濾器

//1  瀏覽器請求時會執行此過濾器 預設情況
//@WebFilter(value = "/*",dispatcherTypes = DispatcherType.REQUEST)
//2 瀏覽器轉發時會執行此過濾器
//@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
//3 瀏覽器請求或轉發時會執行此過濾器
//@WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
public class FilterDemo5 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo5執行了。。。 。。。");
        chain.doFilter(request, response);
    }
}

轉發程式碼:

@WebServlet("/ServletDemo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ServletDemo2 doGet執行了... ...");
        request.getRequestDispatcher("index.jsp").forward(request,response);//轉發
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

4.2.2 web.xml方式實現過濾器

<filter>
        <filter-name>demo1</filter-name>
        <filter-class>cn.lws.demo.filter.FilterDemo5</filter-class>
</filter>
<filter-mapping>
        <filter-name>demo1</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
</filter-mapping>

5配置多個過濾器

濾器先後順序問題:
1. 註解配置:按照類名的字串比較規則比較,值小的先執行 * 如: AFilter 和 BFilter,AFilter就先執行了。
2. web.xml配置: <filter-mapping>誰定義在上邊,誰先執行

過濾器執行順序:如果有兩個過濾器:過濾器1和過濾器2 。執行順序:過濾器1 - 過濾器2 - 資源執行 - 過濾器2 - 過濾器1

@WebFilter("/*")
public class FilterDemo6 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo6 執行了... ...");
        chain.doFilter(request, response);
        System.out.println("FilterDemo6 回來了... ...");
    }
}
@WebFilter("/*")
public class FilterDemo7 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo7 執行了... ...");
        chain.doFilter(request, response);
        System.out.println("FilterDemo7 回來了... ...");
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    index.jsp... ...
  <% out.print("index.jsp執行了。。。 。。。");%> 輸出到jsp頁面中
  <% System.out.println("index.jsp執行了。。。 。。。");%> 輸出到控制檯

  </body>
</html>

輸入:

http://localhost/day19/index.jsp

6 列:登入驗證案例配置過濾器

參考程式碼:day17_case

需求:
1. 訪問day17_case案例的資源。驗證其是否登入
2. 如果登入了,則直接放行。
3. 如果沒有登入,則跳轉到登入頁面,提示"您尚未登入,請先登入"。

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
//servletRequest 與req是同一個
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println(servletRequest);
        HttpServletRequest req = (HttpServletRequest) servletRequest;//1 強制轉換
        //2 獲取資源請求路徑
        String uri = req.getRequestURI();
        System.out.println("uri:"+uri);
        //3.判斷是否包含登入相關資源路徑,要注意排除掉 css/js/圖片/驗證碼等資源
        if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet")  ){
            filterChain.doFilter(servletRequest,servletResponse);//放行
        }else {
            Object user = req.getSession().getAttribute("user");
            if(user!=null){
                filterChain.doFilter(servletRequest,servletResponse);//放行
            }else {
                req.setAttribute("login_msg","你尚未登入,請輸入使用者名稱和密碼");
                req.getRequestDispatcher("/login.jsp").forward(req,servletResponse);
            }
        }

    }

    @Override
    public void destroy() {

    }
}

7敏感詞彙過濾

src目錄下建立檔案:敏感詞彙.txt(檔案內容可以自行新增)


@WebFilter("/*")
public class FilterDemo8 implements Filter {
    private  List<String> list=new ArrayList<String>();
    public void init(FilterConfig config) throws ServletException {
        try{
            String realPath =config.getServletContext().getRealPath("/WEB-INF/classes/敏感詞彙.txt");//1 獲取檔案真實路徑
            BufferedReader reader = new BufferedReader(new FileReader(realPath));//2 讀取檔案
            String line=null;
            while ((line=reader.readLine())!=null){
                list.add(line);
            }
            reader.close();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//使用了設計模式:裝飾模式
        ServletRequest o = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //增強getParameter方法  判斷是否是getParameter方法
                        if(method.getName().equals("getParameter")){
                            //增強返回值
                            //獲取返回值
                            String value = (String) method.invoke(req,args);
                            if(value != null){
                                for (String str : list) {
                                    if(value.contains(str)){
                                        value = value.replaceAll(str,"***");
                                    }
                                }
                            }
                        }
                        return method.invoke(req,args);
                    }
                });
    }
}

測試程式碼:

@WebServlet("/ServletDemo2")
public class ServletDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String msg = request.getParameter("msg");

        System.out.println(name+":"+msg);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

驗證方式:輸入

http://localhost/day19/ServletDemo2?name=laowang&msg=sb
過濾後:http://localhost/day19/ServletDemo2?name=laowang&msg=xxx

8設計模式:裝飾模式

  • 真實物件:被代理的物件
  • 代理物件:
  • 代理模式:代理物件代理真實物件,達到增強真實物件功能的目的

8.1實現方式:

8.1.1 靜態代理:有一個類檔案描述代理模式

8.1.2 動態代理:在記憶體中形成代理類

實現步驟:

1 代理物件和真實物件實現相同的介面

2建立代理物件 = Proxy.newProxyInstance();並增強方法:

3 使用代理物件呼叫方法。

4 增強方法:

增強方式:
1. 增強引數列表
2. 增強返回值型別
3. 增強方法體執行邏輯

介面:

public interface ProducePc {

    int numPc(int pc);//pc總數量
    String salePcs(double monkey);//單價
    void show();//資訊
}

真實物件:

public class LenovoPc implements ProducePc {


    @Override
    public int numPc(int pc) {
        return pc;
    }

    @Override
    public String salePcs(double monkey) {
        String s = String.valueOf(monkey);
        return s;
    }

    @Override
    public void show() {
        System.out.println("聯想電腦 i7 四核八執行緒 8g 256Gssd");

    }
}

代理物件:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {
    public static void main(String[] args) {
        LenovoPc lenovoPc = new LenovoPc();//1.建立真實物件
/*        三個引數:        1. 類載入器:真實物件.getClass().getClassLoader()        2. 介面陣列:真實物件.getClass().getInterfaces()        3. 處理器:new InvocationHandler()*/
        //2 動態代理增強LenovoPc物件
        ProducePc salePc= (ProducePc) Proxy.newProxyInstance(lenovoPc.getClass().getClassLoader(), lenovoPc.getClass().getInterfaces(),new InvocationHandler() {                
//invoke方法:代理物件呼叫的所有方法都會觸發該方法執行。引數:1. proxy:代理物件 2. method:代理物件呼叫的方法,被封裝為的物件 args:代理物件呼叫的方法時,傳遞的實際引數
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().equals("numPc")){
                            int num = (int) args[0]-1; //1 增強引數
                            Object obj = method.invoke(lenovoPc, num);
                            return obj;
                        }else if (method.getName().equals("salePcs")){
                            double monkey=(double)args[0]*0.85;
                            System.out.println("價格:"); //2 增強方法體
                            Object obj =method.invoke(lenovoPc, monkey);
                            return obj+"元,_ 送一個滑鼠墊"; //3增強返回值
                        }else{
                            Object obj = method.invoke(lenovoPc, args);
                            return obj;
                        }

                    }
                });
        int i = salePc.numPc(100);
        String s = salePc.salePcs(6000);
        System.out.println(i);
        System.out.println(s);
        salePc.show();

    }
}