学习笔记【JavaWeb-第十二节:Filter 与 Listener】

Filter:过滤器

生活中的过滤器:净水器,空气净化器。

web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。

过滤器的作用:一般用于通用的操作。如登录验证、统一编码处理、敏感字符过滤…

快速入门

步骤:

  • 定义一个类,实现接口Filter
  • 复写方法
  • 配置拦截路径
    • web.xml
    • 注解

代码:

url-pattern原是@WebFilter中的,也为value,只有一个值,可省略

@WebFilter("/*")//访问所有资源之前都会执行该过滤器
public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

过滤器细节

web.xml配置
<filter>
    <filter-name>demo1</filter-name>
    <filter-class>cn.huangyy.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
    <filter-name>demo1</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
过滤器执行流程
  • 执行过滤器
  • 执行放行后的资源
  • 回来执行过滤器放行代码下边的代码
过滤器的生命周期

init:
在服务器启动后,会创建Filter对象,然后调用init方法。用于加载资源

doFilter:
每次请求被拦截资源时,会执行。执行多次。

destroy:
在服务器关闭后,Filter对象被销毁。如果正常关闭,会执行destroy方法。用于释放资源

过滤器配置详解

拦截路径配置

  • 具体资源路径:/index.jsp,只有访问index资源时,过滤器才会被执行。
  • 拦截目录:/user/* ,访问/user下的所有资源时,过滤器都会被执行
  • 后缀名拦截:*.jsp,访问所有后缀名为jsp的资源时,过滤器都会被执行
  • 拦截所有资源:/*

拦截方式配置:资源被访问的方式

  • 注解配置
    设置dispatcherTypes属性
    REQUEST:默认值。浏览器直接请求资源
    FORWARD:转发访问资源
    INCLUDE:包含访问资源
    ERROR:错误跳转资源
    ASYNC:异步访问资源

  • web.xml配置
    设置dispatcher标签,也有五个

过滤器链(配置多个过滤器)

执行顺序:
如果有两个过滤器:过滤器1和过滤器2

  • 过滤器1
  • 过滤器2
  • 资源执行
  • 过滤器2
  • 过滤器1

过滤器先后顺序问题:
注解配置的,按照类名字符串比较规则比较,值小的先执行。

web.xml配置的,谁定义在上面,谁就先执行


案例:

1.登录案例

@WebFilter("/*")
public class LoginFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request= (HttpServletRequest) req;
        String uri = request.getRequestURI();
        if (uri.contains("/login.jsp")||uri.contains("/loginServlet")||
                uri.contains("/css/")||uri.contains("/js/")||uri.contains("/fonts/")||uri.contains("/checkCodeServlet")){//要注意css/js/图片/验证码等资源
            chain.doFilter(req, resp);
        }else {
            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);
            }
        }
    }

    public void init(FilterConfig config) throws ServletException {

    }

    public void destroy() {
    }
}

2.敏感词汇

功能增强,可用代理模式

  • 真实对象:被代理的对象
  • 代理对象
  • 代理模式:代理模式代理真实对象,达到增强真实对象功能的目的

静态代理:有一个类文件描述代理模式
动态代理:在内存中形成代理类

实现步骤:
代理对象和真实对象实现相同的接口
代理对象=Proxy.newInstance();
使用代理对象调用方法

增强方式:
增强参数列表
增强返回值类型
增强方法体执行逻辑

回到敏感词汇:
对request对象进行增强。增强获取参数相关的方法
放行。传递代理对象

如:

@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //创建代理对象,增强getParameter方法
        //放行

        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getName().equals("getParameter")){
                    String value = (String) method.invoke(req, args);
                    if (value!=null){
                        for (String str:list) {
                            if (value.contains(str)){
                                value.replaceAll(str,"***");
                            }
                        }
                    }
                    return value;

                }

                return method.invoke(req,args);
            }
        });


        chain.doFilter(proxy_req, resp);
    }

    private List<String> list=new ArrayList<>();
    public void init(FilterConfig config) throws ServletException {
        try {
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("?WEB-INF/classes/敏感词汇表.txt");
            BufferedReader reader=new BufferedReader(new FileReader(realPath));
            String line=null;
            while ((line=reader.readLine())!=null){
                list.add(line);
            }
            reader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void destroy() {
    }
}

Listener监听器

web的三大组件之一。
事件监听机制
事件:一件事情
事件源:事情发生的地方
监听器:一个对象
注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生某个事件后,执行监听器代码

ServletContextListener
监听ServletContext对象的创建和销毁
void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁之前会调用该方法
void contextInitialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法

步骤:
定义一个类实现ServletContextListener接口
复写方法

配置
注解:
@WebListener

xml:
还可指定初始化参数

<listener>
    <listener-class>cn.huangyy.web.listen.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>

如:

@WebListener
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext servletContext=sce.getServletContext();

        String contextConfigLocation= servletContext.getInitParameter("contextConfigLocation");
        String realPath = servletContext.getRealPath(contextConfigLocation);

        FileInputStream fis=new FileInputStream(realPath);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值