JavaWeb之过滤器Filter&监听器

Filter:过滤器,用来过滤网站的数据;

  • 处理中文乱码
  • 登陆验证......

Fitler开发步骤

添加依赖

pom.xml

xml 复制代码
    <dependencies>
        <!--Jsp依赖-->
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        <!--Servlet依赖-->
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!--jstl标签依赖-->
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--standard 依赖-->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--连接数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>

编写过滤器

导包

代码

实现Filter接口,重写对应的方法即可

CharacterEncondingFilter.java

java 复制代码
public class CharacterEncondingFilter implements Filter {

    // Chain:链
    /*
    1.过滤器中的所有代码,在过滤请求的时候都会执行
    2.必须要过滤器继续通行,才能进行转交 chain.doFilter(request, response);死代码

    * */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        System.out.println("过滤执行前");
        chain.doFilter(request, response); //让我们的请求继续走,如果不写,程序在这里就会被拦截。因为如果有其他过滤也会放在链中进行交接
        System.out.println("过滤执行后");
    }

    // 初始化
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //filterConfig. 可以才初始化的时候获得一些东西,但是一般没有必要这样子操作
        System.out.println("CharacterEncondingFilter已经初始化了");
    }

    //销毁:web服务器停止的时候,过滤器会被销毁
    @Override
    public void destroy() {
        //注销的时候也可以进行垃圾回收的额外操作:
        //System.gc();
        System.out.println("CharacterEncondingFilter已经销毁了");
    }
}

ShowServlet.java

java 复制代码
public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        out.write("世界");
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在web.xml配置

xml 复制代码
    <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.cike.servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
        <url-pattern>/cn/show</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.cike.filter.CharacterEncondingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

监听器

实现要给监听器的接口;(有N种)

编写一个HttpSession监听器

实现监听器的接口

java 复制代码
//统计网站在线人数:统计session
//一通百通,有很多个Listener、一年也不一定学的完
public class OnlineCountListener implements HttpSessionListener {
    private static int onlineCount = 0;

    //创建session监听:看你的一举一动(间谍)
    //一旦创建一个Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se){
        //HttpSessionEvent代表session事件的一个对象
        ServletContext ctx = se.getSession().getServletContext();
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        System.out.println(se.getSession().getId());
        if (onlineCount == null){
            onlineCount = new Integer(1);
        }
        else{
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount", onlineCount);

    }


    //销毁session监听
    //一旦销毁Sesson就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se){
        //HttpSessionEvent代表session事件的一个对象
        ServletContext ctx = se.getSession().getServletContext();
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount == null){
            onlineCount = new Integer(0);
        }
        else{
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount", onlineCount);
    }

    /*
    * Session销毁:
    * 手动销毁:getSession()invalidate();
    * 自动销毁:web.xml中进行配置
    * */


}

web.xml注册监听器

xml 复制代码
    <listener>
        <listener-class>com.cike.listen.OnlineCountListener</listener-class>
    </listener>

自动注销session.

xml 复制代码
<session-timeout>
    <!--以分钟为单位-->
    1
</session-timeout>

看情况是否使用

......

过滤器和监听器的常见应用(Gui编写)

  • 工具、写外挂、辅助、木马经常用到这些
java 复制代码
public class TestPanel {
    public static void main(String[] args) {
        Frame title = new Frame("反序列化通杀工具"); //创建窗体
        Panel panel = new Panel(null); // 创建面板
        title.setLayout(null); //设置窗体布局

        title.setBounds(300,300,2000,2000);
        title.setBackground(Color.darkGray);//设置背景颜色

        panel.setBounds(50,50,800,800);
        panel.setBackground(Color.white);//设置背景颜色

        title.add(panel);
        title.setVisible(true);

        //监听事件,监听关闭事件
        title.addWindowListener(new WindowListener() {
            @Override //Windows打开事件
            public void windowOpened(WindowEvent e) {
                System.out.println("Windows打开事件");
            }

            @Override//Windows关闭中事件
            public void windowClosing(WindowEvent e) {
                System.out.println("Windows关闭中事件");
                System.exit(0); //这里的0指的是正常退出、如果是1指的是存在错误(非正常)
            }

            @Override//Windows关闭事件
            public void windowClosed(WindowEvent e) {
                System.out.println("Windows关闭事件");
            }

            @Override//窗体图标被激活事件
            public void windowIconified(WindowEvent e) {

            }

            @Override
            public void windowDeiconified(WindowEvent e) {

            }

            @Override//激活
            public void windowActivated(WindowEvent e) {
                System.out.println("窗体激活事件");
            }

            @Override//窗体未激活
            public void windowDeactivated(WindowEvent e) {
                System.out.println("窗体未激活事件");
            }
        });


    }
}

Filter实现权限拦截(登录实验)

用户登录之后才能进入主页!用户注销后就不能进入!

用户登录之后,向Session中放入用户的数据

进入主页的时候要判断用户是否已经登录;可以过滤器实现

sysFilter.java

java 复制代码
public class sysFilter implements javax.servlet.Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse rep, FilterChain filterChain) throws IOException, ServletException {
        // ServletRequest                      HttpServletRequest   类型不一样,先需要强转换
        // ServletResponse                     HttpServletResponse  类型不一样,先需要强转换
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) rep;
        if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
            response.sendRedirect("/login.jsp");
        }
        filterChain.doFilter(request, response);

    }

    @Override
    public void destroy() {

    }
}

注销的时候不建议销毁session

开发中一般不建议销毁session,因为频繁的创建session是非常消耗资源的。移除session,只是客户端的session值没了,但是服务端还在,可以做到session复用,就不需要频繁的创建session了

LogoutServlet

java 复制代码
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //开发中一般不建议销毁session,因为频繁的创建session是非常消耗资源的
        Object userSession = req.getSession().getAttribute("USER_SESSION");
        if (userSession != null){
        //移除session,只是客户端的session值没了,但是服务端还在,可以做到session复用,就不需要频繁的创建session了
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect("/login.jsp");
        }

    }
}

配置常量SESSION

java 复制代码
public class Constant {
    //常量,不加final也可以
    //final 在Java 中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。 一旦你将引用声明作final,你将不能改变这个引用了
    public final static String USER_SESSION = "userSession";
}

前端视图跳转

index.jsp

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>当前有<span style="color: aquamarine"><%= this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1>
<h1><a href="${pageContext.request.contextPath}/login.jsp">管理员登录</a></h1>


</body>
</html>

login.jsp

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>

<form action="${pageContext.request.contextPath}/login">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="登录">

</form>

</body>
</html>

/sys/success.jsp

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>管理员后台</title>
</head>
<body>

<%--没有过滤器的时候,也可以这样子进行未授权访问的验证
<%
    Object userSession = request.getSession().getAttribute("USER_SESSION");
    if (userSession == null){
        response.sendRedirect("/login.jsp");
    }
%>
--%>



<h1>恭喜你登陆成功</h1>
<p>flag{this_is_flag}</p>

<p><a href="${pageContext.request.contextPath}/logout">注销</a></p>
</body>
</html>

web.xml的配置

xml 复制代码
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.cike.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>logout</servlet-name>
        <servlet-class>com.cike.servlet.LogoutServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>logout</servlet-name>
        <url-pattern>/logout</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>sysFilter</filter-name>
        <filter-class>com.cike.filter.sysFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>sysFilter</filter-name>
        <url-pattern>/sys/*</url-pattern>
    </filter-mapping>
相关推荐
多则惑少则明6 小时前
SpringAI框架接入-jdk升级21后报错“run failed: Unsupported class file major version 65”
java·后端·spring·springai
uup6 小时前
线程池中任务堆积与饥饿死锁问题
java
deng-c-f6 小时前
C/C++内置库函数(2):智能指针
java·c语言·c++
毕设源码-朱学姐6 小时前
【开题答辩全过程】以 基于SSM框架的餐厅点餐系统的设计与实现为例,包含答辩的问题和答案
java·eclipse
pursue.dreams6 小时前
Java实现企业微信机器人消息推送:文本消息与文件推送完整指南
java·机器人·企业微信
狂奔小菜鸡6 小时前
Day30 | Java集合框架之Collections工具类
java·后端·java ee
Java天梯之路6 小时前
Spring Boot 钩子全集实战(二):`SpringApplicationRunListener.starting()` 详解
java·spring·面试
忘带键盘了6 小时前
eclipse配置
java·ide·eclipse
Aevget6 小时前
知名Java开发工具IntelliJ IDEA v2025.3正式上线——开发效率全面提升
java·ide·人工智能·intellij-idea·开发工具