Java Servlet之Filte(过滤器)详解


提示:以下是本篇文章正文内容,下面案例可供参考

一、Filter是什么?

webServlet有三大组件:Servlet Filter(过滤器) Listerner (监听器)

生活中中的过滤器有哪些?

​ 净水器的滤芯 空心滤芯 鱼网

网络中拦截器:

​ 有些网站必须是在登录下才能访问,比如咱们测评系统,一打开网址,就是登录页面

​ 必须先登录的一些网站
过滤器有什么作用?

​ 验证信息登录,处理字符问题,过滤跳转等

WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

就是咱们请求一个资源的时候,先通过Filter进行拦截,如果你能符合我的条件我就放行。让你继续去请求资源,如果你不符合我的条件,我就不让你去请求这个资源

二、Filter的入门案例

1.自定义一个类去实现一个接口Fileter

2.重写方法

3.配置Filter

​ 注解写法(只用这种情况)

​ 配置写法

e n d end end没有出来什么意思?index.jsp被拦截了?为什么他被拦截了?过滤器我写的是/*,就意味着所有的

资源都要被拦截。

代码如下(示例):

package com.qfedu.b_filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//@WebFilter("/*") 我要去拦截你所有的资源
@WebFilter("/*")

public class FilterDemo1 implements Filter {
    //写着构造方法的目的,目的是为了让你知道这个FilterDemo1被实例化了没?
    public FilterDemo1(){
        System.out.println("我是FilterDemo1的构造方法");
    }

    public void destroy() {
        System.out.println("FilterDemo1这个过滤器被销毁");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //是核心方法,一般的业务逻辑写在这个地方
        System.out.println("doFilter called ....");
//        chain.doFilter(req, resp);  放行代码
        //如果这个地方没有写chain.doFilter(req,resp);
        //代码走到这个地方,资源就会被拦截,不再往下走了
        chain.doFilter(req,resp);//放行,先走的是Servlet,再回到我们的过滤器
        /*
        * if语句,该放行的就写一个chain.doFilter(req,resp);//放行
        * 不该放行的话,让他跳转到其它页面
        * */
        System.out.println("放行完以后资源访问继续");
    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("FilterDemo1这个过滤器被初始化");
    }

}

三、Filter注解和配置文件的写法

优先选择注解写法,方便简单,两者只能选择其一

3.1配置文件的写法

① 需要在web.xml文件写配置
web.xml文件代码如下

代码如下(示例):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <filter>
        <filter-name>FilterDemo2</filter-name>
        <filter-class>com.qfedu.b_filter.FilterDemo2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
package com.qfedu.b_filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

public class FilterDemo2 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

3.2注解的写法【推荐使用】

代码如下(示例):

package com.qfedu.b_filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//@WebFilter("/*") 我要去拦截你所有的资源
@WebFilter("/*")

public class FilterDemo1 implements Filter {
    //写着构造方法的目的,目的是为了让你知道这个FilterDemo1被实例化了没?
    public FilterDemo1(){
        System.out.println("我是FilterDemo1的构造方法");
    }

    public void destroy() {
        System.out.println("FilterDemo1这个过滤器被销毁");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //是核心方法,一般的业务逻辑写在这个地方
        System.out.println("doFilter called ....");
//        chain.doFilter(req, resp);  放行代码
        //如果这个地方没有写chain.doFilter(req,resp);
        //代码走到这个地方,资源就会被拦截,不再往下走了
        chain.doFilter(req,resp);//放行,先走的是Servlet,再回到我们的过滤器
        /*
        * if语句,该放行的就写一个chain.doFilter(req,resp);//放行
        * 不该放行的话,让他跳转到其它页面
        * */
        System.out.println("放行完以后资源访问继续");
    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("FilterDemo1这个过滤器被初始化");
    }

}

四、Filter的细节处理

4.1Filter的执行流程

浏览器访问资源路径的时候,会先匹配咱们的Filter,会被拦截下面(要么放行,要么拦截)

1.先执行的Filter

2.看是否满足条件

​ 如果你满足我的条件,我就放行,让你去请求下面的资源

​ 如果你不满我的条件,我就拦截,哪里来回那里去

3.放行执行资源,又回到拦截器给客户端响应

4.2Filter的生命周期

和Servlet的生命周期特别像

1.Filter构造方法要执行。实例化了Filter

2.Filter初始化 init

3.doFilter() 核心方法

4.服务器关闭,Filter正常销毁

4.3Filter过滤路径的问题【重点】

设置过滤拦截的路径

1.精准拦截

@WebFilter(“/index.jsp”);拦截的就是index.jsp
@WebFilter(“/test”);拦截的就是test这个资源

2.拦截某一个目录

@WebFilter(“/user/*”);拦截uesr下面的所有的资源

3.拦截指定后缀的资源

*.do
*.jsp
*.html

4.拦截所有的资源

/*

package com.qfedu.b_filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//精准拦截
//@WebFilter("/index.jsp")
//@WebFilter("/test")
//@WebFilter("/user/*")//拦截/user下面所有的资源
//@WebFilter("*.jsp")//拦截后缀为.jsp都拦截
//@WebFilter("/*")//拦截所有的资源,讲案例的时候会用!!!
public class FilterDemo3 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//        chain.doFilter(req, resp);//放行的代码关闭
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

4.4拦截方式有哪些参数【了解】

@WebServlet() 有很多参数 比如name value urlPatterns loadOnStartup
都不用
@WebFilter()也有参数
firstName value

dispatcherTypes属性是在转发的时候,拦截请求的次数

package com.qfedu.b_filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/*
*  value 拦截哪些资源
*  dispatcherTypes  和我们转发有关  但是真实开发不用
*  dispatcherTypes = {DispatcherType.REQUEST}如果是这个参数,请求被拦截一次
*  因为转发在服务器中就是一次请求,两次响应
*  dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}
*  如果是这个参数,请求被拦截两次,转发到test.jsp这个页面也是被拦截的
 *
* */
@WebFilter(value = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class FilterDemo4 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //请求被拦截
        System.out.println("请求被拦截");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

4.5过滤器链【了解】

如果有多个过滤到底谁先执行呢?

多个过滤器的时候,执行的顺序是非常随意的,按照字符串进行比较,升序进行的

AFilter BFilter 是先AFilter 再BFilter

数字的话,先执行1 再执行2
FilterDemo5…
FilterDemo6…
FilterDemo6!!!
FilterDemo5 !!!

package com.qfedu.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter( "/*")
public class FilterDemo5 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo5........");
        chain.doFilter(req, resp);
        System.out.println("FilterDemo5  !!!!!");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

package com.qfedu.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo6 implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo6......");
        chain.doFilter(req, resp);
        System.out.println("FilterDemo6!!!!");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

五、过滤器的综合案例

大家使用网站都是什么样的网站,一输入网址就直接跳转到登录页面
大家想一下咱们今天上午写的那个东西,一进来是登录页面?不是的
咱们能不能你写一个请求,无论怎么写?都是进的登录页面?可以的
http://localhost:8080/day43_wb1/sb 也让你跳转到登录页面
和咱们上午写的类似,但是加了过滤器,过滤所有的资源,只放行一个资源login.html

你的网站必须一上去就是登录页面!!!淘宝和京东是半功能性网站。咱们现在要求一进去就是一个登录页面。只是在Filte里面写几个if-else语句,啥时候放行啥时候不放行自己要清楚

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="LoginServlet" method="post">
        姓名:<input type="text" name="user"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

LoginServlet.java

package com.qfedu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取前端(html页面取过来的)传过来的数据
        //因为采用的是post请求,会乱码,解决中文乱码问题
        request.setCharacterEncoding("utf-8");
        String user = request.getParameter("user");
        String password = request.getParameter("password");

        //验证登录信息,连上数据库,写一个sql语句进行判断user和password
        //现在我不写,你们可以试一试,我写的是死数据
        //"张三"  数据库拿出来,但是我现在只写一个字符串写死了
        if("张三".equals(user)&&"123456".equals(password)){
            //之前将的登录成功以后就直接跳转到主页面了,但是现在
            //我再做一件事,把"张三"存到session中

            //1.创建session对象
            HttpSession session = request.getSession();
            //2.获取当前session对象的id  服务器对session唯一的标识
            String id = session.getId();
            //3.创建cookie对象,键叫做JSESSIONID 值 id
            Cookie cookie = new Cookie("JSESSIONID", id);
            //设置cookie的有效时间
            cookie.setMaxAge(60*60*24);
            //4.发送到浏览器进行保存
            response.addCookie(cookie);
            //5.设置session的值
            session.setAttribute("user","张三");
            //6.一旦session有值,重定向到IndexServlet
            //跳转到主页面
            response.sendRedirect("IndexServlet");
        }else{
            response.sendRedirect("login.html");
        }
    }
}

IndexServlet.java:

package com.qfedu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/IndexServlet")
public class IndexServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符集,解决中文乱码问题
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //还需要判断session吗?不需要判断了,因为我们的过滤器过滤掉了
        //过滤器过滤的就是session为空的情况,所以这个地方不用再判断session是否为空了
        //session存的有值的情况
        HttpSession session = request.getSession(false);
        String html = "<font size='7' color='red'>欢迎"+session.getAttribute("user")
                +"来到澳门皇冠洗浴中心<font><br>";
        html += "<a href='ExitServlet' style='color:pink;font-size=20px'>退出</a>";
        response.getWriter().append(html);
    }
}


ExitServlet.java:

package com.qfedu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/ExitServlet")
public class ExitServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取session对象
        HttpSession session = request.getSession();
        if (session != null){
            //销毁session
            session.invalidate();
            //销毁cookie
            Cookie cookie = new Cookie("JSESSIONID", "");
            cookie.setMaxAge(0);//这样才是销毁cookie
            //发送到浏览器进行保存
            response.addCookie(cookie);
            //销毁以后重定向到login.html
            response.sendRedirect("login.html");
        }
    }
}

LoginFilter.java:

package com.qfedu.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/*
*
* 先拦截你所有的资源,然后放行login.html
* */
@WebFilter("/*")
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //符合login.html我就放行,其它不放行
        System.out.println("doFilter");
        //获取session
        HttpSession session = ((HttpServletRequest) req).getSession();
        System.out.println(session);

        //如果session为null,就跳转到登录页面
        //http://localhost:8080/day43_xkh2/IndexServlet
        //http://localHost:8080/day43_xkh2/login.html放行
        //http://localhost:8080/day43_xkh2/LoginServlet放行,最后也是跳转到login.html

        //获取url的一部分/day43_xkh2/IndexServlet
        String requestURI = ((HttpServletRequest) req).getRequestURI();
        System.out.println(requestURI);//统一资源标识符

        //登录相关资源,不应该过滤的应该放行
        if (requestURI.endsWith("/login.html") || requestURI.endsWith("/LoginServlet")){
            //放行
            chain.doFilter(req,resp);
        }else if (session == null || session.getAttribute("user") == null){
            //session为空,就证明你没有登陆过,所以不能放行
            //跳转到登录页面
            ((HttpServletResponse)resp).sendRedirect("login.html");
        }else if (session != null && session.getAttribute("user") != null){
            //session不为空且session里面的值也不为空,就证明你登录过了
            //放行
            chain.doFilter(req,resp);
        }

    }

    public void init(FilterConfig config) throws ServletException {

    }

}

结果如下(示例):

程序点击运行,就直接跳转到登录界面
在这里插入图片描述
输入姓名:张三 密码:123456
在这里插入图片描述
点击登录,就跳转到主页面了
在这里插入图片描述

点击退出,跳转到登录页面

在这里插入图片描述

总结

提示:这里对文章进行总结:
以上就是今天要讲的内容.

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,关于Java过滤器Filter的使用,我可以给您一些详解Java过滤器Filter是一种Web组件,它可以对请求(request)和响应(response)进行过滤和处理。通常情况下,我们使用Java过滤器Filter来对请求进行预处理,或者对响应进行后处理。这样可以减轻Servlet的负担,提高程序的可重用性。 Java过滤器Filter的使用非常简单,只需要创建一个Java类,实现javax.servlet.Filter接口,并重写doFilter方法即可。在doFilter方法中,我们可以对请求和响应进行处理,然后将它们传递给下一个过滤器Servlet。 下面是一个简单的Java过滤器Filter的示例,它可以过滤掉某个包的请求: ``` public class PackageFilter implements Filter { private String packageName; @Override public void init(FilterConfig filterConfig) throws ServletException { packageName = filterConfig.getInitParameter("packageName"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String path = req.getServletPath(); if (path.startsWith(packageName)) { // 过滤掉指定包的请求 return; } chain.doFilter(request, response); } @Override public void destroy() { // do nothing } } ``` 在这个例子中,我们通过init方法获取了过滤器初始化参数packageName,然后在doFilter方法中判断请求路径是否以packageName开头,如果是,则直接返回,否则将请求传递给下一个过滤器Servlet。 使用Java过滤器Filter可以方便地对请求和响应进行处理,从而提高程序的可重用性和性能。同时,Java过滤器Filter还可以通过配置文件进行灵活的配置,满足不同场景的需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小yu别错过

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值