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>
相关推荐
李慕婉学姐29 分钟前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆2 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin2 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20052 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉3 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国3 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882483 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈4 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_994 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹4 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理