Filter (Servlet过滤器)

Filter (Servlet过滤器)

Filter:是Servlet2.3新增的一个特性,同时它也是Servlet技术中最实用的技术。开发人员可以通过Filter技术,能够实现对所有Web资源的管理,如实现权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

  • Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是Servlet 程序、Listener 监听器、Filter 过滤器。

  • Filter 过滤器它是 JavaEE 的规范,也就是一个接口。

  • Filter 过滤器它的作用是:

    拦截请求和过滤响应。拦截请求常见的应用场景有权限检查、日记操作、事务管理等等。例如:登录验证,统一编码处理,敏感字符过滤~~

Servlet需要拿到response和request两个对象,Filter同样需要拿到response和request对象才能进行过滤处理,所以过滤器和Servlet类似,只是Servlet实现HttpServlet接口,过滤器实现Filter接口,注意有很多Filter的接口,实现Maven导的servlet的包的Filter接口

Servlet 的 Filter 特点:

  1. 声明式的
    通过在 web.xml 配置文件中声明,允许添加、删除过滤器,而无须改动任何应用程序代码或 JSP 页面。
  2. 灵活的
    过滤器可用于客户端的直接调用执行预处理和后期的处理工作,通过过滤链可以实现一些灵活的功能。
  3. 可移植的
    由于现今各个 Web 容器都是以 Servlet 的规范进行设计的,因此 Servlet 过滤器同样是跨容器的。
  4. 可重用的
    基于其可移植性和声明式的配置方式,Filter 是可重用的。

总的来说,Servlet 的过滤器是通过一个配置文件来灵活的声明的模块化可重用组件。过滤器动态的截获传入的请求和传出的响应,在不修改程序代码的情况下,透明的添加或删除他们。其独立于任何平台和 Web 容器。

核心方法:

返回值 方法名 作用
void init(FilterConfig config) 初始化方法
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 对请求资源和响应资源进行拦截
void destroy() 销毁方法

Filter开发步骤:

  1. 导包

  2. 编写过滤器

    例子:处理乱码的过滤器

    public class CharacterEncodingFilter implements Filter {
        //初始化:web服务器启动的时候,就已经执行了初始化,随时等待过滤对象出现
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("CharacterEncodingFilter初始化");
    
        }
    
        //对请求资源和响应资源进行拦截
        @Override
        //chain:链
        /*
        * 1. 过滤中的所有代码,在过滤特定请求的时候都会执行
        * 2. 必须要让过滤器继续执行,所以必须要写
        *    filterChain.doFilter(servletRequest,servletResponse);
        * */
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletRequest.setCharacterEncoding("utf-8");
            servletResponse.setCharacterEncoding("utf-8");
            servletResponse.setContentType("text/html;charset=UTF-8");
            System.out.println("CharacterEncodingFilter执行前...");
            filterChain.doFilter(servletRequest,servletResponse);//让我们的请求继续走,如果不写程序就会在在这里被拦截停止
            System.out.println("CharacterEncodingFilter执行后");
        }
    
        //销毁:服务器关闭时,过滤器会销毁
        @Override
        public void destroy() {
            System.out.println("CharacterEncodingFilter销毁");
    
        }
    }
    
  3. 在web.xml中配置过滤器

    <filter>
        <filter-name>characterEncodingFiter</filter-name>
        <filter-class>com.yue.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFiter</filter-name>
        <!--servlet/下的任何请求都会经过这个过滤器-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
    

可以写一个会出现乱码的Servlet进行测试:

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("你好,世界");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在web.xml中配置Servlet,配置两个请求路线,以用来测试过滤器的效果

<servlet>
    <servlet-name>showServlet</servlet-name>
    <servlet-class>com.yue.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>showServlet</servlet-name>
    <url-pattern>/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>showServlet</servlet-name>
    <url-pattern>/servlet/show</url-pattern>
</servlet-mapping>

由于上面的过滤器过滤的是servlet/下的任何请求,所以路径为/servlet/show的页面正常显示"你好,世界"的中文,而路径为/show的页面则会出现乱码

过滤器的常见应用:

例:用户登录后才能进入主页

有些页面需要用户登录才可以查看,如果不设置过滤器,则客户端可直接访问域名进入特定页面,故需要过滤器来筛选登录的客户端

  1. 创建一个util包,定义一个Constant类,用来定义一些常量,方便实用,这里只定义一个USER_SESSION,要在登录的session中添加这个属性

    public class Constant {
        public final static String USER_SESSION = "USER_SESSION";//定义一个唯一的常量USER_SESSION
    }
    
  2. 自定义一个登录的servlet:LoginServlet

    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取前端请求的参数
            String username = req.getParameter("username");
            if (username.equals("admin")){//当输入为admin时就登陆成功,其他的就登录失败
                req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());//在session中添加一个属性USER_SESSION,在Constant设置这个常量,方便日后维护
                resp.sendRedirect(req.getContextPath()+"/sys/success.jsp");//因为有项目名所以写成:req.getContextPath()+"路径",等同于:"项目名/路径"
            }else {//登录失败
                resp.sendRedirect(req.getContextPath()+"/error.jsp");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  3. 自定义一个注销登录的servlet:LogoutServlet

    public class LogoutServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
            if (user_session!=null){
                req.getSession().removeAttribute(Constant.USER_SESSION);//删除session中的USER_SESSION的属性,不必删除session,避免多次创建session
                resp.sendRedirect(req.getContextPath()+"/login.jsp");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  4. 在web.xml中注册LoginServlet和LogoutServlet:

        <servlet>
            <servlet-name>loginServlet</servlet-name>
            <servlet-class>com.yue.servlet.LoginServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>loginServlet</servlet-name>
            <url-pattern>/servlet/login</url-pattern>
        </servlet-mapping>
        
        <servlet>
            <servlet-name>logoutServlet</servlet-name>
            <servlet-class>com.yue.servlet.LogoutServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>logoutServlet</servlet-name>
            <url-pattern>/servlet/logout</url-pattern>
        </servlet-mapping>
    
  5. 自定义一个登录的jsp页面:login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>登陆</h1>
    <form action="${pageContext.request.contextPath}/servlet/login" method="post">
        <input type="text" name="username">
        <input type="submit">
    </form>
    
    </body>
    </html>
    
  6. 自定义一个登录失败的jsp页面:error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>错误</h1>
    <h4>用户名错误</h4>
    <h4>没有权限</h4>
    <a href="${pageContext.request.contextPath}/login.jsp">返回登录页面</a>
    </body>
    </html>
    
  7. 在web包下新建一个sys包,并在里面自定义一个登陆成功的jsp页面success.jsp,并设置注销按钮,注销后跳转到error.jsp页面:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>主页</h1>
    <p><a href="/javaweb_filter/servlet/logout">注销</a></p>
    </body>
    </html>
    
  8. 自定义一个只能让登录用户访问success.jsp页面的过滤器SysFilter,未登录用户则重定向至error.jsp页面

    public class SysFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
    
            //ServletRequest是HttpServletRequest的父类,可以强转
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            if (request.getSession().getAttribute(Constant.USER_SESSION)==null){//如果session中的USER_SESSION属性为空,则重定向至错误页面
                response.sendRedirect(((HttpServletRequest) req).getContextPath()+"/error.jsp");
            }
    
            filterChain.doFilter(req,resp);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
  9. 在web.xml中注册过滤器SysFilter,确保sys下的所有页面都需要权限。

    <filter>
        <filter-name>sysFilter</filter-name>
        <filter-class>com.yue.filter.SysFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>sysFilter</filter-name>
        <url-pattern>/sys/*</url-pattern>
    </filter-mapping>
    
posted @   阿飞bean  阅读(207)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示