chengyuyu

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  10 随笔 :: 0 文章 :: 0 评论 :: 1070 阅读

3. Filter

3.1 过滤器

参考资料:Java中的Filter过滤器 - 菜鸟-传奇 - 博客园 (cnblogs.com)

过滤器开发(2步):

  1. 编写java类实现Filter接口,并实现其doFilter方法。
  2. 在web.xml文件中对编写的filter类进行注册,并设置它所能拦截的资源。

过滤器的生命周期:

public void init(FilterConfig filterConfig) throws ServletException;//初始化
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。

public void destroy();//销毁
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

3.2 实例

页面中文字符编码的过滤器(防止中文乱码)

文件结构

image-20220205200653865

依赖包配置(pom.xml)

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
    <!--JSTL表达式的依赖-->
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
    <dependency>
        <groupId>javax.servlet.jsp.jstl</groupId>
        <artifactId>jstl-api</artifactId>
        <version>1.2</version>
    </dependency>
    <!--standard标签库-->
    <!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
    <dependency>
        <groupId>org.apache.taglibs</groupId>
        <artifactId>taglibs-standard-impl</artifactId>
        <version>1.2.5</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

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>ServletDemo01</servlet-name>
        <servlet-class>com.mystudy.servlet.ServletDemo01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletDemo01</servlet-name>
        <url-pattern>/servlet/d1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ServletDemo01</servlet-name>
        <url-pattern>/d1</url-pattern>
    </servlet-mapping>

    <!--过滤器配置-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.mystudy.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
</web-app>

过滤器:CharacterEncodingFilter.java

注意:filterChain.doFilter(servletRequest,servletResponse);

public class CharacterEncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletResponse.setContentType("text/html;charset=UTF-8");
        servletResponse.setCharacterEncoding("UTF-8");
        servletRequest.setCharacterEncoding("UTF-8");
        
        System.out.println("CharacterEncodingFilter执行前...");
        filterChain.doFilter(servletRequest,servletResponse); //如果不写,程序到此处将会被拦截停止
        System.out.println("CharacterEncodingFilter执行后...");
    }

    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}

应用:ServletDemo01.java

public class ServletDemo01 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 {

    }
}

4. Listen监听

监听器:GUI编程中经常使用

实例

统计在线人数

web.xml

<!--监听配置-->
<listener>
    <listener-class>com.mystudy.listen.SessionCountListen</listener-class>
</listener>

SessionCountListen.java

public class SessionCountListen implements HttpSessionListener {

    //session创建
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession().getServletContext();
        Integer onlienCount = (Integer) ctx.getAttribute("OnlienCount");
        if (onlienCount==null){
            onlienCount = new Integer(1);
        }else {
            int count = onlienCount.intValue();
            onlienCount = new Integer(count+1);
        }
        ctx.setAttribute("OnlienCount",onlienCount);
    }

    //session销毁
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession().getServletContext();
        Integer onlienCount = (Integer) ctx.getAttribute("OnlienCount");
        if (onlienCount==null){
            onlienCount = new Integer(0);
        }else {
            int count = onlienCount.intValue();
            onlienCount = new Integer(count-1);
        }
        ctx.setAttribute("OnlienCount",onlienCount);

    }
}

index.jsp

前端显示servlet值的两种方法:

  • <%=xxx.xxx.xxx.getAttribute("参数名")%>
  • el表达式:$
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <h1>当前有: <span>
    ${applicationScope.OnlienCount}
  </span> 人在线</h1>
  <hr>
  <h1>当前有: <span>
    <%=this.getServletConfig().getServletContext().getAttribute("OnlienCount")%>
  </span> 人在线</h1>
  </body>
</html>

5. 过滤、监听的常见应用

filter实现权限拦截:用户登录之后才能进入主页,用户注销后就不能进入主页了。

  1. 用户登录后,向Session放入用户的数据;
  2. 进入主页时需判断用户是否已经登录;要求:在过滤器中实现。(若直接通过地址栏进入主页,需要经过Filter判断是否登录)

5.1 实例

将session存在一个常量里:

Constant.java

public class Constant {
    public static String USER_SESSION = "USER_SESSION";
}

文件结构

image-20220207172747317

登录:ServletLogin.java

如果登陆成功,往session放一个信息,并且跳转到成功页面

public class ServletLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        if ("admin".equals(username)){// 登陆成功
            // 如果登陆成功,往session放一个信息,并且跳转到成功页面
            req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
            resp.sendRedirect("/sys/success.jsp");
        }else {// 登陆失败
            resp.sendRedirect("/error.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

登录页:login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
</head>
<body>
<form action="/servlet/login" method="post">
    用户名: <input type="text" name="username">
    <input type="submit" value="登录">
</form>
</body>
</html>

action="/servlet/login"需要和web.xml里注册的一致

登录失败页:error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆失败</title>
</head>
<body>
<h1>登陆失败</h1>
<h2>无权限或用户名错误</h2>
<p><a href="login.jsp">返回登录页面</a> </p>
</body>
</html>

注销:ServletLogout.java

注销页

public class ServletLogout extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 注销登录:判断session是否存在,若存在则移除,并重定向到登录页面
        Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
        if (user_session!=null){
            req.getSession().removeAttribute(Constant.USER_SESSION); // 移除该session
            resp.sendRedirect("/login.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

过滤器:SysFilter.java

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // ServletRequest  -->  HttpServletRequest
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 获取Session,如果为空,则跳转到未登录(登陆错误)页
        if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
            response.sendRedirect("/error.jsp");
        }
        filterChain.doFilter(request,response);
    }
    public void destroy() {
    }
}

web.xml

<servlet>
    <servlet-name>ServletLogin</servlet-name>
    <servlet-class>com.mystudy.servlet.ServletLogin</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ServletLogin</servlet-name>
    <url-pattern>/servlet/login</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>ServletLogout</servlet-name>
    <servlet-class>com.mystudy.servlet.ServletLogout</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ServletLogout</servlet-name>
    <url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>

<!--过滤器配置-->
<filter>
    <filter-name>SysFilter</filter-name>
    <filter-class>com.mystudy.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SysFilter</filter-name>
    <url-pattern>/sys/*</url-pattern>
</filter-mapping>
posted on   chengyuyu  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示