Java三大器(過濾器|監聽器|攔截器)


filter過濾器

用的功能很簡單,但是很重要(做框架的時候可能才會用得很深)

平時用就是實現一下Filter接口(重寫它得doFliter(),init(),destroy()方法,放行chain.doFilter(request,response);),並在web.xml里邊進行配置就完事了

另外一個是它的最佳實踐:

公共代碼得提取(如request,response指定編碼解碼方式,公共代碼提到一塊(處理post))

對request,response的方法進行增強(裝飾者模式(包裝,同樣是亂碼處理,使處理參數的能力更強大,支持中文(處理get))/動態代理(反射))(自動登陸)

進行權限控制

//裝飾者模式(這個模式也很好記,就是你想用request對象的時候,你又希望它的getParameter()方法更加強大,可以處理中文,那么你可以建一個新類,對它的方法進行增強)
//(應用場景:不想增加很多子類/只想增強類的一些方法,例如在EncodingFilter過濾器中對request的getParameter方法進行增強,處理其中文參數亂碼問題)
public class EncodingFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        //在傳遞request之前對request的getParameter方法進行增強
        /*
         * 裝飾者模式(包裝)
         * 
         * 1、增強類與被增強的類要實現統一接口(繼承同一個父類)
         * 2、在增強類中傳入被增強的類(構造)
         * 3、需要增強的方法重寫 不需要增強的方法調用被增強對象的
         * 
         */
        
        //被增強的對象req
        HttpServletRequest req = (HttpServletRequest) request;
        //增強對象enhanceRequest
        EnhanceRequest enhanceRequest = new EnhanceRequest(req);
        
        
        chain.doFilter(enhanceRequest, response);
    }

    @Override
    public void destroy() {
        
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        
    }
}

class EnhanceRequest extends HttpServletRequestWrapper{
    //HttpServletRequestWrapper這個包裝類就是專門用來你繼承,進而寫增強方法的
    private HttpServletRequest request;

    public EnhanceRequest(HttpServletRequest request) {//核心:傳入被增強的類
        super(request);
        this.request = request;
    }
    
    //對getParaameter增強,增強的是原來類的方法
    @Override
    public String getParameter(String name) {
        String parameter = request.getParameter(name);//亂碼
        try {
            parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return parameter;
    }
}

Listener監聽器

監聽三個域對象:request,session,servletContext

 ServletContext代表整個web應用,只有一個

步驟:實現接口,覆蓋方法,xml中進行配置

ServletContextListener

方法中可以獲取到被監聽的對象(兩方法,一個是通用的)

應用:

web應用一創建,加載數據庫驅動,連接池的初始話

加載spring初始配置文件(applicationContext.xml)

任務調度(定時器:Timer/TimeTask)

 

 HttpSession(多個)

服務端沒有某瀏覽器對應的session時創建

 3種銷毀:應用正常關閉,手動銷毀,過期(默認30min)

應用:統計訪問量

 

ServletRequest(瞬間的事)

 

ServletContext,HttpSession,ServletRequest三個域對象的屬性變化(getAttribute,setAttribute,removeAttribute)

對象感知監聽器((綁定,解綁)(鈍化,活化)),(對象需要實現接口,不需要配置xml)

綁定狀態:就一個對象被放到session域中
解綁狀態:就是這個對象從session域中移除了
鈍化狀態:是將session內存中的對象持久化(序列化)到磁盤
活化狀態:就是將磁盤上的對象再次恢復到session內存中

package com.itheima.domian;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class Person implements HttpSessionBindingListener{

    private String id;
    private String name;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
    @Override
    //綁定的方法
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("person被綁定了");
    }
    @Override
    //解綁方法
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("person被解綁了");
    }
    
    
    
}

 

 

Person p = new Person();
p.setId("100");
p.setName("zhangsanfeng");

//將person對象綁到session中
session.setAttribute("person", p);

//將person對象從session中解綁
session.removeAttribute("person");

 

一個對象必須要實現了Serializable接口,才能被存儲到磁盤上

鈍化:服務器正常關閉時,session中的對象會被鈍化到磁盤

活化:服務器正常啟動時,session會活化這個對象(外界又可以正常的訪問這個session了)

另外,鈍化和活化你可以進行主動控制(context.xml,默認配置1分鍾不用被銷毀)

package com.itheima.domian;

import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;

public class Customer implements HttpSessionActivationListener,Serializable{

    private String id;
    private String name;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
    @Override
    //鈍化
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println("customer被鈍化了");
    }
    @Override
    //活化
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println("customer被活化了");
    }
    
    
}

 

 

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- maxIdleSwap:session中的對象多長時間不使用就鈍化 -->
    <!-- directory:鈍化后的對象的文件寫到磁盤的哪個目錄下 配置鈍化的對象文件在 work/catalina/localhost/鈍化文件 -->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="itheima32" />
    </Manager>
</Context>

 

Listener 監聽器結合Timer定時任務實現每天定時給過生日的員工發郵件

  <listener>
      <listener-class>com.itheima.birthday.BirthdayListener</listener-class>
  </listener>

 

 

package com.itheima.birthday;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.mail.MessagingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import com.itheima.mail.MailUtils;

public class BirthdayListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //當web應用啟動 開啟任務調動---功能在用戶的生日當前發送郵件
        //開啟一個定時器
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            
            @Override
            public void run() {
                // 為當前的生日的用戶發郵件
                //1、獲得今天過生日的人
                //獲得今天的日期
                SimpleDateFormat format = new SimpleDateFormat("MM-dd");
                String currentDate = format.format(new Date());
                //根據當前時間從數據查詢今天過生日的人
                QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
                String sql = "select * from customer where birthday like ?";
                List<Customer> customerList = null;
                try {
                    customerList = runner.query(sql, new BeanListHandler<Customer>(Customer.class) ,"%"+currentDate+"%");
                } catch (SQLException e) {
                    e.printStackTrace();
                } //08-18
                //2、發郵件
                if(customerList!=null&&customerList.size()>0){
                    for(Customer c : customerList){
                        String emailMsg = "親愛的:"+c.getRealname()+",生日快樂!";
                        try {
                            MailUtils.sendMail(c.getEmail(), "生日祝福", emailMsg);
                            System.out.println(c.getRealname()+"郵件發送完畢");
                        } catch (MessagingException e) {
                            e.printStackTrace();
                        }
                    }
                }
                
                
            }
        }, new Date(), 1000*10);
        //實際開發中起始時間是一個固定的時間
        //實際開發中間隔時間是1天
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        
    }

}

 

 

Interceptor攔截器

 

Java三大器:過濾器,監聽器,攔截器Interceptor

攔截器是依賴Java反射機制來實現的。攔截器的實現,用到的是JDK實現的動態代理,我們都知道,JDK實現的動態代理,需要依賴接口。攔截器

是在面向切面編程中應用的,就是在你的service或者一個方法前調用一個方法,或者在方法后調用一個方法。攔截器不是在web.xml,比如struts在

struts.xml中配置。

過濾器可以簡單的理解為“取你所想取”,過濾器關注的是web請求;攔截器可以簡單的理解為“拒你所想拒”,攔截器關注的是方法調用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM