課程目標(biāo)
掌握過(guò)濾器概念及兩種編寫(xiě)方法
過(guò)濾器Filter
過(guò)濾器也叫攔截器,在一個(gè)層面上解決問(wèn)題骡送。
應(yīng)用:用來(lái)做統(tǒng)一編碼解碼、用來(lái)做權(quán)限驗(yàn)證、做網(wǎng)站計(jì)數(shù)等等
特殊說(shuō)明:過(guò)濾器可以是一個(gè)鏈搀绣。也就是說(shuō)可以配置多個(gè)過(guò)濾器,我們也可以通過(guò)配置來(lái)控制順序
怎么建filter
servlet3.0以后滤蝠⊥阆ǎ可以用向?qū)Ы?br> 例如:我建一個(gè)統(tǒng)一做編碼處理的
我們之前在每個(gè)servlet里要寫(xiě)
request.setChararcterEncoding("utf-8");
response.setChararcterEncoding("utf-8");
file-new -Filter-按向?qū)б徊讲脚渲谩?br>
step1 為filter起個(gè)文件名CharacterFilter
step2 設(shè)置初始化參數(shù) encoding:UTF-8
step3 mapping 配置過(guò)濾對(duì)象(1--可以對(duì)指定的servlet進(jìn)行過(guò)濾 2--可以配置過(guò)濾規(guī)則)
配置完成后生成如下代碼:
package com.neuedu.utils;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter(
urlPatterns = { "/*" },
initParams = {
@WebInitParam(name = "encoding", value = "UTF-8")
})
public class CharacterFilter implements Filter {
public CharacterFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
我們看到有三個(gè)主要方法
init() 初始化方法:做準(zhǔn)備工作
doFilter() 業(yè)務(wù)方法
需要注意的是:j里面有一個(gè)
chain.doFilter(request, response);這句話的意思是執(zhí)行完該過(guò)濾器后去執(zhí)行下一個(gè)過(guò)濾器
用@WebFilter方式配置的過(guò)濾器執(zhí)行順序是按filterName首字母的先后順序執(zhí)行。
destroy() 銷(xiāo)毀方法:做清理工作
完整代碼如下:
package com.neuedu.utils;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
/**
* Servlet Filter implementation class CharacterFilter
*/
@WebFilter(
filterName="MyFilter",
urlPatterns = { "/*" },
initParams = {
@WebInitParam(name = "encoding", value = "UTF-8")
})
public class CharacterFilter implements Filter {
String encode="";
/**
* Default constructor.
*/
public CharacterFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
//在初始化時(shí)準(zhǔn)備好編碼方式
encode=fConfig.getInitParameter("encoding");
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(encode);
response.setCharacterEncoding(encode);
//執(zhí)行下一個(gè)過(guò)濾器
chain.doFilter(request, response);
}
/**
* @see Filter#destroy()
*/
public void destroy() {
encode="";
}
}
filter另外一種創(chuàng)建方式
servlet3.0之前
簡(jiǎn)化版
java類
public class TestFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig fconfig) throws ServletException {
}
}
配置:
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.neuedu.utils.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
分兩步
step1 寫(xiě)一個(gè)類實(shí)現(xiàn)filter接口
package com.neuedu.utils;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter implements Filter {
FilterConfig fconfig=null;
@Override
public void destroy() {
fconfig=null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String encode=fconfig.getInitParameter("encode");
request.setCharacterEncoding(encode);
response.setCharacterEncoding(encode);
//執(zhí)行下一個(gè)過(guò)濾器
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config) throws ServletException {
fconfig=config;
}
}
step2 在WEB-INF\web.xml里配置
配置分兩步
第一步filter 第二步配置filter-mapping
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.neuedu.utils.MyFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
過(guò)濾器使用
日志記錄
登錄驗(yàn)證
編碼處理
后臺(tái)登錄攔截
可以定個(gè)規(guī)則物咳,比如所有需要登錄才能訪問(wèn)的jsp和servlet都加上/admin前綴
@WebFilter("/admin/*")
public class LoginFilter implements Filter {
/**
* Default constructor.
*/
public LoginFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// place your code here
System.out.println("進(jìn)入攔截器");
//在此處做用戶是否登錄的驗(yàn)證
//判斷session里是否存在loginUser
HttpServletRequest httprequest=(HttpServletRequest)request;
HttpSession session=httprequest.getSession();
Object obj=session.getAttribute("loginUser");
if(obj!=null){
//如果有就放行
chain.doFilter(request, response);
return ;
}else{
//如果沒(méi)有锣险,就回登錄頁(yè)
HttpServletResponse httpresponse=(HttpServletResponse)response;
httpresponse.sendRedirect(httprequest.getContextPath()+"/login.jsp");
}
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
監(jiān)聽(tīng)器
監(jiān)聽(tīng)事件蹄皱,比如session建立,系統(tǒng)啟動(dòng)芯肤,請(qǐng)求到達(dá)
本質(zhì)也是java類巷折。
建立方式
file-new listener-輸入名稱-選擇監(jiān)聽(tīng)器種類
比如我選擇了以下三個(gè) ServletContextListener, HttpSessionListener, ServletRequestListener
系統(tǒng)會(huì)自動(dòng)生成如下類
package com.neuedu.utils;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Application Lifecycle Listener implementation class TestLisenter
*
*/
@WebListener
public class TestLisenter implements ServletContextListener, HttpSessionListener, ServletRequestListener {
/**
* Default constructor.
*/
public TestLisenter() {
// TODO Auto-generated constructor stub
}
/**
* @see HttpSessionListener#sessionCreated(HttpSessionEvent)
*/
public void sessionCreated(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}
/**
* @see ServletRequestListener#requestDestroyed(ServletRequestEvent)
*/
public void requestDestroyed(ServletRequestEvent arg0) {
// TODO Auto-generated method stub
}
/**
* @see ServletRequestListener#requestInitialized(ServletRequestEvent)
*/
public void requestInitialized(ServletRequestEvent arg0) {
// TODO Auto-generated method stub
}
/**
* @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
*/
public void sessionDestroyed(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
}
仿照下面程序做一個(gè)在線人數(shù)統(tǒng)計(jì)計(jì)數(shù)器
https://blog.csdn.net/troubleshooter/article/details/78416857
注意:
1、application 的類型為ServletContext
2崖咨、可使用哪些方法取得Web容器環(huán)境ServletContext對(duì)象?
request.getServletContext 锻拘、 sessoin.getServletContext 、 servletConfig.getServletContext
在編寫(xiě)Servlet時(shí)击蹲,需要繼承HttpServlet類署拟,在Servlet中聲明doGet()和doPost()需要HttpServletRequest和HttpServletResponse類型的兩個(gè)參數(shù)。
ServletContextListener:服務(wù)啟動(dòng)和停止時(shí)觸發(fā)期初始化和銷(xiāo)毀(生命周期最長(zhǎng))
HttpSessionListener:session的建立和銷(xiāo)毀(session超時(shí)或調(diào)用invalidate()方法)時(shí)觸發(fā)期初始化和銷(xiāo)毀(其次)
ServletRequestListener:一次請(qǐng)求和響應(yīng)有效(最短)
如果同時(shí)存在監(jiān)聽(tīng)器和過(guò)濾器歌豺,先走監(jiān)聽(tīng)器再走過(guò)濾器.
在線人數(shù)統(tǒng)計(jì)
package com.neuedu.utils;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* Application Lifecycle Listener implementation class MyFilter
*
*/
@WebListener
public class MyListener implements ServletContextListener {
/**
* Default constructor.
*/
public MyListener() {
// TODO Auto-generated constructor stub
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("上下文銷(xiāo)毀");
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
* ServletContext---application
*/
public void contextInitialized(ServletContextEvent applicationEvent) {
ServletContext application=applicationEvent.getServletContext();
//在線人數(shù)推穷,初始化為0
application.setAttribute("onlinenumber", 0);
System.out.println("上下文創(chuàng)建");
}
}
package com.neuedu.utils;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Application Lifecycle Listener implementation class MySessionListenter
*
*/
@WebListener
public class MySessionListenter implements HttpSessionListener {
/**
* Default constructor.
*/
public MySessionListenter() {
// TODO Auto-generated constructor stub
}
/**
* @see HttpSessionListener#sessionCreated(HttpSessionEvent)
*/
public void sessionCreated(HttpSessionEvent sessionEvent) {
System.out.println("sessionCreated建立");
//從session/request里都可以得到ServletContext--->sessionEvent.getSession可以獲取
HttpSession session=sessionEvent.getSession();
ServletContext application= session.getServletContext();
int old_online=(Integer)application.getAttribute("onlinenumber");
//如果有用戶訪問(wèn),我們就把計(jì)數(shù)器加1
int new_online=old_online+1;
application.setAttribute("onlinenumber", new_online);
System.out.println("新的在線人數(shù)"+new_online);
}
/**
* @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
*/
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
System.out.println("sessionDestroyed");
//從session/request里都可以得到ServletContext--->sessionEvent.getSession可以獲取
HttpSession session=sessionEvent.getSession();
ServletContext application= session.getServletContext();
int old_online=(Integer)application.getAttribute("onlinenumber");
//如果有用戶訪問(wèn)类咧,我們就把計(jì)數(shù)器加1
int new_online=old_online-1;
application.setAttribute("onlinenumber", new_online);
System.out.println("新的在線人數(shù)"+new_online);
//如果有用戶退出或超時(shí)馒铃,我們就把計(jì)數(shù)器-1
}
}
前臺(tái)頁(yè)面
在線人數(shù):${onlinenumber}
如果登錄成功才認(rèn)為是在線
@Override
public void attributeAdded(HttpSessionBindingEvent sessionEvent) {
// TODO Auto-generated method stub
User user=(User)sessionEvent.getSession().getAttribute("loginUser");
HttpSession session=sessionEvent.getSession();
ServletContext application= session.getServletContext();
int old_online=(Integer)application.getAttribute("onlinenumber");
//如果有用戶訪問(wèn),我們就把計(jì)數(shù)器加1
if(user!=null){
int new_online=old_online+1;
application.setAttribute("onlinenumber", new_online);
System.out.println("新的在線人數(shù)"+new_online);
}
}