[JavaWeb] Filter&Listener study notes

table of Contents

Filter

Case code:

Life cycle:

Solve the full stack garbled:

Listener

Case code:


    In the actual development process, we need to filter certain access resources. When the request meets certain conditions, the request can access the target resource. If the condition is not met, the target resource cannot be accessed. For example: for the administrator To access the function, we should judge whether it is an administrator authority before requesting it.If the current user has an administrator authority, it can be accessed, and vice versa.

Filter

    Filter is a predefined interface in java, which can filter different content according to needs. The specific filtering content needs to define an implementation class yourself, and then implement the filtering method in the interface. When the client browser sends a request, the request is Before accessing the real target resource, perform a conditional filter, and then request the target resource, this process can be completed through the filter. 

    When we access a certain resource, if the accessed path exists, the filter will perform a release operation and execute the following servlet code normally. If the access path does not exist at this time, then the filter will not perform the release operation. When the console will output the content of the filter.

Case code:

Steps:

  1. Write a class that implements the javax.servlet.Filter interface
  2. Rewrite the filter method, note the dofilter method
  3. Configure filter in web.xml (function)
    1. Tell the servlet container that I am a filter
    2. Tell the filter container to perform filtering operations when accessing other resources.

web.xml code:

    <filter>
        <filter-name>HelloFilter</filter-name>
        <filter-class>com.james.filter.HelloFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HelloFilter</filter-name>
        <!--表示当前filter所拦截的路径设置-->
        <url-pattern>/demo2</url-pattern>
    </filter-mapping>

HelloFilter(Filter) code:

public class HelloFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /**
     * filter执行过滤 主要编写代码的方法 等效 Servlet中的service方法
     * 代码的逻辑 一行一行执行的
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("入门过滤器执行 A");
        //不放行就相当于 当前请求就结束了 直接响应回去

        //放行 进入原来的链接路径 相当 于调用方法 DemoServlet.doGet(request,response)
        //filterChain.doFilter(servletRequest , servletResponse) ;//放行代码

        System.out.println("入门过滤器执行 B");
    }

    @Override
    public void destroy() {

    }
}

servlet code:

public class DemoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doGet(request,response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo被访问了");
        response.getWriter().print("demo");
    }
}

Implementation process:

Life cycle:

void init(FilterConfig config): The initialization method, which will be executed when the project starts, only once

void doFilter(request,response,FilterChain chain) : Execute the filtering method, which will be executed when the request matches

void destroy(): Destroy, it will be executed when the project is removed or the server is shut down, and it will only be executed once

Servlet: By default, it is accessed for the first time and initialized every time the Servlet executes the service method, the server stops executing the destroy method

        Filter is a single-instance, thread-unsafe object (don't give member variables) 

        When the server starts, the server creates a filter object and calls the filter's init method to implement the initialization operation.

        When the request comes, if the filter can match this path, the server will get a thread from the thread pool, call the doFilter method of the filter in the thread, and reach the next place when the doFilter method performs the release operation.

        When the thread is closed normally, the server will call the filter's destroy method to achieve the destruction operation

Note: A path can only be executed by one servlet, but a path can be executed by multiple filters, and there is no path priority issue in the filter

Solve the full stack garbled:

     The first operation of each servlet is processing and response encoding, and when the browser sends any request, we can also process Chinese garbled codes through the filter.  

     In Tomcat8.5, the Chinese garbled code of the get request was processed, but the post was not processed. For the post request, our previous operation was through request.setCharacterEncoding("utf-8"); and each servlet must write a sentence of this code, Very troublesome, we can write only once through the filter and it is effective for multiple servlets.

Code steps:

  1. Write a filter
  2. The path to configure the filter is /*
  3. Write the request logic of the filter
package com.james.web.filter;

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

@WebFilter(filterName = "EncodingFilter" , urlPatterns = "/*")
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //全站编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //放行
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

Listener

    In our java program, we need to supervise the execution of certain things.Once the monitored object changes accordingly, we need to take corresponding actions.

    There are three more domain objects in JavaWeb:

ServletRequest        HTTPSession     ServletContext

    Today, I will make a small summary of ServletContextLister:

There are 8 listeners:

  1. Monitoring the creation and destruction of domain objects
    1. ServletRequestListener
    2. HttpSessionListener
    3. ServletContextListener
  2. Attribute operations of monitoring domain object pairs
    1. ServletRequestAttributeListener
    2. HttpSessionAttributeListener
    3. ServletContextAttributeListener
  3. Monitor special processing of special JavaBean in session
    1. HttpSessionBingdingListener
    2. HttpSessionActivationListener

The main concept of the listener:

    Event source: the object on which the event occurred

    Event: what happened

    Listener: An interface that needs to be implemented by ourselves.

Case code:

Step analysis of examples of counting online people:

1. Write a listener and implement HttpSessionListener

2. Operations after session creation

  • Get the servletContext object
  • Get the number of people online
    • If the number of people is null, set the number of people to 1
    • If the number of people is not null, set the number of people +1\

3. Operations after session destruction

  • Get the servletContext object
  • Get online number
    • Put the number of people in the servletContext field

4. Create a servlet for testing.

listener

package com.james.web.listener;

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 登录成功 或者 退出登录 其实操作的是 session的创建和销毁
 * 监听session的创建和销毁即可
 */
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
    /**
     * 数量+1
     * httpSessionEvent 事件对象
     */
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {

        HttpSession session = httpSessionEvent.getSession();
        System.out.println(session.getId()+",第一次被创建,放入servletContext中");
        //获得全局的域对象
        ServletContext sc = session.getServletContext();

        //先获得原来的登录数量
        Integer count = (Integer)sc.getAttribute("count");
        //以前一定登录过
        if(count != null && count !=0 ){ // 先判断非空 再判断值
            count++;
        }else{
            count=1; //以前没有登录过
        }
        sc.setAttribute("count" , count);
    }

    /**
     * 数量-1
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        //获得session
        HttpSession session = httpSessionEvent.getSession();
        System.out.println(session.getId() +" : 即将销毁 , 退出登录");
        //获得servletContext
        ServletContext servletContext = session.getServletContext();

        Integer count = (Integer)servletContext.getAttribute("count");
        //表示当前一定有人正在登录状态
        if(count != null && count >0 ){
            count -- ;
        }else{
            count= 0 ;
        }
        servletContext.setAttribute("count" , count);
    }
}

login

package com.james.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "LoginServlet" , urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("登陆成功:" +request.getSession().getId());
    }
}

logout

package com.james.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "LoginOutServlet" , urlPatterns = "/loginOut")
public class LoginOutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("退出了session:" + request.getSession().getId());
        //销毁session
        request.getSession().invalidate();
    }
}

showCount:

package com.james.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ShowLogin" , urlPatterns = "/showLogin")
public class ShowLogin extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print("当前人数为:" + getServletContext().getAttribute("count"));
    }
}

page:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <a href="${pageContext.request.contextPath}/login">点我登录服务器-不需要做登录案例</a><br/>
    <a href="${pageContext.request.contextPath}/loginOut">点我退出登录</a><br/>
    <a href="${pageContext.request.contextPath}/showLogin">点我查看登录成功服务器人数</a>
    当前登录人数为: ${count}<br/>
  <%--jsp的底层有九大内置对象 默认自己调用request.getSession();--%>
  </body>
</html>

   Through session creation (request.getsession()) destruction (request.getSession().invalidate();), the method in the monitor is called to change the number of sessions. Finally, it can be displayed on the page.

Guess you like

Origin blog.csdn.net/weixin_43267344/article/details/108721334