JavaWeb 开发 05 —— 过滤器、监听器

系列文章

JavaWeb 开发 01 —— 基本概念、Web服务器、HTTP、Maven

JavaWeb 开发 02 —— ServletContext、读取资源、下载文件、重定向和请求转发

JavaWeb 开发 03 —— Cookie 和 Session

JavaWeb 开发 04 —— JSP(原理、语法、指令、内置对象、JSP标签、JSTP标签)、JavaBean、MVC

JavaWeb 开发 05 —— 过滤器、监听器

JavaWeb 开发 06 —— smbms项目实践



10、过滤器

过滤器用于过滤网站的数据,处理中文乱码、登录验证…

在这里插入图片描述

Filter 实现中文乱码解决

Filter开发步骤:

  1. 导包

    复制下面的,也可以去仓库找 https://mvnrepository.com/

    <!-- Servlet依赖 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- JSP依赖 -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- JSTL表达式依赖 -->
    <dependency>
        <groupId>javax.servlet</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.47</version>
    </dependency>
    
  2. 新建一个类,实现过滤器接口。(注意是Servlet包下的Filter接口)

  3. 编写代码,重写方法。这里通过过滤器解决中文乱码问题!当我们访问Servlet时,如果没有处理(设置编码为UTF-8)就会出现乱码,但每一个Servlet都处理一次比较麻烦,所以可以在过滤器中预先处理,使每一个请求Servlet前,先经过过滤器处理好乱码。

CharacterEncodingFilter.java

package com.zcy.filter;

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

//过滤器可以有多个
public class CharacterEncodingFilter implements Filter {

    //初始化:Tomcat服务器启动时调用
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        System.out.println("过滤器初始化!");
    }

    @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("-------过滤器执行后--------");
    }

    //销毁:Tomcat服务器关闭时调用
    @Override
    public void destroy() {
        System.out.println("过滤器销毁!");
    }
}

FilterServlet.java

public class FilterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("这一段如果没有过滤,将会是乱码");
    }
}

  1. 编写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_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>FilterServlet</servlet-name>
        <servlet-class>com.zcy.servlet.FilterServlet</servlet-class>
    </servlet>
    <!-- 同一个Servlet映射两个位置 -->
    <servlet-mapping>
        <servlet-name>FilterServlet</servlet-name>
        <url-pattern>/filter</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>FilterServlet</servlet-name>
        <url-pattern>/servlet/filter</url-pattern>
    </servlet-mapping>
    
    <!-- 过滤器只过滤/servlet包下的Servlet    -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.zcy.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
</web-app>

没有过滤:

在这里插入图片描述

过滤后:

在这里插入图片描述

Filter 实现权限拦截

描述:只有用户成功登录后,才能进入主页。登录过一次,可以直接将主页URL放入浏览器打开。一旦注销,用户再输入主页URL是无法进入主页的。

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

  2. 跳转到主页的时候过滤器先判断用户是否已经登录,若没有登录则跳转到错误页面,若已经登录,则跳转到主页。

    注意:login.jsp是在webapp的login目录下;

    ​ error.jsp是在webapp的error目录下;

    ​ success.jsp是在webapp的sys目录下;

    ​ LoginServlet2.java和LogoutServlet2.java是在java的com.zcy.servlet目录下; LoginFilter.java是在java的com.zcy.filter目录下。

    login.jsp 登录界面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登录界面</title>
    </head>
    <body>
    <h1>登录界面</h1>
    <form action="/myWeb/login" method="post">
        <input type="text" name="username"/><input type="submit" value="提交"/>
    </form>
    </body>
    </html>
    

    success.jsp 成功登录后的主页

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>登录成功!</h1>
    <h2>这是主页</h2>
    <h3><a href="/myWeb/logout">注销,并返回登录界面</a><h3>
    </body>
    </html>
    

    error.jsp 登录失败的错误页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>登录失败</h1>
    <h2>权限不够或者密码错误...</h2>
    <h3><a href="/myWeb/login/login.jsp">返回登录界面</a></h3>
    </body>
    </html>
    

    LoginServlet2.java

    package com.zcy.servlet;
    
    import com.zcy.util.Constant;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LoginServlet2 extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String userName = req.getParameter("username");
            if (userName.equals("admin")){
                //登录成功,将数据放到Session中,随便放什么,这里放Session ID
                req.getSession().setAttribute(Constant.USER_SESSION, req.getSession().getId());
    
                //成功则重定向到成功页面,这里因为将数据放到session中,所以其他页面也能用该数据
                resp.sendRedirect("/myWeb/sys/success.jsp");
            }
            else
                resp.sendRedirect("/myWeb/error/error.jsp");//失败则跳转到失败页面
        }
    }
    

    LogoutServlet2.java

    package com.zcy.servlet;
    
    import com.zcy.util.Constant;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LogoutServlet2 extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //移除Session中的数据,也可以直接手动销毁session(但后面session再自动创建会浪费资源)
            //只有已经登录了才能注销
            if (req.getSession().getAttribute(Constant.USER_SESSION) != null)
                req.getSession().removeAttribute(Constant.USER_SESSION);
            //注销后,最终都会回到登陆界面
            resp.sendRedirect("/myWeb/logi/login.jsp");
    
        }
    }
    
    

    LoginFilter.java

    package com.zcy.filter;
    
    import com.zcy.util.Constant;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LoginFilter implements Filter {
        @Override
        public void doFilter(
                ServletRequest request, ServletResponse response, FilterChain chain
                            ) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse)response;
    
            if (req.getSession().getAttribute(Constant.USER_SESSION) == null)
                resp.sendRedirect("/myWeb/error/error.jsp");
            chain.doFilter(request, response);
        }
    }
    
    

    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_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>LoginServlet2</servlet-name>
            <servlet-class>com.zcy.servlet.LoginServlet2</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LoginServlet2</servlet-name>
            <url-pattern>/login</url-pattern>
        </servlet-mapping>
    
        <servlet>
            <servlet-name>LogoutServlet2</servlet-name>
            <servlet-class>com.zcy.servlet.LogoutServlet2</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LogoutServlet2</servlet-name>
            <url-pattern>/logout</url-pattern>
        </servlet-mapping>
    
        <!-- 过滤:访问sys目录下的所有文件都需要先访问LoginFilter.java  -->
        <filter>
            <filter-name>LoginFilter</filter-name>
            <filter-class>com.zcy.filter.LoginFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>LoginFilter</filter-name>
            <url-pattern>/sys/*</url-pattern>
        </filter-mapping>
    
    </web-app>
    
    

结果:

1613633129164 1613633199631 1613633243110

11、监听器

监听器有很多,它们使用方法都相同。这里举个例子,统计网站在线人数。

OnlineCountListener.java

package com.zcy.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 通过监听Session,统计网站在线人数
 * 一个session代表一个用户,tomcat启动项目时默认会有三个session,重新发布tomcat后清零。
 * session销毁两种方式:1. 手动:se.getSession().invalidate(); 
 *                     2.自动 去web.xml配置session-config和session-timeout
 */
public class OnlineCountListener implements HttpSessionListener {

    //创建一个session时会调用该方法,创建session即一个浏览器打开网页。一个浏览器只能代表一个session
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        //ServletContext代表Servlet上下文,也就是JSP中的application对象,作用域是整个服务器
        ServletContext servletContext = se.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("onLineCount");
        
        //之前没人则人数为1(当前一个用户),有人则人数加一
        if (onlineCount == null)
            onlineCount = new Integer(1);
        else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }
        //更新人数
        servletContext.setAttribute("onLineCount", onlineCount);
    }

    //销毁一个session时会调用该方法,
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        //ServletContext代表Servlet上下文,也就是JSP中的application对象,作用域是整个服务器
        ServletContext servletContext = se.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("onLineCount");

        if (onlineCount == null)
            onlineCount = new Integer(0);
        else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }
        //更新人数
        servletContext.setAttribute("onLineCount", onlineCount);
    }
}

linsten.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>当前在线人数:<%=this.getServletConfig().getServletContext().getAttribute("onLineCount")%></h1>
</body>
</html>

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_4_0.xsd"
         version="4.0">
	<!-- 注册监听器 -->
    <listener>
        <listener-class>com.zcy.listener.OnlineCountListener</listener-class>
    </listener>
</web-app>

结果:启动项目后,先重新发布,因为tomcat本身会有一个session。

在这里插入图片描述

一个浏览器即便打开多个网页也只算一个用户,因为session是按浏览器创建的。

在这里插入图片描述

用IE再进入这个网页,人数显示2,关闭IE后刷新谷歌浏览器,人数保持是2,因为session即便浏览器关闭也不会被销毁。

在这里插入图片描述
在这里插入图片描述

12、JDBC

详细可看我另一篇博客:数据库 —— Java操作MySQL

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

老板来碗小面加蛋~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值