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請求;攔截器可以簡單的理解為“拒你所想拒”,攔截器關注的是方法調用