Filter与Listener入门
Filter:过滤器
Filter概述
-
JavaWeb三大组件之一,与Servlet很相似,Servlet处理请求,Filter拦截请求的。当客户端发送请求的时候,会经过过滤器,然后才能到servlet,当我们的servlet处理完请求之后,我们的response还是先经过过滤器才能到达客户端
-
Filter也称之为过滤器,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
-
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
Filter使用步骤
- 定义一个类实现javax.servlet下的Filter接口,并重写接口中的所有抽象方法
- 自定义filter模板:settings->Editor->File and Code Templates->Other选项卡->Web->Filter Annotated Class.java
package cn.simplek9.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; public class filter2 implements Filter {//注意是javax.servlet下的Filter public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //去的时候对request对象请求消息进行操作 System.out.println("filter2被执行了......"); //放行,没有该语句无法访问被拦截的资源 chain.doFilter(req, resp); //回来的时候对response对象响应消息进行操作 System.out.println("filter2回来了......"); } public void init(FilterConfig config) throws ServletException { } }
- 配置Filter
- 拦截路径配置:
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
- 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
- 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
- 拦截方式配置:资源被访问的方式 注解配置设置dispatcherTypes属性,web.xml配置设置的子标签
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
- 配置拦截路径(必选),配置拦截方式:资源被访问的方式(可选)
- 方法一:在项目的web/WEB-INF/web.xml的根标签中配置
<filter> <filter-name>demo1</filter-name><!--给该filter所起的名字--> <filter-class>cn.simplek9.web.filter.filter</filter-class><!--src下的全类名--> </filter> <filter-mapping> <filter-name>demo1</filter-name> <url-pattern>/*</url-pattern><!--该filter的拦截路径--> <dispatcher>REQUEST</dispatcher><!--配置拦截方式--> </filter-mapping>
- 方法二:类前使用@WebFilter("拦截路径")注解配置
//仅配置拦截路径 //@WebFilter("/hello.jsp")//拦截index.jsp资源 //@WebFilter("/user/*")//拦截/user下的所有资源 //@WebFilter("*.jsp")//拦截所有jsp资源 @WebFilter("/*")//拦截所有资源
//配置拦截路径与拦截方式 //浏览器直接请求index.jsp资源时,该过滤器会被执行 //@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST) //只有转发访问index.jsp时,该过滤器才会被执行 //@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.FORWARD) //浏览器直接请求index.jsp或者转发访问index.jsp时,该过滤器才会被执行 @WebFilter(value="/index.jsp",dispatcherTypes ={DispatcherType.FORWARD,DispatcherType.REQUEST})
Filter生命周期方法
- init:在服务器启动后,会创建Filter对象,然后调用init方法。(一次)
- 可以读取web.xml文件中Servlet过滤器的初始化参数。
- doFilter:每一次请求被拦截资源时执行。(多次)
- 调用chain.doFilter(request,response)方法完成对下一个过滤器的调用,如果没有下一个过滤器,则把客户请求传给相应的web组件(放行)。
- destroy:在销毁过滤器实例之前调用该方法,以释放占用的资源(一次)
过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器:过滤器1和过滤器2 过滤器1 ->过滤器2->资源执行->过滤器2->过滤器1
- 过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较字典序,字典序小的先执行
- 如: AFilter 和 BFilter,AFilter就先执行了。
- web.xml配置: 谁定义在上边,谁先执行
- 注解配置:按照类名的字符串比较字典序,字典序小的先执行
Filter登录验证
登录成功时,会在 session 中存入 login_msg 值,所以可以以此判读用户是否登录
package cn.itcast.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 登录验证的过滤器
*/
@WebFilter("/*")
public class LoginFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//0.强制转换,HttpServletRequest是ServletRequest的子类,因为要用到Http相应请求和响应方法,所以要强转
HttpServletRequest request = (HttpServletRequest) req;
//1.获取资源请求路径
String uri = request.getRequestURI();
//2.判断是否包含登录相关资源路径,要注意排除掉 css/js/图片/验证码等资源
if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet") ){
//包含,用户就是想登录。放行
chain.doFilter(req, resp);
}else{
//不包含,需要验证用户是否登录
//3.从获取session中获取user
Object user = request.getSession().getAttribute("user");
if(user != null){
//登录了。放行
chain.doFilter(req, resp);
}else{
//没有登录。跳转登录页面
request.setAttribute("login_msg","您尚未登录,请登录");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
}
}
// chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
Listener:监听器
Listener概述
- JavaWeb三大组件之一,监听器就是监听某个域对象的的状态变化的组件
- 监听器的相关概念:
- 事件源:被监听的对象(三个域对象 request、session、servletContext)
- 监听器:监听事件源对象事件源对象的状态的变化都会触发监听器(6+2)
- 注册监听器:将监听器与事件源进行绑定
- 响应行为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)
Listener使用步骤
- 定义一个类实现ServletContextListener接口,并重写接口中的所有抽象方法
package cn.simplek9.web.listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import java.io.FileInputStream; import java.io.FileNotFoundException; @WebListener//不需要路径 public class listener implements ServletContextListener { /* * 监听ServletContext对象创建的。会在服务器启动后自动调用 * */ @Override public void contextInitialized(ServletContextEvent sce) {//ServletContext对象创建后会调用该方法 //加载资源文件 //1.获取ServletContext对象 ServletContext servletContext = sce.getServletContext(); //2.加载资源文件 String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation"); //3.获取真实路径 String realPath = servletContext.getRealPath(contextConfigLocation); //4.加载进内存 try { FileInputStream fis = new FileInputStream(realPath); System.out.println(fis); } catch (FileNotFoundException e) { e.printStackTrace(); } System.out.println("ServletContext对象被创建了"); } /* * 在服务器关闭后,ServletContext对象被销毁。会在服务器正常关闭后自动调用 * */ @Override public void contextDestroyed(ServletContextEvent sce) {//ServletContext对象被销毁之前会调用该方法 System.out.println("ServletContext对象被销毁了"); } }
- 配置Listener
- 方法一:在项目的web/WEB-INF/web.xml的根标签中配置
<listener> <listener-class>cn.simplek9.web.listener.listener</listener-class> </listener>
<!--指定初始化参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/config.xml</param-value> </context-param>
- 方法二:类前使用@WebListener注解配置
@WebListener
- 方法一:在项目的web/WEB-INF/web.xml的根标签中配置