课程目标
掌握过滤器概念及两种编写方法
过滤器Filter
过滤器也叫拦截器,在一个层面上解决问题。
应用:用来做统一编码解码、用来做权限验证、做网站计数等等
特殊说明:过滤器可以是一个链。也就是说可以配置多个过滤器,我们也可以通过配置来控制顺序
怎么建filter
servlet3.0以后。可以用向导建
例如:我建一个统一做编码处理的
我们之前在每个servlet里要写
request.setChararcterEncoding("utf-8");
response.setChararcterEncoding("utf-8");
file-new -Filter-按向导一步步配置。
step1 为filter起个文件名CharacterFilter
step2 设置初始化参数 encoding:UTF-8
step3 mapping 配置过滤对象(1--可以对指定的servlet进行过滤 2--可以配置过滤规则)
配置完成后生成如下代码:
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
}
}
我们看到有三个主要方法
init() 初始化方法:做准备工作
doFilter() 业务方法
需要注意的是:j里面有一个
chain.doFilter(request, response);这句话的意思是执行完该过滤器后去执行下一个过滤器
用@WebFilter方式配置的过滤器执行顺序是按filterName首字母的先后顺序执行。
destroy() 销毁方法:做清理工作
完整代码如下:
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 {
//在初始化时准备好编码方式
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);
//执行下一个过滤器
chain.doFilter(request, response);
}
/**
* @see Filter#destroy()
*/
public void destroy() {
encode="";
}
}
filter另外一种创建方式
servlet3.0之前
简化版
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 写一个类实现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);
//执行下一个过滤器
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>
过滤器使用
日志记录
登录验证
编码处理
后台登录拦截
可以定个规则,比如所有需要登录才能访问的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("进入拦截器");
//在此处做用户是否登录的验证
//判断session里是否存在loginUser
HttpServletRequest httprequest=(HttpServletRequest)request;
HttpSession session=httprequest.getSession();
Object obj=session.getAttribute("loginUser");
if(obj!=null){
//如果有就放行
chain.doFilter(request, response);
return ;
}else{
//如果没有,就回登录页
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
}
}
监听器
监听事件,比如session建立,系统启动,请求到达
本质也是java类。
建立方式
file-new listener-输入名称-选择监听器种类
比如我选择了以下三个 ServletContextListener, HttpSessionListener, ServletRequestListener
系统会自动生成如下类
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
}
}
仿照下面程序做一个在线人数统计计数器
https://blog.csdn.net/troubleshooter/article/details/78416857
注意:
1、application 的类型为ServletContext
2、可使用哪些方法取得Web容器环境ServletContext对象?
request.getServletContext 、 sessoin.getServletContext 、 servletConfig.getServletContext
在编写Servlet时,需要继承HttpServlet类,在Servlet中声明doGet()和doPost()需要HttpServletRequest和HttpServletResponse类型的两个参数。
ServletContextListener:服务启动和停止时触发期初始化和销毁(生命周期最长)
HttpSessionListener:session的建立和销毁(session超时或调用invalidate()方法)时触发期初始化和销毁(其次)
ServletRequestListener:一次请求和响应有效(最短)
如果同时存在监听器和过滤器,先走监听器再走过滤器.
在线人数统计
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("上下文销毁");
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
* ServletContext---application
*/
public void contextInitialized(ServletContextEvent applicationEvent) {
ServletContext application=applicationEvent.getServletContext();
//在线人数,初始化为0
application.setAttribute("onlinenumber", 0);
System.out.println("上下文创建");
}
}
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");
//如果有用户访问,我们就把计数器加1
int new_online=old_online+1;
application.setAttribute("onlinenumber", new_online);
System.out.println("新的在线人数"+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");
//如果有用户访问,我们就把计数器加1
int new_online=old_online-1;
application.setAttribute("onlinenumber", new_online);
System.out.println("新的在线人数"+new_online);
//如果有用户退出或超时,我们就把计数器-1
}
}
前台页面
在线人数:${onlinenumber}
如果登录成功才认为是在线
@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");
//如果有用户访问,我们就把计数器加1
if(user!=null){
int new_online=old_online+1;
application.setAttribute("onlinenumber", new_online);
System.out.println("新的在线人数"+new_online);
}
}