Uso de javaWeb-8-Filter + ThreadLocal

índice

1. O que é o Filter-API Complete Works

2. Primeira experiência de filtro

2.1 Requisitos para a experiência inicial de Filtro

2.2 Estrutura do projeto

2.2.1 Colocar os recursos a serem acessados ​​no diretório web do projeto

2.2.2 Escreva um filtro Filtro: AdminFilter implementar Filtro

2.2.3 Escreva um Servlet de processador de recurso dinâmico para os usuários processarem o login: LoginServlet extends HttpServlet

2.2.4 Configurar o caminho de interceptação do filtro e o caminho de acesso do servlet no arquivo web.xml

2.2.5 Página inicial: a.html

2.2.6 Página de front-end: a.jsp

2.2.7 Página de login front-end: login.jsp

2.2.8 O front end inicia uma solicitação de teste

2.3 Passos para usar o filtro FIlter

3. O ciclo de vida do filtro

4. Trabalhos completos da API de classe FilterConfig

5. Cadeia de filtros FilterChain

5.1 O conjunto completo de APIs da interface FilterChain

5.2 Explicação detalhada dos métodos da interface FilterChain

5.3 Se houver vários filtros no projeto web, o fluxo de execução entre eles é o seguinte: importante

5.4 Se houver vários filtros em um projeto web: estrutura de projeto de demonstração de código

5.4.1 Gravar filtro de filtro: Filtro1 e Filtro2

5.4.2 Recurso de solicitação de gravação interceptado pelo filtro FIlter: target.jsp

5.4.3 Configurar o caminho de interceptação do filtro FIlter no arquivo web.xml

5.4.4 A página front-end inicia uma solicitação de teste e vê o resultado

6. Caminho de interceptação do filtro: correspondência exata de diretório de correspondência de nome de sufixo

7. Uso de ThreadLocal

7.1 Introdução à API oficial do ThreadLocal

7.2 Breve introdução do ThreadLocal

7.3 Uma breve introdução ao ThreadLocal: primeiro use Hashtable para demonstração

7.3.1 ThreadLocalTest 类

7.3.2 Classe OrderService

7.3.3 Classe OrderDao

7.3.4 Resultados da demonstração

7.4 Uma breve introdução ao ThreadLocal: use ThreadLocal para demonstrar

7.4.1 ThreadLocalTest2 类

7.4.2 Classe OrderService2

7.4.3 Classe OrderDao2

7.4.4 Resultados de demonstração

1. O que é o Filter-API Complete Works

(1) O filtro é um dos três componentes básicos do JavaWeb: Filtro, processador dinâmico de servlet, ouvinte.

(2) O filtro é uma especificação do JavaEE, que é uma interface.

(3) A função do Filtro: interceptar solicitações ; filtrar respostas.

(4) Os cenários de aplicação comuns para interceptar solicitações são: verificação de permissão, operação de log, gerenciamento de transação ... 

2. Primeira experiência de filtro

2.1 Requisitos para a experiência inicial de Filtro

Requisitos: Existe um diretório de administração em seu projeto web. Todos os recursos (páginas html, imagens jpg, arquivos jsp, etc.) neste diretório devem ser acessados ​​após o login do usuário.

Pensando: De acordo com o que aprendemos antes, sabemos que após o login do usuário, as informações de login do usuário serão salvas no domínio da Sessão.

Portanto : Para verificar se o usuário está conectado, você só precisa determinar se os dados do domínio da sessão contêm as informações de login do usuário.

2.2 Estrutura do projeto

2.2.1 Colocar os recursos a serem acessados ​​no diretório web do projeto

2.2.2 Escreva um filtro Filtro: AdminFilter implementar Filtro

package com.wind.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @Description: 写一个过滤器
 */
public class AdminFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("AdminFilter init...");
    }

    /**
     * doFilter()方法专门用于拦截请求,拦截请求之后,可以对这个请求做一些额外的操作,比如权限检查等。
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        if (session != null) {
            Object user = session.getAttribute("username");
            if (user == null) {
                //如果等于null,表示用户还没有登录,需要给用户跳转到登录页面,注意这里是转发
                servletRequest.getRequestDispatcher("/admin/login.jsp").forward(servletRequest, servletResponse);
            } else {
                //如果不等于null,则表示用户已经登录了,可以让用户继续往下往下走流程,访问用户的目标资源
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    }

    @Override
    public void destroy() {
        System.out.println("AdminFilter destroy...");
    }
}

2.2.3 Escreva um Servlet de processador de recurso dinâmico para os usuários processarem o login: LoginServlet extends HttpServlet

package com.wind.servlet;

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

/**
功能:用于处理登录的servlet处理器
 */
public class LoginServlet extends HttpServlet {

    private static final long serialVersionUID = 2655616816599866422L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if ("abc".equals(username) && "123".equals(password)) {
            req.getSession().setAttribute("username", username);
            resp.getWriter().write("登录成功");
        } else {
            req.getRequestDispatcher("/admin/login.jsp").forward(req, resp);
        }
    }
}

2.2.4 Configurar o caminho de interceptação do filtro e o caminho de acesso do servlet no arquivo 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">

    <!--给AdminFilter过滤器配置拦截路径-->
    <!--filter标签:用于配置一个过滤器filter-->
    <filter>
        <!--filter-name标签:给filter起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--filter-class标签:配置filter的全类名-->
        <filter-class>com.wind.filter.AdminFilter</filter-class>
    </filter>

    <!--filter-mapping标签:配置过滤器filter的拦截路径-->
    <filter-mapping>
        <!--filter-name标签:表示当前的拦截路径给哪个filter使用-->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern标签:配置拦截路径-->
        <!--
            /  斜杠:表示请求地址是:http://ip:port/工程路径/,映射到IDEA的"web"目录
            /admin/*:表示请求地址是:http://ip:port/工程路径/admin/*
        -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.wind.servlet.LoginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>

</web-app>

2.2.5 Página inicial: a.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<b>我是a.html文件</b>
</body>
</html>

2.2.6 Página de front-end: a.jsp

<%--
  Created by IntelliJ IDEA.
  User: cmm
  Date: 2020/12/24
  Time: 17:42
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<b>我是a.jsp文件</b>
<%
    System.out.println("a.jsp页面执行了");
    Object user = session.getAttribute("user");
    //如果等于null,则说明还没有登录,于是,服务器端转发到登录页面
    if (user == null) {
        request.getRequestDispatcher("/admin/login.jsp").forward(request, response);
        return;
    }
%>
</body>
</html>

2.2.7 Página de login front-end: login.jsp

<%--
  Created by IntelliJ IDEA.
  User: cmm
  Date: 2020/12/24
  Time: 18:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<b>这是登录页面,login.jsp</b><br>
<form action="http://localhost:8080/15_filter/loginServlet" method="get">
    用户名:<input type="text" name="username"/><br>
    密 码:<input type="password" name="password"/><br>
    <input type="submit" name="登录"/><br>
</form>
</body>
</html>

2.2.8 O front end inicia uma solicitação de teste

(1) Enquanto a solicitação HTTP acessar os recursos do diretório admin, ela será interceptada pelo filtro AdminFilter e encaminhada para a página de login.

(2) Na página de login, se você inserir o nome de usuário e a senha incorretos, ele ainda será bloqueado pelo filtro AdminFilter. No filtro AdminFilter, é avaliado se o nome de usuário e a senha estão corretos. Se for considerado incorreto, ainda será encaminhado para a página de login.

(3) Na página de login, digite o nome de usuário e a senha corretos; ele ainda será bloqueado pelo filtro AdminFilter. No filtro AdminFilter, determine se o nome de usuário e a senha estão corretos e, se forem considerados corretos, exiba "Login bem-sucedido".

(4) Neste momento, quando houver outra solicitação de HTTP para acessar recursos no diretório admin, embora seja interceptada pelo filtro AdminFilter, o nome do usuário e a senha passaram na verificação, então ela continuará a executar, ou seja, para obter o usuário deseja Recursos acessados.

2.3 Passos para usar o filtro FIlter

3. O ciclo de vida do filtro

O ciclo de vida do Filtro inclui estes métodos:

(1) Método do construtor. (2) método de inicialização init ().

          A primeira e a segunda etapas são executadas quando o projeto da web é iniciado (o Filtro será criado neste momento).

(3) método de filtragem doFilter.

          A terceira etapa é executar sempre que uma solicitação for interceptada.

(4) método destroy () destroy.

          A quarta etapa será executada quando o projeto da web for interrompido (interromper o projeto da web também destruirá o Filtro).

4. Trabalhos completos da API de classe FilterConfig

5. Cadeia de filtros FilterChain

5.1 O conjunto completo de APIs da interface FilterChain

5.2 Explicação detalhada dos métodos da interface FilterChain

5.3 Se houver vários filtros no projeto web, o fluxo de execução entre eles é o seguinte: importante

5.4 Se houver vários filtros em um projeto web: estrutura de projeto de demonstração de código

5.4.1 Gravar filtro de filtro: Filtro1 e Filtro2

package com.wind.filter;

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

/**
Filter1
 */
public class Filter1 implements Filter {

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter1 前置业务执行");
        System.out.println("Filter1 线程的后置=" + Thread.currentThread().getName());
        //在filter1中设置一个值
        servletRequest.setAttribute("key1", "value1");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("Filter1 线程的后置=" + Thread.currentThread().getName());
        System.out.println("Filter1 后置业务执行");
    }

    @Override
    public void destroy() {

    }
}
package com.wind.filter;

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

/**
Filter2
 */
public class Filter2 implements Filter {

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter2 前置业务执行");
        System.out.println("Filter2 线程的前置=" + Thread.currentThread().getName());
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("Filter2 线程的后置=" + Thread.currentThread().getName());
        System.out.println("Filter2 后置业务执行");
        //在filter2中可以获取在filter1中设置的那个值
        System.out.println("在filter2中获取在filter1中设置的key1对应的value=" + servletRequest.getAttribute("key1"));
    }

    @Override
    public void destroy() {

    }
}

5.4.2 Recurso de solicitação de gravação interceptado pelo filtro FIlter: target.jsp

<%--
  Created by IntelliJ IDEA.
  Date: 2020/12/24
  Time: 22:59
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    System.out.println("target.jsp 业务执行");
    System.out.println("target.jsp 线程=" + Thread.currentThread().getName());
%>
</body>
</html>

5.4.3 Configurar o caminho de interceptação do filtro FIlter no arquivo 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">

    <!--给AdminFilter过滤器配置拦截路径-->
    <!--filter标签:用于配置一个过滤器filter-->
    <filter>
        <!--filter-name标签:给filter起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--filter-class标签:配置filter的全类名-->
        <filter-class>com.wind.filter.AdminFilter</filter-class>
        <init-param>
            <param-name>user</param-name>
            <param-value>root</param-value>
        </init-param>
    </filter>

    <!--filter-mapping标签:配置过滤器filter的拦截路径-->
    <filter-mapping>
        <!--filter-name标签:表示当前的拦截路径给哪个filter使用-->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern标签:配置拦截路径-->
        <!--
            /  斜杠:表示请求地址是:http://ip:port/工程路径/,映射到IDEA的"web"目录
            /admin/*:表示请求地址是:http://ip:port/工程路径/admin/*
        -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>Filter1</filter-name>
        <filter-class>com.wind.filter.Filter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter1</filter-name>
        <url-pattern>/admin/target.jsp</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>Filter2</filter-name>
        <filter-class>com.wind.filter.Filter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter2</filter-name>
        <url-pattern>/admin/target.jsp</url-pattern>
    </filter-mapping>


    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.wind.servlet.LoginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>

</web-app>

5.4.4 A página front-end inicia uma solicitação de teste e vê o resultado

6. Caminho de interceptação do filtro: correspondência exata de diretório de correspondência de nome de sufixo

7. Uso de ThreadLocal

7.1 Introdução à API oficial do ThreadLocal

 

7.2 Breve introdução do ThreadLocal

7.3 Uma breve introdução ao ThreadLocal: primeiro use Hashtable para demonstração

7.3.1 ThreadLocalTest 类

package com.wind.threadLocal;

import java.util.Hashtable;
import java.util.Map;
import java.util.Random;

/**
    public static Map<String, Object> date = new Hashtable<>();
 */
public class ThreadLocalTest {

    public static Map<String, Object> date = new Hashtable<>();

    private static Random random = new Random();

    public static class Task implements Runnable {
        @Override
        public void run() {
            //1.在run方法中随机生成一个变量,这个变量是线程需要关联的数据,然后以当前线程名作为key存储到map中
            //随机数是:0-999
            Integer integer = random.nextInt(1000);
            String name = Thread.currentThread().getName();
            System.out.println("线程[" + name + "]" + "生成的随机数是=" + integer);
            date.put(name, integer);

            try {
                Thread.sleep(2000);
                new OrderService().createOrder();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //2.在线程执行结束之前,以当前线程名作为key从map中取出数据,查看是否能够取出
            Object o = date.get(name);
            System.out.println("在线程[" + name + "]" + "在结束时数据的数据是=" + o);
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new Task()).start();
        }
    }
}

7.3.2 Classe OrderService

package com.wind.threadLocal;

import java.io.Serializable;
public class OrderService implements Serializable {

    private static final long serialVersionUID = -6969950483259564262L;

    public void createOrder() {
        String name = Thread.currentThread().getName();
        System.out.println("OrderService 当前线程[" + name + "]" + "中保存的数据是=" + ThreadLocalTest.date.get(name));
        new OrderDao().saveOrder();
    }
}

7.3.3 Classe OrderDao

package com.wind.threadLocal;

import java.io.Serializable;
public class OrderDao implements Serializable {

    private static final long serialVersionUID = -6969950483259564262L;

    public void saveOrder() {
        String name = Thread.currentThread().getName();
        System.out.println("OrderDao 当前线程[" + name + "]" + "中保存的数据是=" + ThreadLocalTest.date.get(name));
    }
}

7.3.4 Resultados da demonstração

7.4 Uma breve introdução ao ThreadLocal: use ThreadLocal para demonstrar

7.4.1 ThreadLocalTest2 类

package com.wind.threadLocal;

import java.util.Random;

/**
    public static ThreadLocal<Object> threadLocal = new ThreadLocal<>();
 */
public class ThreadLocalTest2 {

    public static ThreadLocal<Object> threadLocal = new ThreadLocal<>();

    private static Random random = new Random();

    public static class Task implements Runnable {
        @Override
        public void run() {
            //1.在run方法中随机生成一个变量,这个变量是线程需要关联的数据,然后以当前线程名作为key存储到map中
            //随机数是:0-999
            Integer integer = random.nextInt(1000);
            String name = Thread.currentThread().getName();
            System.out.println("线程[" + name + "]" + "生成的随机数是=" + integer);
            threadLocal.set(integer);

            try {
                Thread.sleep(2000);
                new OrderService2().createOrder2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //2.在线程执行结束之前,以当前线程名作为key从map中取出数据,查看是否能够取出
            Object o = threadLocal.get();
            System.out.println("在线程[" + name + "]" + "在结束时数据的数据是=" + o);
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new Task()).start();
        }
    }
}

7.4.2 Classe OrderService2

package com.wind.threadLocal;

import java.io.Serializable;

public class OrderService2 implements Serializable {

    private static final long serialVersionUID = -6969950483259564262L;

    public void createOrder2() {
        String name = Thread.currentThread().getName();
        System.out.println("OrderService2 当前线程[" + name + "]" + "中保存的数据是=" + ThreadLocalTest2.threadLocal.get());
        new OrderDao2().saveOrder2();
    }
}

7.4.3 Classe OrderDao2

package com.wind.threadLocal;

import java.io.Serializable;

public class OrderDao2 implements Serializable {

    private static final long serialVersionUID = -6969950483259564262L;

    public void saveOrder2() {
        String name = Thread.currentThread().getName();
        System.out.println("OrderDao2 当前线程[" + name + "]" + "中保存的数据是=" + ThreadLocalTest2.threadLocal.get());
    }
}

7.4.4 Resultados de demonstração

 

 

 

 

Acho que você gosta

Origin blog.csdn.net/cmm0401/article/details/111655999
Recomendado
Clasificación