JavaWeb (11. Tecnología conversacional)

11-Tecnología conversacional

El objetivo de hoy

  • Comprender qué es la tecnología de seguimiento de sesiones

  • Comprender el uso de cookies

  • Domina el uso de Session

  • Mejorar la función del caso de registro de inicio de sesión de usuario.

uno,Descripción general de la tecnología de seguimiento de sesiones

  Para 会话跟踪estas cuatro palabras, debemos desglosarlas para explicarlas. Primero debemos entender qué son 会话y luego entender qué son 会话跟踪:

  • Sesión :El usuario abre el navegador, accede a los recursos del servidor web y la sesión se establece hasta que una de las partes se desconecta y finaliza la sesión. Una sesión puede contener múltiples solicitudes y respuestas.

    • Después de que el navegador realiza una solicitud y el servidor responde con datos al front-end, se establece una sesión (entre el navegador y el servidor).
    • Una vez establecida la sesión, si no se cierra ni el navegador ni el servidor, se seguirá estableciendo la sesión.
    • El navegador y el servidor pueden continuar usando la sesión para enviar solicitudes y responder. Todo el proceso anterior se llamasesión

      Utilice escenarios reales para comprender la conversación. Por ejemplo, cuando visitamos JD.com, después de abrir el navegador e ingresar a la página de inicio de JD.com, se establece una sesión entre el navegador y el servidor de JD.com, luego buscamos productos, ver los detalles del producto y unirse al carrito de compras, etc., se completan en esta sesión.
      Pensando: ¿Cuántas sesiones se establecen en total en la imagen a continuación?
    Insertar descripción de la imagen aquí
    Cada navegador establecerá una sesión con el servidor y el total es3sesiones.

  • Seguimiento de sesiones :Un método para mantener el estado del navegador. El servidor necesita identificar si múltiples solicitudes provienen del mismo navegador para poder compartir datos entre múltiples solicitudes en la misma sesión.

    • El servidor recibirá múltiples solicitudes, que pueden provenir de múltiples navegadores. Por ejemplo, las 6 solicitudes en la imagen de arriba provienen de 3 navegadores.

    • El servidor necesita identificar si la solicitud proviene del mismo navegador.

    • El proceso utilizado por el servidor para identificar el navegador, este proceso es el seguimiento de la sesión.

    • Después de que el servidor reconoce el navegador, puede compartir datos entre múltiples solicitudes en la misma sesión.

       Entonces tenemos otra pregunta en la que pensar. ¿Por qué varias solicitudes en una sesión necesitan compartir datos? Con esta función de intercambio de datos, podemos ¿Qué funciones? ¿son implementados?

    • Carrito de compras: 加入购物车y 去购物车结算son dos solicitudes, pero si desea mostrar los productos agregados en la solicitud anterior en esta solicitud posterior, debe utilizar el intercambio de datos.

    • La página muestra información de inicio de sesión del usuario: muchos sitios web acceden a múltiples funciones después de iniciar sesión. Después de enviar múltiples solicitudes, el navegadorHabrá información sobre el usuario actualmente conectado [nombre de usuario], como Baidu, JD.com, Code Cloud, etc.

    • Funciones de la página de inicio de sesión del sitio web 记住我: después de que el usuario inicia sesión exitosamente, 记住我el sitio web completará automáticamente el nombre de usuario y la contraseña la próxima vez que inicie sesión después de marcar el botón, lo que simplifica la operación de inicio de sesión del usuario. Múltiples inicios de sesión darán lugar a múltiples solicitudes. También implica compartir datos entre

    • La función del código de verificación de la página de inicio de sesión: genere el código de verificación e ingrese el código de verificación y haga clic para registrarse. Estas también son dos solicitudes. Los datos de las dos solicitudes deben compararse. Si son iguales, se permite el registro, si son diferentes, se deniega el registro.La implementación de esta función también requiere Compartir datos dentro de la misma sesión.

  A través de la explicación de estos ejemplos, creo que todos 会话追踪tienen una cierta comprensión de la tecnología, y esta tecnología también es muy importante en el desarrollo real. Luego, debemos aprender 会话跟踪las tecnologías a continuación. Antes de aprender estas tecnologías, debemos pensar: ¿Por qué los navegadores y servidores no admiten el intercambio de datos ahora?

  • Las solicitudes HTTP se utilizan para la transmisión de datos entre el navegador y el servidor.
  • El protocolo HTTP essin Estado, cada vez que el navegador solicita al servidor, el servidor tratará la solicitud comonuevopreguntar
  • El protocolo HTTP está diseñado para no tener estado, de modo que cada solicitud sea independiente entre sí y no se afecte entre sí.
  • Una vez que las solicitudes son independientes, no se puede compartir datos entre múltiples solicitudes.

Después de analizar las razones específicas, ¿cómo implementar la tecnología de seguimiento de sesiones? Los métodos de implementación específicos son:
(1) Tecnología de seguimiento de sesiones del cliente:Cookie
(2) Tecnología de seguimiento de sesiones del lado del servidor:Session
  Ambas tecnologías pueden lograr el seguimiento de sesiones y la mayor diferencia entre ellas es:Las cookies se almacenan en el lado del navegador y las sesiones se almacenan en el lado del servidor.

Las ideas de aprendizaje específicas son:

  • CooKieUso básico, principios, detalles de uso.
  • SessionUso básico, principios, detalles de uso.
  • CookieSessionCasos integrales de y

1. Resumen

En esta sección, presentamos principalmente lo que essesiónytecnología de seguimiento de sesionesLo que hay que tener en cuenta es:

  • El protocolo HTTP no tiene estado y no se puede lograr el seguimiento de la sesión confiando en el protocolo HTTP.
  • Si desea implementar el seguimiento de sesiones, debe utilizar Cookie y Sesión

Cómo utilizar esta Cookie y Sesión específicamente, comencemos con la Cookie.

dos,Galleta

Para aprender Cookie, solucionamos principalmente los siguientes problemas:

  • ¿Qué son las galletas?
  • ¿Cómo se utilizan las cookies?
  • ¿Cómo se implementan las cookies?
  • ¿Cuáles son las precauciones al utilizar cookies?

1 、Uso básico de cookies

① Concepto

Galleta: La tecnología de sesión del cliente guarda datos para el cliente y cada solicitud posterior lleva datos de cookies para el acceso.
②.Flujo de trabajo de cookies
Insertar descripción de la imagen aquí

  • El servidor proporciona dos Servlets, a saber, ServletA y ServletB.
  • El navegador envía la solicitud HTTP 1 al servidor y el servidor ServletA recibe la solicitud y realiza el procesamiento comercial.
  • El ServletA del lado del servidor puede crear un objeto Cookie durante el procesamiento y name=zsalmacenar los datos en la Cookie.
  • Cuando el ServletA del lado del servidor responde a los datos, responderá al navegador con el objeto Cookie.
  • Cuando el navegador recibe los datos de respuesta, almacenará los datos en el objeto Cookie en la memoria del navegador. En este momento, el navegador y el servidorSe estableció una sesión
  • en la misma sesiónEl navegador envía nuevamente la solicitud HTTP 2 al servidor ServletB y el navegador transportará todos los datos en el objeto Cookie.
  • Después de que ServletB recibe la solicitud y los datos, puede obtener los datos almacenados en el objeto Cookie, de modo que los datos se puedan compartir entre múltiples solicitudes en la misma sesión.

③.Uso básico de
  cookies. Para el uso de cookies, debemos prestar más atención a cómo opera el código de fondo de las cookies. Las operaciones de las cookies se dividen principalmente en dos categorías. Esta esEnviar galletayObtener galleta¿Cómo implementar los dos contenidos anteriores respectivamente?

1.1 Enviar cookie

  • Crear objeto Cookie y establecer datos
Cookie cookie = new Cookie("key","value");
  • Enviar cookie al cliente: utilizarrespuestaobjeto
response.addCookie(cookie);

Luego de presentar los pasos correspondientes al envío de Cookies, usemos un caso para completar el envío de Cookies, los pasos de implementación específicos son:

Requisitos: generar objetos Cookie y almacenar datos en Servlet, y luego enviar los datos al navegador
(1), crear un proyecto Maven, el nombre del proyecto es cookie-demo y agregar dependencias en pom.xml
(2), escribir un Servlet. clase, el nombre es AServlet
(3). Cree un objeto Cookie en el AServlet, almacene los datos y envíelos al front-end
(4). Inicie la prueba y vea el valor en el objeto Cookie en el navegador.

(1) Cree una demostración de cookies del proyecto Maven y agregue dependencias en pom.xml

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
    <!--servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!--jsp-->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
    <!--jstl-->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>
</dependencies>

(2) Escriba una clase de servlet llamadaAServlet
(3) Cree un objeto Cookie en el Servlet, almacene los datos y envíelos al front-end

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //发送Cookie
        //1. 创建Cookie对象
        Cookie cookie = new Cookie("username","zs");
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(4) Inicie la prueba y vea el valor en el objeto Cookie en el navegador
Hay dos formas de acceder http://localhost:8080/cookie-demo/aServlet
al navegador Chrome para ver el valor de la cookie:

Método 1:
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Método 2 : seleccione para abrir las herramientas de desarrollador o use la tecla de método abreviado F12 o Ctrl+Shift+I

1.2 Obtener cookies

  • Para que todas las cookies sean transportadas por el cliente, utilicepedidoobjeto
Cookie[] cookies = request.getCookies();
  • Recorre la matriz y obtén cada objeto Cookie:for
  • Obtener datos utilizando métodos de objeto Cookie
cookie.getName();
cookie.getValue();

  Luego de presentar los pasos correspondientes a la obtención de cookies, usemos un caso para completar la adquisición de cookies, los pasos de implementación específicos son:

Requisitos: obtener los datos almacenados en el objeto Cookie en el caso anterior en el Servlet
1. Escriba una nueva clase de Servlet llamada BServlet,
2. Utilice el objeto de solicitud en el BServlet para obtener la matriz de Cookies, recorrer la matriz y obtener el objeto especificado. nombre de los datos El valor correspondiente
3. Inicie la prueba e imprima el valor obtenido en la consola;

(1) Escriba una nueva clase de servlet llamada BServlet
(2) Utilice el objeto de solicitud en BServlet para obtener la matriz de cookies, recorrer la matriz y obtener el valor correspondiente al nombre especificado de los datos.=

package com.itheima.web.cookie;

@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取Cookie
        //1. 获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2. 遍历数组
        for (Cookie cookie : cookies) {
    
    
            //3. 获取数据
            String name = cookie.getName();
            if("username".equals(name)){
    
    
                String value = cookie.getValue();
                System.out.println(name+":"+value);
                break;
            }
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3) Inicie la prueba e imprima el valor obtenido en la consola
Visite http://localhost:8080/cookie-demo/bServlet
Insertar descripción de la imagen aquí
la consola de IDEA para ver los resultados de salida:
Insertar descripción de la imagen aquí

pensar:al probar

  • ¿Puedo obtener los datos en la cookie cerrando el navegador entre el acceso a AServlet y BServlet, reiniciando el navegador y luego accediendo a BServlet? [Prueba personal, ¡es posible!

Discutiremos este tema en los detalles del uso de cookies, para que puedas probarlo primero.

1.3 Resumen

En este apartado explicamos principalmente el uso básico de las Cookies, incluyendo dos partes

  • Enviar galleta:
    • Cree un objeto Cookie y establezca el valor:Cookie cookie = new Cookie("key","value");
    • Usos del envío de cookies al clienteObjeto de respuesta:response.addCookie(cookie);
  • Obtener galletas:
    • usarSolicitar objetoObtenga la matriz de cookies:Cookie[] cookies = request.getCookies();
    • matriz transversal
    • Obtenga el valor de cada objeto Cookie en la matriz:cookie.getName()和cookie.getValue()

  Después de introducir el uso básico de las cookies, ¿cómo logra la capa inferior de cookies el intercambio de datos entre dos solicitudes en una sesión?

2. Análisis del principio de Cookie (solo conócelo)

El principio de implementación de Cookie se basa en el protocolo HTTP, en el que se diseñan dos información de encabezado de solicitud en el protocolo HTTP: (la respuesta y la solicitud son relativas al servidor)

  • Encabezado de respuesta: establecer-cookie
  • Encabezado de solicitud: cookie
    Insertar descripción de la imagen aquí
  • En el caso anterior, se ha podido implementar la función de que AServlet envíe Cookie al front end y BServlet obtenga la Cookie de la solicitud.
  • Cuando AServlet responde a los datos, el servidor Tomcat responde a los datos según el protocolo HTTP.
  • Cuando Tomcat descubre que el backend está devolviendo un objeto Cookie, Tomcat agregará una línea de datos al encabezado de respuesta.Set-Cookie:username=zs
  • Una vez que el navegador obtiene el resultado de la respuesta, puede obtener Set-Cookieel valor correspondiente del encabezado de respuesta username=zsy almacenar los datos en la memoria del navegador.
  • Cuando el navegador envía una solicitud a BServlet nuevamente, el navegador la agregará automáticamente al encabezado de la solicitud.Cookie: username=zsEnviado al servidor BServlet
  • El objeto Solicitud encapsulará los valores correspondientes a las cookies en el encabezado de la solicitud en objetos Cookie y eventualmente formará una matriz.
  • Después de que BServlet obtiene Cookie [] a través del objeto Solicitud, puede obtener los datos que necesita de él.

A continuación, utilice el caso de ahora para verificar la conclusión anterior:
(1) Acceda a la dirección correspondiente al AServlet http://localhost:8080/cookie-demo/aServlet
  y utilice el navegador Chrom para abrir las herramientas de desarrollador (F12 o Ctrl+Shift+I) para verencabezado de respuestaLos datos en
Insertar descripción de la imagen aquí
(2) Acceda a la dirección correspondiente a BServlet `http://localhost:8080/cookie-demo/bServlet
  Utilice el navegador Chrom para abrir las herramientas de desarrollador (F12 o Crtl+Shift+I) para verEncabezado de solicitudDatos en:
Insertar descripción de la imagen aquí

3 、Detalles de uso de cookies (pesados)

  En esta sección, explicamos principalmente dos conocimientos: el primero es el tiempo de supervivencia de Cookie y el segundo es cómo Cookie almacena los caracteres chinos. Primero, aprendamos sobre el tiempo de supervivencia de Cookie.

3.1 Tiempo de supervivencia de las cookies (Pesado

Te pedí que pensaras en una pregunta antes:Insertar descripción de la imagen aquí

(1) El navegador envía una solicitud a AServlet, y AServlet responderá a un usernanme=zsobjeto Cookie existente en el navegador
(2) El navegador recibe los datos de respuesta y almacena la cookie en la memoria del navegador
(3) Cuando el navegador envía una solicitud a BServlet, BServlet puede usar el objeto Solicitud para obtener datos de Cookies
(4) Antes de enviar una solicitud a BServlet, si el navegador se cierra y se vuelve a abrir para acceder, ¿puede BServlet obtener datos de Cookies?
Nota: Cerrar y abrir el navegador no significa abrir una nueva tarjeta gráfica seleccionada, debe cerrarse y luego abrirse y el orden no se puede cambiar.
Insertar descripción de la imagen aquí

  En respuesta al problema anterior, a través de la demostración, encontrará que los datos de las cookies ya no se pueden obtener en BServlet, ¿por qué?

  • De forma predeterminada, las cookies se almacenan en la memoria del navegador. Cuando se cierra el navegador y se libera la memoria, la cookie se destruye.
    Esta conclusión confirma el efecto de demostración anterior, pero si utiliza esta cookie predeterminada, algunos requisitos no se pueden cumplir, por ejemplo:
    Insertar descripción de la imagen aquí
    hay una función en la página de inicio de sesión del sitio web anterior 记住我, con la que todos están familiarizados.
  • Ingrese su nombre de usuario y contraseña por primera vez y marque la casilla 记住我para iniciar sesión.
  • La próxima vez que inicie sesión, su nombre de usuario y contraseña se completarán automáticamente y no necesitará volver a ingresarlos para iniciar sesión.
  • Por ejemplo, 记住我esta función requiere recordar el usuario y la contraseña durante una semana, por lo que habrá problemas al utilizar las cookies predeterminadas.
  • Porque, de forma predeterminada, las cookies se eliminarán de la memoria del navegador tan pronto como se cierre el navegador y 记住我las funciones no se podrán implementar.

Entonces ahora nos encontramos con un problema:Cómo almacenar cookies de forma persistente?

De hecho, Cookie nos ha proporcionado la API correspondiente para lograr esto. Esta API esestablecer edad máxima,

  • Establecer el tiempo de supervivencia de las cookies
setMaxAge(int seconds)

Los valores de los parámetros son:
1.Número positivo: escriba la cookie en el disco duro de la computadora donde se encuentra el navegador para un almacenamiento persistente. Eliminar automáticamente cuando expire el tiempo
2.Número negativo: valor predeterminado, la cookie está en la memoria actual del navegador, cuando se cierra el navegador, la cookie se destruye.
3. Cero: Elimina la cookie correspondiente
, luego configuramos el tiempo de supervivencia de la cookie en AServlet.

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //发送Cookie
        //1. 创建Cookie对象
        Cookie cookie = new Cookie("username","zs");
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60*60*24*7); //易阅读,需程序计算
        //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

Después de modificar el código, inicie la prueba y visitehttp://localhost:8080/cookie-demo/aServlet

  • Después de acceder a un AServlet, cierre el navegador, reinícielo y luego acceda nuevamente. Si http://localhost:8080/cookie-demo/bServetse puede imprimir en la consola username:zs, significa que la cookie no se destruye cuando se cierra el navegador.
  • Vea el contenido de la cookie a través de su navegador y encontrará información relacionada con las cookies.
    Insertar descripción de la imagen aquí

3.2 Tiendas de galletas chinas (Pesado

Primero, demostremos un efecto. username=zsCambie el valor anterior username=张三para 张三guardar caracteres chinos en la cookie y vea cuál es el efecto:

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //发送Cookie
        //1. 创建Cookie对象
        String value = "张三";
        Cookie cookie = new Cookie("username", value);
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60 * 60 * 24 * 7); //易阅读,需程序计算
        //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

Inicie la prueba de acceso, al acceder http://localhost:8080/cookie-demo/aServletencontrará que el navegador le mostrará un mensaje de error:
Insertar descripción de la imagen aquí
A través de la demostración del caso anterior, llegamos a una conclusión:

  • Las cookies no pueden almacenar directamente caracteres chinos

  Las cookies no pueden almacenar chino, pero si es necesario, ¿cómo debemos resolverlo en este momento? En este momento
  , podemos usar un punto de conocimiento que hemos aprendido antes URL编码, por lo que si necesitamos almacenar chino, simplementeNecesidad de transcodificar, las ideas de implementación específicas son:

1. Codifique la URL china en AServlet, úsela URLEncoder.encode()y almacene el valor codificado en Cookie
2. Obtenga el valor en Cookie en BServlet, y el valor obtenido es el valor codificado en URL
3. Almacene el valor obtenido en la decodificación de URL, usándolo URLDecoder.decode(), Puedes obtener el valor chino correspondiente.

(1) URL que codifica chino en AServlet

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //发送Cookie
        //1. 创建Cookie对象
        String value = "张三";
        //对中文进行URL编码
        value = URLEncoder.encode(value, "UTF-8");
        System.out.println("存储数据:" + value);
        //将编码后的值存入Cookie中
        Cookie cookie = new Cookie("username", value);
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60 * 60 * 24 * 7); //易阅读,需程序计算
        //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(2) Obtener el valor en BServlet y decodificar el valor

package com.itheima.web.cookie;

@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //获取Cookie
        //1. 获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2. 遍历数组
        for (Cookie cookie : cookies) {
    
    
            //3. 获取数据
            String name = cookie.getName();
            if ("username".equals(name)) {
    
    
                String value = cookie.getValue(); //获取的是URL编码后的值 %E5%BC%A0%E4%B8%89
                //URL解码
                value = URLDecoder.decode(value, "UTF-8");
                System.out.println(name + ":" + value);//value解码后为 张三
                break;
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

Ejecute el programa y ejecute las direcciones de los dos archivos anteriores en el navegador respectivamente. Puede generar dos oraciones en la consola:

存储数据:%E5%BC%A0%E4%B8%89
username:张三

En este punto, podemos almacenar chino en Cookie para su uso.

3.3 、resumen

En los detalles del uso de cookies, hablamos de 存活时间la suma de cookies 存储中文:

  • El tiempo de supervivencia requiere dominar setMaxAage()el uso de API
  • Para almacenar chino, es necesario dominar el uso de la codificación y decodificación de URL.

tres,Sesión

  Las cookies ya pueden completar el intercambio de datos entre múltiples solicitudes en una sesión. También mencionamos que las sesiones también se pueden implementar, entonces:

  • ¿Qué es la sesión?
  • ¿Cómo utilizar la sesión?
  • ¿Cómo se implementa la sesión?
  • ¿Cuáles son las precauciones al usar Session?

1 、Uso básico de la sesión

1. Concepto
Sesión:Tecnología de seguimiento de sesiones del lado del servidor: guarda datos en el servidor.

  • La sesión se almacena en el lado del servidor y la cookie se almacena en el lado del cliente.
  • Los datos almacenados en el cliente se roban e interceptan fácilmente y existen muchos factores de inseguridad.
  • Los datos almacenados en el lado del servidor son más pequeños que los del lado del cliente.más seguro

2.Flujo de trabajo de la sesión
Insertar descripción de la imagen aquí

  • El AServlet del lado del servidor obtiene un objeto de sesión y almacena los datos en él.
  • El BServlet en el lado del servidor obtiene el mismo objeto de sesión y recupera datos de él.
  • Esto permite compartir datos entre múltiples solicitudes en una sesión.
  • La pregunta más importante ahora es ¿cómo garantizar que AServlet y BServlet utilicen el mismo objeto de sesión (explicado en la sesión de análisis de principios)?

3. Uso básico de Session
  La interfaz HttpSession se proporciona en JavaEE para realizar la función de compartir datos entre múltiples solicitudes en una sesión.
Los pasos de uso específicos son:

  • Obtener objeto de sesión, usando requestel objeto
HttpSession session = request.getSession();
  • Funciones proporcionadas por el objeto Sesión:
    • Almacenar datos en el campo de sesión.
      void setAttribute(String name, Object o)
      
    • Obtener el valor según la clave
      Object getAttribute(String name)
      
    • Eliminar el par clave-valor según la clave
      void removeAttribute(String name)
      

  Después de presentar la API relacionada con la sesión, usemos un caso para completar el uso de la sesión. Los pasos de implementación específicos son:

Requisitos: almacenar datos en la sesión en un servlet y obtener los datos almacenados en la sesión en otro servlet
1. Crear una clase de servlet llamada SessionDemo1
2. Crear una clase de servlet llamada SessionDemo2
3. En el método de SessionDemo1: obtener el objeto de sesión y almacenar datos
4. En el método de SessionDemo2: Obtenga el objeto Session y obtenga los datos
5. Inicie la prueba

(1) Cree una clase de servlet llamada SessionDemo1
(3) SessionDemo1: obtenga el objeto Session y almacene datos

package com.itheima.web.session;

@WebServlet("/demo1")
public class SessionDemo1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //存储到Session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        //2. 存储数据
        session.setAttribute("username", "zs");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(2) Cree una clase de servlet llamada SessionDemo2
(4) SessionDemo2: obtenga el objeto Session y obtenga datos

package com.itheima.web.session;

@WebServlet("/demo2")
public class SessionDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取数据,从session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        //2. 获取数据
        Object username = session.getAttribute("username");
        System.out.println(username);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(5) Comience a probar,

  • Acceda primero http://localhost:8080/cookie-demo/demo1y almacene datos en la sesión
  • Durante el acceso http://localhost:8080/cookie-demo/demo2, obtenga datos de la sesión
  • Ver la consola.
    Insertar descripción de la imagen aquí
    A través del efecto del caso, puede ver que la sesión puede compartir datos entre dos solicitudes en una sesión.

1.1 、resumen

En este punto, se ha completado el uso básico de Session, los puntos clave a dominar son:

  • Adquisición de sesión
    HttpSession session = request.getSession();
    
  • Uso de métodos de sesión comunes
    void setAttribute(String name, Object o)
    Object getAttribute(String name)
    
    Nota: Lo que se puede almacenar en la sesión es un tipo de datos de objeto, lo que significa que cualquier tipo de datos se puede almacenar en la sesión.

  Después de presentar el uso básico de Session, ¿cómo logra la capa subyacente de Session compartir datos entre dos solicitudes en una sesión?

2. Análisis del principio de Sesión

  • La sesión se implementa en base a Cookie

  De hecho, esta oración no puede explicar en detalle la implementación subyacente de Session. A continuación, analicemos el principio de implementación específico de Session paso a paso:

(1)Requisitos previos
Insertar descripción de la imagen aquí
  Si Session desea compartir datos entre múltiples solicitudes en una sesión, debe asegurarse de que el objeto obtenido por múltiples solicitudes sea la misma sesión..
  ¿Son entonces un objeto? Es muy sencillo verificar esta conclusión: en el caso anterior, solo necesita imprimir los objetos de sesión en los dos servlets.
Demostración de sesión1

        //1. 获取Session对象
        HttpSession session = request.getSession();
        System.out.println(session);

Demostración de sesión2

        //获取数据,从session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        System.out.println(session);

Inicie la prueba y visite respectivamente,
http://localhost:8080/cookie-demo/demo1
http://localhost:8080/cookie-demo/demo2
Insertar descripción de la imagen aquí
al imprimir podrá obtener las siguientes conclusiones:

  • El objeto de sesión obtenido en las dos clases de servlet es el mismo
  • Actualice las solicitudes demo1 y demo2 varias veces y los resultados finales impresos en la consola serán los mismos.

  Entonces surge nuevamente la pregunta: si abre un nuevo navegador y accede a demo1 o demo2, ¿la sesión impresa en la consola seguirá siendo el mismo objeto?
Insertar descripción de la imagen aquí
  Nota: Al realizar una demostración en una computadora, si es el mismo navegador, debe cerrar todos los navegadores y volver a abrirlos para abrir un nuevo navegador.
  Por supuesto, también puede utilizar diferentes navegadores para realizar pruebas, por lo que no es necesario cerrar todos los navegadores anteriores.
  Resultados de la prueba: Si es un navegador diferente o después de volver a abrir el navegador, la Sesión impresa será diferente.
  Por lo tanto, Session también implementa el intercambio de datos entre múltiples solicitudes en una sesión.
  Entonces surge la pregunta principal,¿Cómo garantiza Session que el objeto Session obtenido en una sesión sea el mismo?
Insertar descripción de la imagen aquí

(1) Cuando demo1 obtiene el objeto de sesión por primera vez, el objeto de sesión tendrá un identificador único. Si es así (2 id:10
) después de que demo1 almacene otros datos en la sesión y procese todos los negocios, debe responder al resultado a través de el servidor Tomcat Navegador
(3) Cuando el servidor Tomcat descubre que el objeto de sesión se utiliza en el procesamiento empresarial, tratará el identificador único de la sesión id:10como una cookie, lo agregará Set-Cookie:JESSIONID=10al encabezado de respuesta y responderá al navegador
(4) Después el navegador recibe el resultado de la respuesta, almacenará los datos de la cookie en el encabezado de respuesta en la memoria del navegador
(5) Cuando el navegador accede a demo2 en la misma sesión, agregará cookie: JESSIONID=10los datos de la cookie al encabezado de la solicitud en el formato y enviarlo al servidor Tomcat
(6) Después de que demo2 recibe la solicitud, lee el valor JSESSIONID en la cookie como 10 del encabezado de la solicitud y luego busca id:10el objeto de sesión en la memoria del servidor. Si lo encuentra, devuelve el objeto directamente. Si no, crea una nueva sesión. Después de que el objeto
(7) cierra y abre el navegador, debido a que la cookie del navegador ha sido destruida, no hay datos JESSIONID y la sesión obtenida por el servidor es un objeto de sesión completamente nuevo. .

En este Session是基于Cookie来实现的punto hemos terminado la explicación, a continuación lo demostraremos mediante ejemplos:
(1) Utilice el navegador Chrome para acceder http://localhost:8080/cookie-demo/demo1, abra el modo desarrollador (F12 o Ctrl+Shift+I) y veaEncabezados de respuestaDatos:
Insertar descripción de la imagen aquí
(2) Utilice el navegador Chrome para visitar nuevamente http://localhost:8080/cookie-demo/demo2y verEncabezados de solicituddatos:
Insertar descripción de la imagen aquí

2.1 、resumen

Después de introducir el principio de sesión, solo necesitamos recordar

  • La sesión se implementa en base a Cookie

3 、Detalles de uso de la sesión

  En esta sección explicaremos principalmente dos conocimientos, el primero esPasivación y activación de sesión., el segundo esDestrucción de sesiónPrimero, aprendamos qué es la pasivación y activación de sesiones.

3.1 、Pasivación y activación de sesión.

La primera pregunta en la que todos deben pensar es:

  • Después de reiniciar el servidor, ¿los datos de la sesión siguen ahí?
    Para responder a esta pregunta, primero podemos mirar la siguiente imagen:
    Insertar descripción de la imagen aquí
    (1) El objeto de sesión compartido por el AServlet y el BServlet del lado del servidor debe almacenarse en el servidor. memoria
    (2)) Después de reiniciar el servidor, los datos en la memoria deberían haberse liberado y los objetos deberían haberse destruido,
    por lo que los datos de la sesión ya no deberían existir. ¿Pero qué problemas ocurrirán si la sesión no existe?

    Por ejemplo,
    (1) el usuario agrega los artículos que desea comprar al carrito de compras. Debido a que es necesario solicitar la misma sesión varias veces para compartir datos, se supone que los datos se almacenan en el objeto Sesión. (2)
    El El usuario está a punto de pagar. Cuando el usuario recibió una llamada, la acción de pago quedó varada.
    (3) Mientras el usuario estaba haciendo una llamada, el sitio web de compras necesitaba reiniciarse por algunas razones.
    (4) Después del reinicio, la sesión Los datos se destruyeron y la información del producto en el carrito de compras también se perdió, luego desaparece
    (5) Si el usuario desea iniciar el pago nuevamente, habrá un problema.

      Entonces, para los datos de la sesión, deberíamos poder guardar los datos incluso si se reinicia el servidor.
      Después de analizar tanto, cuando se reinicia el servidor Tomcat, si se guardarán los datos de la sesión y cómo se guardan, podemos demostrarlo a través de casos reales:
      Nota: El apagado y el inicio mencionados aquí deberían garantizar un apagado y un inicio normales.
    Entonces, ¿cómo cerrar el servidor Tomcat normalmente?
    Debe usar la línea de comando para iniciar y detener el servidor Tomcat:
    puesta en marcha: Ingrese al directorio donde se encuentra el proyecto pom.xml y ejecútelotomcat7:run
    Insertar descripción de la imagen aquí
    detener:En la interfaz de línea de comando que se inicia, ingresectrl+c

    Con los dos métodos normales de inicio y apagado anteriores, el siguiente proceso de prueba es:

    (1) Primero inicie el servidor Tomcat
    (2) Acceda http://localhost:8080/cookie-demo/demo1y almacene los datos en la sesión
    (3) Detenga el servidor Tomcat correctamente
    (4) Reinicie el servidor Tomcat nuevamente
    (5) Acceda http://localhost:8080/cookie-demo/demo2para ver si se pueden obtener los datos en la sesión
    Insertar descripción de la imagen aquí

      Después de la prueba, encontrará que siempre que el servidor se apague y se inicie normalmente, los datos de la sesión se pueden guardar.
    Entonces, ¿cómo lo hace el servidor Tomcat?
    Las razones específicas son:Pasivación y activación de sesión.:

    • pasivación: Después de que el servidor se apaga normalmente, Tomcat escribirá automáticamente los datos de la sesión en el archivo del disco duro.
      • La ruta de datos pasivada es:项目目录\target\tomcat\work\Tomcat\localhost\项目名称\SESSIONS.ser
        Insertar descripción de la imagen aquí
    • activación: Después de iniciar el servidor nuevamente, cargue los datos del archivo en la sesión
      • Una vez cargados los datos en la sesión, los archivos en la ruta SESSIONS.serse eliminarán.

  Sólo necesita comprender todo el proceso mencionado anteriormente. Debido a que todos los procesos los completa Tomcat, no es necesario que participemos.

Resumen
Después de introducir la pasivación y activación de Session, debemos prestar atención a lo siguiente:

  • Los datos de la sesión se almacenan en el lado del servidor. Después de reiniciar el servidor, los datos de la sesión se guardarán.
  • Una vez que se cierra e inicia el navegador, la conexión restablecida ya es una nueva sesión y los datos de la sesión obtenidos también son un nuevo objeto.
  • Si desea compartir los datos de la sesión, el navegador no se puede cerrar, por lo que los datos de la sesión no se pueden guardar durante mucho tiempo.
  • Las cookies se almacenan en el lado del cliente y pueden almacenarse durante mucho tiempo.

3.2 Destrucción de sesión

Hay dos formas de destruir una sesión:

  • De forma predeterminada, no se realiza ninguna operación y se destruye automáticamente en 30 minutos.
    • Este tiempo de caducidad se puede modificar a través de la configuración.
      • Configurar en el web.xml del proyecto.
        <?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_3_1.xsd"
                 version="3.1">
        
            <session-config>
                <session-timeout>100</session-timeout>
            </session-config>
        </web-app>
        
      • Si no está configurado, el valor predeterminado es 30 minutos. El valor predeterminado está codificado en el archivo de configuración web.xml de Tomcat.Insertar descripción de la imagen aquí
  • Llame a invalidate() del objeto Session para destruirlo
    • Agregue un método de destrucción de sesión a la clase SessionDemo2
package com.itheima.web.session;

@WebServlet("/demo2")
public class SessionDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取数据,从session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        // 销毁
        session.invalidate();
        //2. 获取数据
        Object username = session.getAttribute("username");
        System.out.println(username);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}
  • Inicie la prueba de acceso, primero visite demo1 para almacenar datos en la sesión y luego visite demo2 nuevamente para obtener datos de la sesión.
    Insertar descripción de la imagen aquí
  • Este método de destrucción generalmente requiere que la sesión se destruya cuando el usuario sale.

4 、Resumen de Cookies y Sesiones

  • Tanto la cookie como la sesión se utilizan para completar múltiples solicitudes dentro de una sesión.compartir datosde.
    Al juntar los dos objetos requeridos, debe pensar en: ¿
    Cuál es la diferencia entre Cookie y Sesión? ¿
    Cuáles son los escenarios de aplicación de Cookie y Sesión?

  • la diferencia:

    • Ubicación de almacenamiento: la cookie almacena datos en el lado del cliente y la sesión almacena datos en el lado del servidor.
    • Seguridad: la cookie no es segura, la sesión es segura
    • Tamaño de los datos: Cookie máximo de 3 KB, la sesión no tiene límite de tamaño
    • Tiempo de almacenamiento: las cookies se pueden almacenar durante mucho tiempo a través de setMaxAge () y la sesión tiene un valor predeterminado de 30 minutos.
    • Rendimiento del servidor: las cookies no ocupan recursos del servidor y las sesiones ocupan recursos del servidor.
  • Escenarios de aplicación:

    • Carrito de compras: utiliza cookies para almacenar
    • Se muestra en el nombre del usuario que inició sesión: Usar sesión para almacenar
    • Función Recordarme: utiliza cookies para almacenar
    • Código de verificación: use la sesión para almacenar
  • en conclusión

    • Las cookies se utilizan para garantizar la identificación del usuario cuando no ha iniciado sesión.
    • La sesión se utiliza para guardar datos después de iniciar sesión

  Después de presentar Cookie y Session,Aún es necesario analizar en detalle cuál utilizar en función del negocio específico.

cuatro,Caso de registro de inicio de sesión de usuario

1. Análisis de la demanda

Declaración de necesidades:

  1. Complete la función de inicio de sesión del usuario . Si el usuario marca "Recordar usuario" , la página de inicio de sesión se visitará la próxima vez.autocompletarUsuario Contraseña
  2. Complete la función de registro e implementeCódigo de verificaciónFunción
    Insertar descripción de la imagen aquí

2 、Función de inicio de sesión de usuario

1. Requisitos:
Insertar descripción de la imagen aquí

  • Después de que el usuario inicie sesión correctamente, salte a la página de lista y muestre el nombre del usuario actualmente conectado en la página.
  • Después de que el usuario no pueda iniciar sesión, regrese a la página de inicio de sesión y muestre el mensaje de error correspondiente en la página.

2.Implementar análisis de procesos.
Insertar descripción de la imagen aquí

(1) El front-end envía solicitudes y datos al LoginServlet de la capa web a través del formulario
(2) Recibe la solicitud y los datos [nombre de usuario y contraseña] en el LoginServlet
(3) Después de que LoginServlet recibe la solicitud y los datos, Llame a la capa de Servicio para completar la consulta según el nombre de usuario y la contraseña Objeto de usuario
(4) En la capa de Servicio, debe escribir la clase UserService, implementar el método de inicio de sesión en la clase y llamar al UserMapper de la capa Dao. en el método
(5) En la interfaz UserMapper, declare un método para consultar la información del usuario según el nombre de usuario y la contraseña
(6) Dao Después de que la capa consulta los datos, encapsula los datos devueltos en el objeto Usuario y entrega el objeto a la capa de Servicio
(7) La capa de Servicio devuelve los datos a la capa Web
(8) Después de que la capa Web obtiene el objeto Usuario, determina el objeto Usuario y, si es Nulo, responde el mensaje de error a la página de inicio de sesión. no es nulo, salte a la página de la lista, guarde la información del usuario actualmente conectado en la sesión y llévela a la página de la lista.

3. Implementación específica

(1) Complete la escritura del código de la capa Dao
(1.1) y 04-资料\1. 登录注册案例\2. MyBatis环境\UserMapper.javacolóquelo debajo del paquete com.itheima.mapper`:

package com.itheima.mapper;

public interface UserMapper {
    
    
    /**
     * 根据用户名和密码查询用户对象
     * @param username
     * @param password
     * @return
     */
    @Select("select * from tb_user where username = #{username} and password = #{password}")
    User select(@Param("username") String username,@Param("password")  String password);

    /**
     * 根据用户名查询用户对象
     * @param username
     * @return
     */
    @Select("select * from tb_user where username = #{username}")
    User selectByUsername(String username);

    /**
     * 添加用户
     * @param user
     */
    @Insert("insert into tb_user values(null,#{username},#{password})")
    void add(User user);
}

(1.2)、(Crear objeto de clase de entidad) se 04-资料\1. 登录注册案例\2. MyBatis环境\User.javacolocará com.itheima.pojodebajo del paquete:

package com.itheima.pojo;
public class User {
    
    

    private Integer id;
    private String username;
    private String password;

    public Integer getId() {
    
    
        return id;
    }
    public void setId(Integer id) {
    
    
        this.id = id;
    }
    public String getUsername() {
    
    
        return username;
    }
    public void setUsername(String username) {
    
    
        this.username = username;
    }
    public String getPassword() {
    
    
        return password;
    }
    public void setPassword(String password) {
    
    
        this.password = password;
    }
    @Override
    public String toString() {
    
    
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

(1.3) se 04-资料\1. 登录注册案例\2. MyBatis环境\UserMapper.xmlcolocará en resources/com/itheima/mapperel directorio:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.UserMapper">

</mapper>

(2) Complete la escritura del código de la capa de Servicio
(2.1) com.itheima.serviceCree la clase UserService en el paquete

public class UserService {
    
    
    //1.使用工具类获取SqlSessionFactory
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    /**
     * 登录方法
     * @param username
     * @param password
     * @return
     */
    public User login(String username,String password){
    
    
        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取UserMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //4. 调用方法
        User user = mapper.select(username, password);
        //释放资源
        sqlSession.close();

        return  user;
    }
}

(3) Complete la escritura del código de la página y la capa web.

(3.1) 04-资料\1. 登录注册案例\1. 静态页面Copiar al webappdirectorio del proyecto:
Insertar descripción de la imagen aquí
(3.2) login.htmlModificar el contenido paralogin.jsp

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false"  language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link href="css/login.css" rel="stylesheet">
</head>

<body>
<div id="loginDiv" style="height: 350px">
    <form action="/brand-demo/loginServlet" method="post" id="form">
        <h1 id="loginMsg">LOGIN IN</h1>
        <!-- <div id="errorMsg">用户名或密码不正确</div>-->
        <div id="errorMsg">${login_msg}</div>
        <p>Username:<input id="username" name="username" type="text"></p>

        <p>Password:<input id="password" name="password" type="password"></p>
        <p>Remember:<input id="remember" name="remember" type="checkbox"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
            <a href="register.html">没有账号?</a>
        </div>
    </form>
</div>
</body>
</html>

(3.3) Crear clase LoginServlet

package com.itheima.web;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    
    
    private UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //2. 调用service查询
        User user = service.login(username, password);

        //3. 判断
        if (user != null) {
    
    
            //登录成功,跳转到查询所有的BrandServlet

            //将登陆成功后的user对象,存储到session
            HttpSession session = request.getSession();
            //将user信息存储到session;
            session.setAttribute("user", user);

            String contextPath = request.getContextPath();//获取项目访问路径
            response.sendRedirect(contextPath + "/selectAllServlet");//Respones请求重定向
        } else {
    
    
            // 登录失败,
            // 将错误信息存储到request,setAttribute传递数据给转发的对象
            request.setAttribute("login_msg", "用户名或密码错误");
            // 跳转到login.jsp,请求转发
            request.getRequestDispatcher("/login.jsp").forward(request, response);  
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3.4) Agregue un mensaje para dar la bienvenida al usuario actual debajo de la etiqueta en brand.jsp:

<h1>${user.username},欢迎您</h1>

(3.5) Modifique login.jsp y use la expresión EL para obtener información de error

修改前内容:<div id="errorMsg">用户名或密码不正确</div>
修改后内容: <div id="errorMsg">${login_msg}</div>

(4) Inicio, prueba de acceso

(4.1) Ingrese a la página de inicio de sesión e ingrese el nombre de usuario o contraseña incorrectos
Insertar descripción de la imagen aquí
(4.2) Ingrese la información de usuario y contraseña correcta
Insertar descripción de la imagen aquí

2.1 Resumen

  • En LoginServlet, los datos del usuario que inició sesión correctamente se almacenan en la sesión y el método obtiene la información del usuario actualmente conectado en la página de lista para su visualización.
  • En LoginServlet, el mensaje de error de error de inicio de sesión se almacena en la solicitud. Si se almacena en la sesión, todas las solicitudes en esta sesión tendrán el mensaje de error de error de inicio de sesión. Esto no es necesario, por lo que no es necesario almacenarlo. en sesión

3 、Recuérdame-establecer galleta

  1. necesidad:
      Si el usuario marca "Recordar usuario", el nombre de usuario y la contraseña se completarán automáticamente la próxima vez que visite la página de inicio de sesión. Esto puede mejorar la experiencia del usuario.
    Insertar descripción de la imagen aquí
    En respuesta a la demanda anterior, la pregunta más importante es: ¿Cómo completar automáticamente el nombre de usuario y la contraseña?

  2. Análisis del proceso de implementación
      Debido a que 记住我la función es lograr el efecto de que incluso si el usuario cierra el navegador y vuelve a visitarlo después de unos días, se puede completar automáticamente, por lo que la información de inicio de sesión debe almacenarse en un archivo que se pueda guardar. durante mucho tiempo y aún puede ser válido después de cerrar y reiniciar el navegador. El lugar es del que hablamos antesGalleta,entonces:

  • Escribir nombre de usuario y contraseñaGalleta, y la cookie se almacena de forma persistente. El navegador la llevará automáticamente la próxima vez que visite.
  • Después de obtener los datos de las cookies en la página, configúrelas en las casillas de nombre de usuario y contraseña.
  • ¿Cuándo se escriben las cookies?
    • El usuario debe iniciar sesión correctamente antes de escribir.
    • 记住我Casillas de verificación que los usuarios deben marcar en la página de inicio de sesión
      Insertar descripción de la imagen aquí

(1) Al enviar solicitudes y datos, el front-end debe llevar un Rememberdato más sobre si el usuario ha verificado o no
(2) Después de que LoginServlet obtiene los datos, llama al Servicio para completar la determinación del nombre de usuario y la contraseña
( 3) El inicio de sesión es exitoso y el usuario marca la casilla de verificación en la interfaz. Si se selecciona 记住我, debe escribir los datos del nombre de usuario y la contraseña en la cookie y configurar el tiempo de supervivencia de la cookie
(4) Después de que la configuración sea exitosa, los datos serán respondidos al front-end.

  1. Implementación

(1) Establezca el valor de la casilla de verificación en login.jsp

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link href="css/login.css" rel="stylesheet">
</head>

<body>
<div id="loginDiv" style="height: 350px">
    <form action="/brand-demo/loginServlet" method="post" id="form">
        <h1 id="loginMsg">LOGIN IN</h1>
        <!--        <div id="errorMsg">用户名或密码不正确</div>-->
        <div id="errorMsg">${login_msg}</div>
        <p>Username:<input id="username" name="username" type="text"></p>
        <p>Password:<input id="password" name="password" type="password"></p>
        <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
            <a href="register.html">没有账号?</a>
        </div>
    </form>
</div>
</body>
</html>

(2) Obtenga el valor de la casilla de verificación en LoginServlet y configure la cookie después de iniciar sesión correctamente

package com.itheima.web;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    
    
    private UserService service = new UserService();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //获取复选框数据
        String remember = request.getParameter("remember");

        //2. 调用service查询
        User user = service.login(username, password);

        //3. 判断
        if (user != null) {
    
    
            //登录成功,跳转到查询所有的BrandServlet
            //判断用户是否勾选记住我,字符串写前面是为了避免出现空指针异常
            if ("1".equals(remember)) {
    
    
                //勾选了,发送Cookie
                //1. 创建Cookie对象
                Cookie c_username = new Cookie("username", username);
                Cookie c_password = new Cookie("password", password);
                // 设置Cookie的存活时间
                c_username.setMaxAge(60 * 60 * 24 * 7);
                c_password.setMaxAge(60 * 60 * 24 * 7);
                //2. 发送
                response.addCookie(c_username);
                response.addCookie(c_password);
            }
            //将登陆成功后的user对象,存储到session
            HttpSession session = request.getSession();
            session.setAttribute("user", user);

            String contextPath = request.getContextPath();//获取项目访问路径
            response.sendRedirect(contextPath + "/selectAllServlet");//Respones请求重定向
        } else {
    
    
            // 登录失败,
            // 存储错误信息到request
            request.setAttribute("login_msg", "用户名或密码错误");
            // 跳转到login.jsp,转发;
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3) Inicie la prueba de acceso.
  Solo cuando el nombre de usuario y la contraseña actuales se ingresan correctamente y la casilla Recordar está marcada, se pueden ver los datos relacionados con las cookies en el encabezado de respuesta.
Insertar descripción de la imagen aquí

4 、Recuérdame - Obtén galleta

  1. Después de que el
      inicio de sesión requerido sea exitoso y se marque Recordar, los datos de la cookie devueltos por el backend al frontend se almacenarán. A continuación, debe obtener los datos en la cookie de la página y configurar los datos en las casillas de nombre de usuario y contraseña en la página de inicio de sesión.
    Insertar descripción de la imagen aquí
    ¿Cómo obtener el valor de la cookie directamente en la página?

  2. Para implementar el análisis de procesos
    , puede utilizar expresiones EL en la página ${cookie.key.value}
    clave: se refiere al nombre de la clave almacenada en la cookie.
    Insertar descripción de la imagen aquí

(1) Utilice el valor en el cuadro de entrada del formulario del nombre de usuario login.jsp para agregar un valor predeterminado al elemento del formulario. Se puede utilizar el valor${cookie.username.value}

(2) Utilice el valor en el cuadro de entrada del formulario de contraseña login.jsp para agregar un valor predeterminado al elemento del formulario. Se puede utilizar el valor${cookie.password.value}

  1. Implementación específica
    (1) Modificar la página login.jsp
<p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p>

<p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p>
  1. Después de acceder a la prueba y volver a visitar la página de inicio de sesión, podrá ver que se han completado el usuario y la contraseña.
    Insertar descripción de la imagen aquí

5 、Función de registro de usuario

  1. necesidad
  • Función de registro: guarda la información del usuario en la base de datos
  • Función de código de verificación
    • Mostrar código de verificación: muestra la imagen del código de verificación y haz clic para cambiar.
    • Código de verificación de verificación: si el código de verificación no se completa correctamente, el registro fallará.

Insertar descripción de la imagen aquí
2. Implementar análisis de procesos
Insertar descripción de la imagen aquí
(1) El front-end envía solicitudes y datos al RegisterServlet de la capa web a través de un formulario

(2) Recibir solicitudes y datos en RegisterServlet [nombre de usuario y contraseña]

(3) Después de que RegisterServlet recibe la solicitud y los datos, llama a la capa de Servicio para completar el guardado de la información del usuario.

(4) En la capa de Servicio, debe escribir la clase UserService e implementar el método de registro en la clase. Debe determinar si el usuario ya existe. Si no, completar el guardado de los datos del usuario.

(5) En la interfaz UserMapper, declare dos métodos, uno es consultar la información del usuario según el nombre de usuario y el otro es guardar la información del usuario.

(6) Si el guardado en la clase UserService tiene éxito, devolverá verdadero, si falla, devolverá falso y los datos se devolverán a la capa web.

(7) Después de que la capa web obtenga el resultado, si devuelve verdadero, lo solicitará 注册成功y lo reenviará a la página de inicio de sesión. Si devuelve falso, lo solicitará 用户名已存在y lo reenviará a la página de registro.

  1. Implementación

(1) Complete el contenido del material de referencia del código de la capa Dao
(2) Escriba el código de la capa de servicio

public class UserService {
    
    
    //1.使用工具类获取SqlSessionFactory
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    /**
     * 注册方法
     * @return
     */
    public boolean register(User user){
    
    
        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取UserMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //4. 判断用户名是否存在
        User u = mapper.selectByUsername(user.getUsername());

        if(u == null){
    
    
            // 用户名不存在,注册
            mapper.add(user);
            sqlSession.commit();//提交事务;
        }
        sqlSession.close();//关闭

        return u ;

    }
}

(3) Complete la escritura del código de la página y la capa web
(3.1) Modifique el contenido de Register.html a Register.jsp

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎注册</title>
    <link href="css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
    <div class="reg-content">
        <h1>欢迎注册</h1>
        <span>已有帐号?</span> <a href="login.jsp">登录</a>
    </div>
    <form id="reg-form" action="/brand-demo/registerServlet" method="post">

        <table>
            <tr>
                <td>用户名</td>
                <td class="inputs">
                    <input name="username" type="text" id="username">
                    <br>
                    <span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
                </td>
            </tr>
            <tr>
                <td>密码</td>
                <td class="inputs">
                    <input name="password" type="password" id="password">
                    <br>
                    <span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
                </td>
            </tr>

            <tr>
                <td>验证码</td>
                <td class="inputs">
                    <input name="checkCode" type="text" id="checkCode">
                    <img src="imgs/a.jpg">
                    <a href="#" id="changeImg">看不清?</a>
                </td>
            </tr>
        </table>
        <div class="buttons">
            <input value="注 册" type="submit" id="reg_btn">
        </div>
        <br class="clear">
    </form>
</div>
</body>
</html>

(3.2)Escribir Servlet de Registro

package com.itheima.web;

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    
    
    private UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        //2. 调用service 注册
        boolean flag = service.register(user);
        //3. 判断注册成功与否
        if(!flag){
    
    
            //注册功能,跳转登陆页面
            request.setAttribute("register_msg","注册成功,请登录");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
    
    
            //注册失败,跳转到注册页面

            request.setAttribute("register_msg","用户名已存在");
            request.getRequestDispatcher("/register.jsp").forward(request,response);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3.3) La información de error devuelta por el fondo debe mostrarse en la página y es necesario modificar Register.jsp.

修改前:<span id="username_err" class="err_msg" style="display:none">用户名不太受欢迎</span>
修改后:<span id="username_err" class="err_msg">${register_msg}</span>

(3.4) Si el registro se realiza correctamente, la información de éxito debe mostrarse en la página de inicio de sesión, por lo que login.jsp también debe modificarse.

修改前:<div id="errorMsg">${login_msg}</div>
修改后:<div id="errorMsg">${login_msg} ${register_msg}</div>

(3.5) Modifique login.jsp y cambie la dirección de salto de registro a Register.jsp

修改前:<a href="register.html">没有账号?</a>
修改后: <a href="register.jsp">没有账号?</a>

(3.6) Inicie la prueba y acceda al navegador. http://localhost:8080/brand-demo/login.jsp
Si la información del usuario registrado ya existe:
Insertar descripción de la imagen aquí
Si la información del usuario registrado no existe, el registro es exitoso:
Insertar descripción de la imagen aquí

6 、Visualización del código de verificación

  1. análisis de la demanda

Mostrar código de verificación: muestra la imagen del código de verificación y haz clic para cambiar.
Insertar descripción de la imagen aquí
La generación del código de verificación se implementa a través de clases de herramientas. Para clases de herramientas específicas, consulta
04-资料\1. 登录注册案例\CheckCodeUtil.java

Escriba el método principal en esta clase de herramienta para realizar pruebas:

public static void main(String[] args) throws IOException {
    
    
    //生成验证码的图片位置
    OutputStream fos = new FileOutputStream("d://a.jpg");
    //checkCode为最终验证码的数据
    String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, fos, 4);
    System.out.println(checkCode);
}

Luego de generar el código de verificación, podemos saber:

  • El código de verificación es una imagen generada usando código Java.
  • La función del código de verificación: evitar que la máquina se registre automáticamente y ataque al servidor
  1. Implementar análisis de procesos.

Insertar descripción de la imagen aquí
(1) La interfaz envía una solicitud a CheckCodeServlet

(2) Después de que CheckCodeServlet recibe la solicitud, genera una imagen del código de verificación y escribe la imagen en el front-end utilizando el flujo de salida del objeto Respuesta.

Pensando: ¿Cómo escribir imágenes en el navegador frontal?

(1) Ya existe una clase de herramienta en Java para generar imágenes de código de verificación. En la clase de prueba, la imagen solo se genera en el disco. (2) Se utiliza el proceso
de generación del disco OutputStream流. Cómo generar esta imagen en el ¿página?
(3) Anteriormente en Al escribir Reponseun objeto, tiene un método para obtener su flujo de salida de bytes. getOutputStream()
(4) En resumen, podemos cambiar el objeto de flujo escrito en el disco a un Responseflujo de bytes para completar la respuesta de la imagen al Interfaz.

  1. Implementación

(1) Modifique Register.jspla página y obtenga la imagen del código de verificación en segundo plano.

           <tr>
                <td>验证码</td>
                <td class="inputs">
                    <input name="checkCode" type="text" id="checkCode">
                    <img id="checkCodeImg" src="/brand-demo/checkCodeServlet">
                    <a href="#" id="changeImg">看不清?</a>
                </td>
            </tr>

            <script>
                document.getElementById("changeImg").onclick = function () {
                    //路径后面添加时间戳的目的是避免浏览器进行缓存静态资源
                    document.getElementById("checkCodeImg").src = "/brand-demo/checkCodeServlet?"+new Date().getMilliseconds();
                }
            </script>

(2) Escriba la clase CheckCodeServlet para recibir solicitudes y generar códigos de verificación.

package com.itheima.web;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 生成验证码
        ServletOutputStream os = response.getOutputStream();
        String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);
         // 存入Session
        HttpSession session = request.getSession();
        session.setAttribute("checkCodeGen",checkCode);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

Ejecute el código: puede ver que 看不清la imagen cambiará cuando hagamos clic
Insertar descripción de la imagen aquí

7. Código de verificación-verificación

  1. necesidad
  • Determine si el código de verificación generado por el programa es el mismo que el código de verificación ingresado por el usuario, de lo contrario se bloqueará el registro.

  • La imagen del código de verificación para acceder y enviar el formulario de registro esdos vecessolicitud, por lo que el código de verificación generado por el programa debe almacenarse en la sesión
    Insertar descripción de la imagen aquí
    Pensando: ¿Por qué los datos del código de verificación deberían almacenarse en la sesión?

  • Generar el código de verificación y verificar el código de verificación son dos solicitudes. Aquí, los datos deben compartirse entre las dos solicitudes en una sesión.

  • El código de verificación pertenece a la categoría de datos de seguridad, por lo que seleccionamos Sesión para almacenar los datos del código de verificación.

  1. Implementar análisis de procesos.

Insertar descripción de la imagen aquí
(1) Al generar el código de verificación en CheckCodeServlet, almacene los datos del código de verificación en el objeto Sesión

(2) La interfaz envía el código de verificación y los datos de registro al fondo y los entrega a la clase RegisterServlet

(3) Después de que la clase RegisterServlet recibe la solicitud y los datos, contiene un código de verificación, que se compara con el código de verificación en la sesión.

(4) Si son consistentes, se completará el registro. Si son inconsistentes, se mostrará un mensaje de error.

  1. Implementación

(1) Modificar CheckCodeServletla clase y almacenar el código de verificación en Sessionel objeto

package com.itheima.web;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 生成验证码
        ServletOutputStream os = response.getOutputStream();
        String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);

        // 存入Session
        HttpSession session = request.getSession();
        session.setAttribute("checkCodeGen",checkCode);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(2) En RegisterServlet, obtenga sessionel código de verificación de la página y el objeto, y compárelo.

package com.itheima.web;

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    
    
    private UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        // 获取用户输入的验证码
        String checkCode = request.getParameter("checkCode");

        // 程序生成的验证码,从Session获取
        HttpSession session = request.getSession();
        String checkCodeGen = (String) session.getAttribute("checkCodeGen");

        // 比对,忽略大小写
        if(!checkCodeGen.equalsIgnoreCase(checkCode)){
    
    

            request.setAttribute("register_msg","验证码错误");
            //跳转
            request.getRequestDispatcher("/register.jsp").forward(request,response);

            // 不允许注册
            return;
        }

        //2. 调用service 注册
        boolean flag = service.register(user);
        //3. 判断注册成功与否
        if(!flag){
    
    
            //注册功能,跳转登陆页面
            request.setAttribute("register_msg","注册成功,请登录");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
    
    
            //注册失败,跳转到注册页面

            request.setAttribute("register_msg","用户名已存在");
            request.getRequestDispatcher("/register.jsp").forward(request,response);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

Ejecute el programa: http://localhost:8080/brand-demo/login.jsp
Al completar el código de verificación incorrectamente:
Insertar descripción de la imagen aquí
Al completar el código de verificación correctamente:
Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_52223770/article/details/127672324
Recomendado
Clasificación