[Crazy God Talks Java] Notas detalladas de JavaWeb Introducción al combate práctico (completo)

@[toc]7

1. Conceptos básicos

1.1 Prefacio

desarrollo web:

  • web, es decir, página web, www.baidu.com·
  • web estática
    • html, css
    • ¡Los datos disponibles para que todos los vean nunca cambian!
  • web dinámica
    • Taobao, casi todos los sitios web;
    • Los datos proporcionados a todos siempre cambiarán y todos ven información diferente en diferentes momentos y en diferentes lugares.
    • Pila de tecnología: Servlet/JSP, ASP, PHP

1.2 Aplicación web Aplicación web:

Programas que brindan acceso al navegador;

  • a.html, b.html... múltiples recursos web: el mundo exterior puede acceder a estos recursos web y proporcionar servicios al mundo exterior;
  • Cualquier página o recurso al que pueda acceder existe en una computadora en algún lugar del mundo.
  • URL
  • Este recurso web unificado se colocará en la misma carpeta, aplicación web > Tomcat: servidor
  • Una aplicación web consta de varias partes (web estática, web dinámica)
    • html,css,js
    • jsp, servlet
    • programa java
    • paquete de frasco
    • Archivo de configuración (Propiedades)

Una vez escrito el programa de aplicación web, si desea proporcionarlo para acceso externo, debe utilizar un servicio para administrarlo de manera uniforme.

1.3 Web estática

  • * .htm, * .html son el fondo de los usuarios de la red. Si estas cosas siempre existen en el servidor, podemos leerlas directamente y solicitar la red;
  • imagen.png
  • Desventajas de la web estática
    • Las páginas web no se pueden actualizar dinámicamente y todos los usuarios ven la misma página.
      • Imagen de carrusel, haga clic en efectos especiales: pseudodinámico
      • JavaScript [En el desarrollo real, es el que más se usa]
      • VBScript
    • No puede interactuar con la base de datos (los datos no se pueden conservar y los usuarios no pueden interactuar)

1.4 Web dinámica

La página se mostrará dinámicamente y "el efecto de visualización de la página web varía de persona a persona"
imagen.png
Desventajas:

  • Hay un error al agregar recursos web dinámicos al servidor. Necesitamos reescribir nuestro programa en segundo plano y volver a publicarlo;
    • Ventajas del mantenimiento en tiempo de inactividad:
  • Las páginas web se pueden actualizar dinámicamente y no todos los usuarios verán la misma página.
  • Puede interactuar con la base de datos (persistencia de datos: registro, información del producto, información del usuario...)
    imagen.png

2. servidor web

2.1 Explicación técnica

ÁSPID:

  • Microsoft: el más antiguo y popular en China es ASP;
  • ·Script VB integrado, ASP+COM en HTML;
  • ·En el desarrollo ASP, básicamente cada página tiene varias líneas de código comercial y la página es extremadamente confusa.
  • ·¡Altos costes de mantenimiento!
  • C#
  • IIS

PHP:

  • La velocidad de desarrollo de PHP es muy rápida, sus funciones son muy potentes, multiplataforma y el código es muy simple (70%, WP)
  • No se pueden transportar grandes cantidades de tráfico (limitaciones)

jSP/Servlet:
B/S; navegación y servidor C/S: cliente y servidor

  • La arquitectura B/S promovida principalmente por Sun Company
  • Basado en lenguaje Java (todas las grandes empresas, o algunos componentes de código abierto, están escritos en Java)
  • Puede soportar el impacto de las tres cuestiones importantes;
  • La sintaxis es como ASP, ASP->JSP, fortaleciendo la fuerza del mercado;

2.2 servidor web

El servidor es una operación pasiva, utilizada para procesar algunas de las solicitudes del usuario y brindarle información de respuesta;
ES Microsoft; ASP., el Tomcat
que viene con Windows está orientado a la programación de Baidu: Tomcat es la Apache Software Foundation (Apache Software Foundation) Un proyecto central en el proyecto de Yakarta, las últimas especificaciones de Servlet y JSP siempre se pueden reflejar en Tomcat. Debido a que Tomcat tiene tecnología avanzada, rendimiento estable y es gratuito, es muy querido por los entusiastas de Lava y ha sido favorecido por algunos software. desarrolladores reconocidos y convertidos en un popular servidor de aplicaciones web. El servidor Tomcat es un servidor de aplicaciones web de código abierto y gratuito. Es un servidor de aplicaciones liviano. Se usa comúnmente en sistemas pequeños y medianos y en situaciones donde no hay muchos usuarios de acceso simultáneo. Es la primera opción para desarrollar y depurar JSP. programas. Para un principiante en Java web, es la mejor opción. Tomcat ejecuta páginas JSP y Serlets. Después de que la última versión de Tornct 9.0 haya estado funcionando durante 3 a 5 años, puede intentar escribir un servidor Tomcat a mano; descargue Tomcat:

imagen.png





  1. Instalar o descomprimir
  2. Comprender los archivos de configuración y la estructura de directorios
  3. ¿Qué hace esta cosa?

3 、 gato

3.1 Instalar Tomcat Tomcat

Sitio web oficial: http://tomcat.apache.org/
imagen.png
imagen.png

3.2 Inicio y configuración de Tomcat

Función de carpeta:
imagen.png
imagen.png
Prueba de acceso: http://localhost:8080/
Posibles problemas:

  1. Las variables de entorno Java no están configuradas
  2. Problema de bloqueo: es necesario configurar la compatibilidad
  3. Problema de código confuso: configuraciones en el archivo de configuración

Puede modificar java.util.logging.ConsoleHandler.encoding = GBK en conf/logging.properties para resolver el problema confuso (no recomendado)

3.3 Configuración

imagen.png
Número de puerto de inicio configurable

  • El número de puerto predeterminado de Tomcat es: 8080
  • mysql:3306
  • http:80
  • https:443
<Connector port="8081" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />

Nombre de host configurable

  • El nombre de host predeterminado es: localhost->127.0.0.1
  • La ubicación de almacenamiento predeterminada de la aplicación del sitio web es: webapps
<Host name="www.qinjiang.com"  appBase="webapps"
    unpackWARs="true" autoDeploy="true">
// name 默认是loaclhost, 改了之后,需要去host里面改DNS映射关系

Pregunta difícil de la entrevista: ¡
dígame cómo acceder al sitio web!

  1. Ingrese un nombre de dominio; presione Enter
  2. Compruebe si existe esta asignación de nombre de dominio en el archivo de configuración C:\Windows\System32\drivers\etc\hosts de esta máquina;
    1. Sí: devuelve directamente la dirección IP correspondiente, en esta dirección está el programa web al que necesitamos acceder, al que se puede acceder directamente.
    2. No: Vaya al servidor DNS para buscar, si lo encuentra, regresará, si no se puede encontrar, regresará si no se puede encontrar;
      imagen.png

4. Puedes configurar variables de entorno (opcional)

3.4 Publicar un sitio web

Si no lo sabes, imítalo primero.

  • Coloque el sitio web que escribió en la carpeta de la aplicación web especificada (webapps) en el servidor (Tomcat) y podrá acceder a él.

La estructura que debe tener un sitio web

--webapps :Tomcat服务器的web目录
    -ROOT
    -kuangstudy :网站的目录名
    	-WEB-INF
    		-classes : java程序
        	-lib:web应用所依赖的jar包
        	-web.xml :网站配置文件
        -index.html 默认的首页
        -static 
        	-css
        	-js
        	-img
        	-.....

Protocolo HTTP: Entrevista
con Maven: herramienta de compilación

  • Paquete de instalación de Maven

Empezando con los servlets

  • ¡Hola Mundo!
  • Principio de configuración del servlet

4、HTTP

4.1 ¿Qué es HTTPHTTP?

(Protocolo de transferencia de hipertexto) es un protocolo simple de solicitud-respuesta que generalmente se ejecuta sobre TCP.

  • Texto: html, cadena,…
  • Hipertexto: imágenes, música, vídeos, posicionamiento, mapas...
  • Puerto:80

HTTPS: seguro

4.2 Dos eras

  • http1.0
    • HTTP/1.0: después de que el cliente puede conectarse al servidor web, solo puede obtener un recurso web y desconectarse
  • http2.0
    • HTTP/1.1: una vez que el cliente puede conectarse al servidor web, puede obtener múltiples recursos web.

4.3 Solicitud HTTP

  • Cliente – Solicitud – Servidor

Baidu:

Request URL:https://www.baidu.com/   请求地址
Request Method:GET    get方法/post方法
Status Code:200 OK    状态码:200
Remote(远程) Address:14.215.177.39:443

Accept:text/html  
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9    语言
Cache-Control:max-age=0
Connection:keep-alive
1. Línea de solicitud
  • Método de solicitud en la línea de solicitud: GET
  • Método de solicitud: Obtener, Publicar, ENCABEZAR, BORRAR, PONER, TRACT...
    • get: la solicitud puede contener relativamente pocos parámetros, el tamaño es limitado y el contenido de los datos se mostrará en la barra de direcciones URL del navegador. No es seguro, pero es eficiente.
    • Publicación: no hay límite en los parámetros que la solicitud puede llevar, y no hay límite en el tamaño. El contenido de los datos no se mostrará en la barra de direcciones URL del navegador. Es seguro, pero no eficiente.
2. Encabezado del mensaje
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.

4.4 Respuesta HTTP

  • Servidor – Respuesta….Cliente

Baidu:

Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip    编码
Content-Type:text/html   类型  
1. Órgano de respuesta
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
2. Código de estado de respuesta

200: Solicitud de respuesta exitosa 200
3xx: Solicitud de redirección · Redirección: Vas a la nueva ubicación que te di;
4xx: Recurso no encontrado 404 · El recurso no existe;
5xx: Error de código del servidor 500 502: Error de puerta de enlace
Preguntas comunes en la entrevista:
¿Qué experimentó cuando ingresó la dirección en la barra de direcciones de su navegador y presionó Enter cuando se mostró la página?

5、Maven

¿Por qué debería aprender esta tecnología?

  1. En el desarrollo web Java, se necesita utilizar una gran cantidad de paquetes jar y los importamos manualmente;
  2. ¿Cómo puedo hacer que algo importe y configure automáticamente este paquete jar por mí?

¡De esto nació Maven!

5.1 Herramienta de gestión de arquitectura de proyectos Maven

¡Actualmente lo estamos usando para facilitar la importación de paquetes jar!
La idea central de Maven: el acuerdo es mayor que la configuración

  • Hay restricciones, no las violes.

Maven estipulará cómo debes escribir nuestro código Java y debes seguir esta especificación;

5.2 Descargar e instalar Maven

Sitio web oficial:
imagen.png
después de descargarlo, descomprímalo;

5.3 Configurar variables de entorno

Configure la siguiente configuración en las variables de entorno de nuestro sistema:

  • El directorio bin bajo el directorio M2_HOME maven
  • MAVEN_HOME directorio maven
  • Configure %MAVEN_HOME%\bin en la ruta del sistema

imagen.png
imagen.png
Pruebe si Maven se ha instalado correctamente y asegúrese de que debe configurarse.

5.4 Imagen de la nube de Alibaba

  • Espejos: espejos
  • Función: Acelerar nuestras descargas
  • En China se recomienda utilizar la imagen de Alibaba Cloud
<mirror>
  <id>nexus-aliyun</id>  
  <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>  
  <name>Nexus aliyun</name>  
  <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
</mirror>

5.5 Almacén local

Almacén local, almacén remoto; cree un almacén local: localRepository

在D:\java\Maven\apache-maven-3.8.7\ 新建一个空目录,maven-repo

<localRepository>D:\java\Maven\apache-maven-3.8.7\maven-repo</localRepository>

5.6 Maven de implementación de IDEA

imagen.png
Tenga en cuenta que debe configurarlo dos veces. ¡La ubicación de configuración es como se muestra en la imagen de arriba!
imagen.png
Al crear un proyecto por primera vez, use un generador. Al
imagen.png
imagen.png
crear un proyecto por segunda vez, use un generador.
imagen.png
Como se muestra a continuación, main-java coloca el código fuente de Java, resources coloca el archivo de configuración y test-java prueba (¡la convención es mayor que la configuración!)
imagen.png
y lo reconstruye usando el constructor. En un proyecto maven, aparecerá el siguiente paquete de aplicación web. Haga
imagen.png
clic derecho para marcarlo como el directorio del código fuente, o puede configurar la estructura del proyecto. -Configuración del módulo.

5.7 Configurar Tomcat en IDEA

Archivo actual en la esquina superior derecha, desplácese hacia abajo para seleccionar el archivo de configuración, + un servidor local Tomcan.
imagen.png
Intente no establecer la configuración de ruta a continuación en /De lo contrario, se eliminará el directorio raíz original en Tomcat.
imagen.png
Luego inícielo y podrá acceder a hola mundo.
imagen.png

archivo 5.8 pom

pom.xml es el archivo de configuración principal de maven

<!--Maven版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <!--这里是刚才配置的GAV-->
  <groupId>org.example</groupId>
  <artifactId>test2</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--Packaging 项目的打包方式
  jar: java 应用
  war: JavaWeb 应用
  -->
  <packaging>war</packaging>

  <name>test2 Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  <!--项目依赖-->
  <dependencies>
    <!--具体依赖的jar包-->
		<!--高级之处在于自动下载对应的jar包-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
			<!--作用域 -->
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <!--配置-->
  <properties>
    <!--编码版本 -->
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <!--项目的默认编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <build>
    <finalName>test2</finalName>
  </build>
</project>

Dado que Maven tiene más convenciones que configuración, podemos encontrar el problema de que el archivo de configuración que escribimos no se puede exportar ni tener efecto Solución: Operación IDEA: el árbol de directorios en la esquina superior derecha puede mostrar
imagen.png
la estructura de directorios dependientes.Crtl+Alt+Shift+U

IDEA utiliza el constructor Maven. La versión predeterminada del web.xml generado es 2.3, que debe ser coherente con Tomcat, por lo que debe copiar el contenido web.xml del directorio ROOT en Tomcat. Actualmente es 5.0.

<?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"
  metadata-complete="true">

</web-app>

6、Servlet

6.1 Introducción a Servlet

  • Servlet es una tecnología utilizada por Sun para desarrollar web dinámica.
  • Sun proporciona una interfaz en estas API llamada: Servlet. Si desea desarrollar un programa Servlet, solo necesita completar dos pequeños pasos:
    • Escribe una clase para implementar la interfaz Serlet.
    • Implemente las clases Java desarrolladas en el servidor web.

El programa Java que implementa la interfaz Servlet se llama Servlet.

6.2、HolaServlet

Interfaz Serlvet Sun tiene dos clases de implementación predeterminadas: HttpServlet, GenericServled

  1. Cree un proyecto Maven ordinario y elimine el directorio src que contiene. En el futuro, construiremos Moudel en este proyecto; este proyecto vacío es el proyecto principal de Maven;
  2. Comprensión de los proyectos padre e hijo de Maven;
    habrá en el proyecto padre
<modules>
  <module>servlet-01</module>
</modules>

Habrá subproyectos

<parent>
  <artifactId>javaweb-02-servlet</artifactId>
  <groupId>com.kuang</groupId>
  <version>1.0-SNAPSHOT</version>
</parent>

Java en el proyecto principal puede ser utilizado directamente por subproyectos

son extends father
  1. Optimización del entorno Maven
    1. Modifique web.xml para que sea el más reciente
    2. Completa la estructura maven
<?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"
  metadata-complete="true">

</web-app>
  1. Escribir un programa servlet
    1. Escribe una clase normal.
    2. Implemente la interfaz de Servlet, aquí heredamos directamente HttpServlet
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>org.example</groupId>
    <artifactId>javaweb-02-servlet</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>servlet-01</module>
        <module>servlet-02</module>
    </modules>
    
    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        
         <!--这个是Tomcat10用的-->
         <!--https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
        <!--<dependency>-->
        <!--    <groupId>jakarta.servlet</groupId>-->
        <!--    <artifactId>jakarta.servlet-api</artifactId>-->
        <!--    <version>6.0.0</version>-->
        <!--</dependency>-->


    </dependencies>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>
package org.Martin.servlet;

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

public class HelloServlet extends HttpServlet {
    
    

    //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter(); //响应流
        writer.print("Hello,Serlvet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        doGet(req, resp);
    }
}
  1. Escribir mapeo de servlet
    Por qué se necesita el mapeo: escribimos un programa JAVA, pero se debe acceder a él a través de un navegador, y el navegador necesita conectarse al servidor web, por lo que
    debemos es un navegador La ruta a la que puede acceder el servidor;
<!--注册Servlet-->
<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. Nota al configurar Tomcat
    : simplemente configure la ruta (del proyecto) para el lanzamiento del proyecto; si no hay contenido en la implementación, actualice Maven a la derecha
  2. Comienza la prueba, ¡vale!
    imagen.png

6.3 Principio del servlet

El servidor web llama al servlet. Después de recibir la solicitud del navegador, el servidor web:
imagen.png

6.4 Problema de mapeo

  1. Un servlet puede especificar una ruta de mapeo
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. Un servlet puede especificar múltiples rutas de mapeo
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello4</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello5</url-pattern>
</servlet-mapping>
  1. Un servlet puede especificar una ruta de mapeo universal
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  1. Ruta de solicitud predeterminada
<!--默认请求路径,直接顶替了Index它成为了首页-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>
  1. Especifique algunos sufijos o prefijos, etc...
<!--可以自定义后缀实现请求映射
注意点,*前面不能加项目映射的路径
例如不能这样: /*.txt /hello/*.txt
-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>*.qinjiang</url-pattern>
</servlet-mapping>
  1. Problema de prioridad:
    se especifica que la ruta de mapeo inherente tiene la máxima prioridad. Si no se puede encontrar, se utilizará la solicitud de procesamiento predeterminada;
<!-- 访问/hello优先级高,不会进入error界面 -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>myError</servlet-name>
    <servlet-class>org.Martin.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>myError</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

6.5、ServletContexto

Cuando se inicia el contenedor web, creará un objeto ServletContext correspondiente para cada programa web, que representa la aplicación web actual;

1. Compartir datos

Los datos que guardo en este servlet los puedo obtener en otro servlet;

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

        //this.getInitParameter()   初始化参数
        //this.getServletConfig()   Servlet配置
        //this.getServletContext()  Servlet上下文
        ServletContext context = this.getServletContext();

        String username = "秦疆"; //数据
        context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username

    }

}
public class GetServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        ServletContext servletContext = this.getServletContext();

        // 获取HelloServlet保存的
        String username = (String) servletContext.getAttribute("username");

        resp.getWriter().print(username);
    }
}

<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.Martin.servlet.HelloServlet</servlet-class>
</servlet>    
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>gets</servlet-name>
  <servlet-class>com.Martin.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>gets</servlet-name>
  <url-pattern>/gets</url-pattern>
</servlet-mapping>

Pruebe los resultados del acceso; primero acceda a hello y luego el acceso tendrá efecto. De lo contrario, hello no envió datos y no se podrá acceder a get.

2. Obtener parámetros de inicialización
<!--配置一些web应用初始化参数-->
<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>

<servlet>
    <servlet-name>gp</servlet-name>
    <servlet-class>com.Martin.servlet.GetParaServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>gp</servlet-name>
    <url-pattern>/gp</url-pattern>
</servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    ServletContext context = this.getServletContext();
    String url = context.getInitParameter("url");
    resp.getWriter().print(url);
}
3. Solicitar reenvío

Recursos de GP reenviados a mi propia página

	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        ServletContext context = this.getServletContext();
        System.out.println("进入了ServletDemo04");
        //RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
        //requestDispatcher.forward(req,resp); //调用forward实现请求转发;
        context.getRequestDispatcher("/gp").forward(req,resp);
    }

imagen.png
4. Leer archivos de recursos
Properties

  • Cree nuevas propiedades en el directorio java (esto requiere configuración)
  • Crear nuevas propiedades en el directorio de recursos.

Encontrado: Todos están empaquetados en la misma ruta: clases de destino, comúnmente llamamos a esta ruta classpath:
imagen.pngimagen.png
Idea: Se necesita una secuencia de archivos

username=admin	
password=root
public class GetPropertiesServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 在打包之后的target下的项目路径
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");

        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");

        resp.getWriter().print(username+password);
    }
}

El acceso a la prueba está bien;

6.6、Respuesta HTTPServlet

El servidor web recibe la solicitud http del cliente, para esta solicitud crea un
objeto HttpServletRequest que representa la solicitud y un HttpServletResponse que representa la respuesta;

  • Si desea obtener los parámetros solicitados por el cliente: busque HttpServletRequest
  • Si desea responder al cliente con alguna información: busque HttpServletResponse
1. Clasificación sencilla

Método responsable del envío de datos al navegador.

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

Método responsable de enviar encabezados de respuesta al navegador.

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String varl,long var2);
void addDateHeader(String var1,long var2);
void setHeader(String var1,String var2);
void addHeader(String var1,String var2);
void setIntHeader(String var1,int var2);
void addIntHeader(String varl,int var2);

código de estado de respuesta
imagen.png
imagen.png

2. Aplicaciones comunes
  1. Enviar un mensaje al navegador (he estado hablando de eso desde siempre, así que no hablaré más de eso)
  2. descargar archivo
    1. Para obtener la ruta al archivo descargado
    2. ¿Cuál es el nombre del archivo descargado?
    3. Configurar formas de permitir que el navegador admita la descarga de lo que necesitamos
    4. Obtenga el flujo de entrada del archivo descargado
    5. Crear buffer
    6. Obtener el objeto OutputStream
    7. Escriba la secuencia FileOutputStream en el búfer
    8. Utilice OutputStream para enviar los datos del búfer al cliente.
package org.Martin.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 1. 要获取下载文件的路径
        String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/ctfshow.png");
        // String realPath = "E:\\Martin_Code\\java\\javaweb\\javaweb-02-servlet\\Response-01\\target\\Response-01\\WEB-INF\\classes\\ctfshow.png";
        System.out.println("文件路径:"+realPath);
        // 2. 下载的文件名是啥?
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3. 设置想办法让浏览器能够支持下载我们需要的东西
        // "Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"))
        resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
        // 4. 获取下载文件的输入流
        FileInputStream fis = new FileInputStream(realPath);
        // 5. 创建缓冲区
        int len=0;
        byte[] buffer = new byte[1024];
        // 6. 获取OutputStream对象
        ServletOutputStream outputStream = resp.getOutputStream();
        // 7. 将FileOutputStream流写入到bufer缓冲区
        while ((len=fis.read(buffer))!=-1){
    
    
            // 8. 使用OutputStream将缓冲区中的数据输出到客户端!
            outputStream.write(buffer,0,len);
        }
        outputStream.close();
        fis.close();
    }
}

3. Función de código de verificación

¿Cómo se produjo la verificación?

  • Implementación frontal
  • La implementación de back-end requiere el uso de la clase de imagen de Java para producir una imagen.
package org.Martin.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

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

        // 如何让浏览器每5秒刷新一次
        resp.setHeader("refresh","3");

        // 在内存中创建一个图片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        // 得到图片
        Graphics2D g = (Graphics2D) image.getGraphics(); //笔
        // 设置图片背景颜色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,80,20);
        // 给图片写数据
        g.setColor(Color.BLUE);
        g.setFont(new Font("null",Font.BOLD,20));
        g.drawString(makeNum(),0,20);

        // 告诉浏览器这个请求用图片的方式打开
        resp.setContentType("image/png");
        // 网站存在缓冲,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        // 把图片写给浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());


    }

    // 生成随机数
    private String makeNum(){
    
    
        Random random = new Random();
        // 最大值,4位数
        String num = random.nextInt(9999) + "";
        StringBuffer sb = new StringBuffer();
        // 不足四位数,补充0
        for (int i = 0; i < 4-num.length(); i++) {
    
    
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }
}

<servlet>
  <servlet-name>ImageServlet</servlet-name>
  <servlet-class>com.kuang.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Imageservlet</servlet-name>
  <url-pattern>/img</url-pattern>
</servlet-mapping>
4. Implementar la redirección

imagen.png
Escenarios comunes:

  • Inicio de sesión de usuario
void sendRedirect(String var1) throws IOException;

prueba:

public class RedirectServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 跳转到哪里
        /*
        resp.setHeader("Location","./image");
        resp.setStatus(302);
         */
        // resp.sendRedirect(req.getContextPath()+"/image");
        resp.sendRedirect("./image");

    }
}

imagen.png
imagen.png
índice.jsp

<html>
  <body>
    <h2>Hel1o World!</h2>

    <%--这里超交的路径,需要寻找到项目的路径--%>
      <%--${pageContext. request, contextPath}代表当前的项目--%>
        <form action="${pageContext. request.contextPath}/login" method="get">
          用户名: <input type="text" name="username"> <br>
          密码: <input type="password" name="password"> <br>
          <input type="submit">
        </form>
      </body>
      </html>

SolicitudPrueba.java

public class RequestTest extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("进入请求");
        // 处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username+password);

        // 重定向到成功,注意路径
        resp.sendRedirect(req.getContextPath()+"/success.jsp");
        // resp.sendRedirect("./success.jsp");
    }
}

Redirigir página Success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>success</h1>
</body>
</html>

configuración web.xml

<servlet>
  <servlet-name>requset</servlet-name>
  <servlet-class>com. kuang. servlet. RequestTest</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>requset</servlet-name>
  <url-pattern>/login</url-pattern>
</servlet-mapping>

Importar paquetes jar dependientes

<dependencies>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
</dependencies>

6.7、Solicitud HTTPServlet

HttpServletRequest representa la solicitud del cliente. El usuario accede al servidor a través del protocolo Http. Toda la información de la solicitud HTTP se encapsulará en HttpServletRequest. A través de este método HttpServletRequest se obtiene toda la información del cliente;
imagen.png
imagen.png

1. Obtener parámetros y solicitar reenvío

imagen.png
Cree su propia clase y necesite heredar la clase HttpServlet

public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req. setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
        for (String hobby : req.getParameterValues("hobby")) {
    
    
            System.out.println(hobby);
        }

        // 请求转发 会保留项目地址  所以不用加这个 req.getContextPath()
        req.getRequestDispatcher("/success.jsp").forward(req,resp);

        System.out.println(req.getPathInfo()); // null
        System.out.println(req.getContextPath()); // /Request_01_war 项目的根路径
        System.out.println(req.getServletPath()); // /login 自己这个类的路径

    }
}

6.8 ¡La diferencia entre redirección y reenvío de solicitudes!

imagen.png

// 重定向,需要根目录的地址
response.sendRedirect(req.getContextPath()+"/success.jsp");


// 请求转发, 会保留项目的根目录地址,不用加requset.getContextPath()来获取根目录地址
requset.getRequestDispatcher("/success.jsp").forward(req,resp);

// 前端获取项目的根地址
${
    
    pageContext.request.contextPath}

7、Cookie、Sesión

7.1 Conversación

Sesión : El usuario abre un navegador, hace clic en muchos hipervínculos, accede a múltiples recursos web y cierra el navegador. Este proceso se puede llamar sesión; sesión con estado:
un compañero ha estado en el aula y sabremos cuándo llega al aula. clase la próxima vez. Este compañero de clase, que ha estado aquí antes, lo llama una conversación con estado: ¿
cómo puedes demostrar que eres un estudiante de Xikai?
conduces hacia el oeste

  1. Factura Xikai te entregará la factura
  2. Registro escolar Xikai marca que has estado aquí

¿Cómo puede un sitio web demostrar que has estado allí?
Servidor de cliente

  1. El servidor envía una carta al cliente, y el cliente puede traer la carta consigo la próxima vez que visite el servidor; cookie
  2. El servidor registra que has venido y te emparejaré la próxima vez que vengas; seesion

7.2 Dos técnicas para guardar sesiones

Galleta

  • Tecnología del cliente (respuesta, solicitud)

sesión

  • Tecnología de servidor, utilizando esta tecnología, ¿se puede guardar la información de la sesión del usuario? ¡Podemos poner información o datos en Session!

Común común: después de iniciar sesión en el sitio web, no es necesario que vuelva a iniciar sesión la próxima vez. ¡Iniciará sesión directamente la segunda vez que lo visite!

7.3、Cookie

imagen.png

  1. Obtener información de cookies a partir de la solicitud
  2. El servidor responde a la cookie del cliente.
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie

代码:
public class CookieDemo01  extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 解决中文乱码,解决不了!!
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // 写数据
        PrintWriter writer = resp.getWriter();

        // Cookie从服务器获取
        Cookie[] cookies = req.getCookies(); // 可能存在多个,是一个数组

        // 判断是否是第一次登录
        boolean flag = false;
        for (Cookie cookie : cookies) {
    
    
            if (cookie.getName().equals("lastTime")){
    
    
                flag=true;
                // cookie.getValue();是一个字符串
                // 字符串变整数时间戳
                long lastTime = Long.parseLong(cookie.getValue());
                Date date = new Date(lastTime);
                writer.write("Not first: ");
                writer.write(date.toLocaleString());
            }
        }
        if (!flag){
    
    
            writer.write("The First");
        }

        // 服务器更新Cookie  name value
        // System.currentTimeMillis()一个时间戳
        Cookie cookie = new Cookie("lastTime",String.valueOf(System.currentTimeMillis()));
        cookie.setMaxAge(24*60*60); //有效期
        resp.addCookie(cookie);
    }
}

Cookies: generalmente se almacenan en el directorio local de usuarios AppData;
¿existe un límite superior para las cookies en un sitio web? Hablemos de detalles

  • Una cookie sólo puede guardar una información;
  • Un sitio web puede enviar múltiples cookies al navegador, almacenando hasta 20 cookies;
  • El tamaño de las cookies está limitado a 4kb;
  • Límite del navegador de 300 cookies

Eliminar las cookies;

  • Si no establece un período de validez, cierre el navegador y caducará automáticamente;
  • Establezca el período de validez en 0;

codificar descodificar:

URLEncoder.encode("秦疆","utf-8");
URLDecoder.decode(cookie.getValue(),"UTF-8");

7.4 Sesión (puntos clave)

imagen.png
¿Qué es la sesión?

  • El servidor creará un objeto Seesion para cada usuario (navegador);
  • Una Seesion ocupa un navegador, mientras el navegador no esté cerrado, esta sesión existe;
  • Después de que el usuario inicia sesión, se puede acceder a todo el sitio web. –> Guardar información del usuario; guardar información del carrito de compras…

escenas a utilizar:

  • Guarde la información de un usuario que haya iniciado sesión;
  • Información del carrito de compras;
  • Guardamos datos que se utilizan con frecuencia en todo el sitio web en Session;

Usar sesión:

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

        //解决乱码
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        // 得到Session
        HttpSession session = req.getSession();

        // session.removeAttribute("name"); 删除session中的name
        // session.invalidate(); 清除session,当浏览器再次访问,会生成新的session,应用于用户手动注销
        
        // 给Session 存信息 可以存一个对象
        session.setAttribute("name","Martin");
        session.setAttribute("Person",new Person("person.name",3));

        // 得到Session 的信息
        System.out.println(session.getAttribute("name"));
        System.out.println(session.getAttribute("Person"));

        // 获取Session ID
        String sessionId = session.getId();

        // 判断是不是新的
        if (session.isNew()){
    
    
            resp.getWriter().write("new: "+sessionId);
        }else {
    
    
            resp.getWriter().write("old: "+sessionId);
        }

        //Session创建的时候做了什么?
        //传递了一个Cookie, name="JSESSIONID" value=session.getId()
    }
}

Caducidad automática de la sesión: configuración web.xml

<!--设置Session默认的失效时间-->
<session-config>
  <!--15分钟后Session自动失效,以分钟为单位-->
  <session-timeout>15</session-timeout>
</session-config>

7.5 Comparación entre Cookie y Sesión

  • Galleta
    • Obtener galletareq.getCookies()
    • Agregue una matriz de cookies de pares clave-valor:resp.addCookies(cookie)
    • Obtener el contenido de la cookie:cookie.getName();cookie.getValue();
  • Sesión
    • Obtener sesiónreq.getSession()
    • Agregue el par clave-valor del objeto Sesiónsession.setAttribute(name,value)
    • Obtenga el contenido de la sesión: session.getAttribute(name)
      | Cookie | Sesión | Token |
      | — | — | — |
      | Cuando el usuario inicia sesión por primera vez:
  1. Cliente envía solicitud
  2. El servidor configura la cookie y la envía al cliente.
  3. El cliente acepta la cookie, la guarda localmente y la trae consigo la próxima vez que visite.
  4. El servidor acepta la cookie y devuelve los datos del usuario correspondiente (Limitaciones de la cookie: solo se puede guardar con pares clave-valor, lo cual es ineficiente e introduce Sesión) | Cada vez que
    el usuario inicia sesión:
  5. Cliente envía solicitud
  6. El servidor establece un ID de sesión único y lo devuelve al cliente (usando cookies)
  7. El cliente lleva el SessionID cada vez que visita (en forma de cookie)
  8. Debido a que el servidor guarda el ID de sesión de todos los usuarios, la forma de distinguir a cada usuario es comparar. El servidor guarda demasiados datos y aparece Token |
    cuando el usuario inicia sesión:
  9. Cliente envía solicitud
  10. El servidor genera un Token y lo devuelve al usuario. Este token almacena el ID de usuario cifrado y se utiliza para distinguir a los usuarios.
  11. El cliente lleva el Token cada vez que accede
  12. El servidor acepta el token, lo descifra y luego obtiene el ID de usuario para distinguir a los usuarios; no utiliza la sesión para guardar una gran cantidad de datos de ID de sesión, lo que ahorra espacio
    |

Cookie: solo puede guardar pares clave-valor, baja eficiencia. Se introduce sesión. Session
: SessionID es el valor hash de una cadena de pares clave-valor, que es altamente eficiente (el servidor usa SessionID para compararlos entre sí para verificar y distinguir usuarios), pero todos están almacenados en el servidor. El servidor es muy incómodo, por lo que se introduce Token Token
: guarde el ID de usuario cifrado en el cliente y el servidor lo descifre para obtener el ID de usuario, lo cual es muy fácil para el servidor.

8、JSP

8.1 ¿Qué es JSP?

Páginas del servidor Java: las páginas del lado del servidor Java, también como los servlets, se utilizan en tecnologías web dinámicas.
La característica más importante:

  • Escribir JSP es como escribir HTML
  • la diferencia:
    • HTML solo proporciona datos estáticos a los usuarios
    • El código JAVA se puede incrustar en páginas JSP para proporcionar a los usuarios datos dinámicos;

8.2 Principios JSP

Idea: ¿Cómo se ejecuta JSP?

  • No hay problemas a nivel de código.
  • El funcionamiento interno del servidor es que hay un directorio de trabajo en Tomcat; si usa Tomcat en IDEA, se producirá un directorio de trabajo en Tomcat en IDEA.

C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat
La dirección de mi computadora: ¡ C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat\16a6cd02-6b09-4de3-a7fa-601b94a708b7\work\Catalina\localhost\Request_01_war\org\apache\jspLa página de descubrimiento se convirtió en un programa Java!
imagen.png
El navegador envía una solicitud al servidor, no importa a qué recurso se acceda, ¡en realidad está accediendo al Servlet!
¡El JSP eventualmente se convertirá en una clase Java!

JSP es esencialmente un servlet encapsulado.

//初始化
public void _jspInit() {
    
    

}
//销毁
public void _jspDestroy() {
    
    
}
//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response){
    
    
}

  1. Solicitud de sentencia
  2. objetos incorporados
  3. Código agregado antes de generar la página.
  4. ¡Podemos usar los objetos anteriores directamente en páginas JSP!
final javax.servlet.jsp.PageContext pageContext;  //页面上下文
javax.servlet.http.HttpSession session = null;    //session
final javax.servlet.ServletContext application;   //applicationContext
final javax.servlet.ServletConfig config;         //config
javax.servlet.jsp.JspWriter out = null;           //out
final java.lang.Object page = this;               //page:当前
HttpServletRequest request;                       //请求
HttpServletResponse response;                     //响应
response.setContentType("text/html");       //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
                                          null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;

imagen.png
En la página JSP,
siempre que sea código JAVA, se generará intacto;
si es código HTML, se convertirá a: ¡ out.write("<html>\r\n");dicho formato y se enviará al front-end!

8.3 Sintaxis básica de JSP

Cualquier idioma tiene su propia gramática y JAVA la tiene. Como aplicación de la tecnología Java, JSP tiene su propia sintaxis expandida (¡conócela, conócela!), ¡y todas las sintaxis de Java son compatibles!

expresión JSP
<%-- 注释 --%> 
<%= 变量或者表达式%>  //作用:用来将程序的输出,输出到客户端
<%= new java.util.Date()%>
fragmento de script jsp
<%--jsp脚本片段--%>

<%
 int sum = 0;
 for (int i = 1; i <=100 ; i++) {
   sum+=i;
 }
 out.println("<h1>Sum="+sum+"</h1>");
%>

Reimplementación de fragmentos de script.

<%
 int x = 10;
 out.println(x);
%>
<p>这是一个JSP文档</p>
<%
 int y = 2;
 out.println(y);
%>

<hr>
 
 
<%--在代码嵌入HTML元素--%>
<%
 for (int i = 0; i < 5; i++) {
%>
 <h1>Hello,World  <%=i%> </h1>
<%
 }
%>
declaración JSP
<%!
 static {
   System.out.println("Loading Servlet!");
 }

 private int globalVar = 0;

 public void kuang(){
   System.out.println("进入了方法Kuang!");
 }
%>

Declaración JSP: ¡se compilará en la clase Java generada por JSP! ¡Otros se generarán en el método _jspService!
imagen.png
En JSP, ¡simplemente incruste código Java!

<%%>  java代码片段
<%= %> 表达式的值
<%! %> jsp声明
 
<%--注释--%>

Los comentarios JSP no se mostrarán en el cliente, ¡el HTML sí!

8.4 Instrucciones JSP

<%@page args.... %>
<%@include file=""%>

<%--@include会将两个页面合二为一,参数不能冲突--%>

<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>

<hr>


<%--jSP标签
   jsp:include:拼接页面,本质还是三个,参数互不影响
   --%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

8.5, 9 objetos integrados

  • PageContext almacena cosas
  • Solicitar guardar algo
  • Respuesta
  • La sesión salva cosas
  • La aplicación [ServletContext] guarda cosas
  • configuración 【ServletConfig】
  • afuera
  • página, no es necesario entender
  • excepción
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器

imagen.png
solicitud: el cliente envía una solicitud al servidor. Los datos generados son inútiles después de que el usuario los ha leído. Por ejemplo: ¡las noticias son inútiles después de que el usuario las ha leído!
Sesión: el cliente envía una solicitud al servidor y el usuario puede utilizar los datos generados durante un tiempo, como un carrito de compras; aplicación: el cliente
envía una solicitud al servidor y los datos generados son utilizados por uno usuario, pero otros usuarios aún pueden usarlo. Por ejemplo: datos de chat;

8.6, etiquetas JSP, etiquetas JSTL, expresiones EL

<!-- JSTL表达式的依赖 -->
<dependency>
  <groupId>javax.servlet.jsp.jstl</groupId>
  <artifactId>jstl-api</artifactId>
  <version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
</dependency>

Expresión EL: ${ }

  • recuperar datos
  • realizar operaciones
  • Obtener objetos comunes utilizados en el desarrollo web.

etiquetas JSP

<%--jsp:include--%>
 
<%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%>

<jsp:forward page="/jsptag2.jsp">
   <jsp:param name="name" value="kuangshen"></jsp:param>
   <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

/jsptag2.jsp
<%=request.getParameter("name")%>

El uso de la biblioteca de etiquetas JSTL de expresión
JSTL es para compensar las deficiencias de las etiquetas HTML, personaliza muchas etiquetas y podemos usarlas. ¡Las funciones de las etiquetas son las mismas que las del código Java! Es necesario introducir la etiqueta
de formato de la biblioteca de etiquetas Etiqueta
SQL Etiqueta
XML
Etiqueta principal (parte maestra)
imagen.png
Pasos de uso de la biblioteca de etiquetas JSTL

  • Introduce el taglib correspondiente.<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  • Usa el método
  • Tomcat también necesita introducir el paquete jstl; de lo contrario, se informará un error: error de análisis JSTL

c: si

<head>
  <title>Title</title>
</head>
<body>
<h4>if测试</h4>

<hr>

<form action="coreif.jsp" method="get">
  <%--
  EL表达式获取表单中的数据
  ${param.参数名}
  --%>
  <input type="text" name="username" value="${param.username}">
  <input type="submit" value="登录">
</form>

<%--判断如果提交的用户名是管理员,则登录成功--%>
<!--   test是接受的值,var返回的boolean,cout输出value的值 -->
<c:if test="${param.username=='admin'}" var="isAdmin">
  <c:out value="管理员欢迎您!"/>
</c:if>

<%--自闭合标签--%>
<c:out value="${isAdmin}"/>

</body>

c:elija c:cuándo

<body>

<%--定义一个变量score,值为85--%>

<c:set var="score" value="55"/>

  <c:choose>
    <c:when test="${score>=90}">
      你的成绩为优秀
    </c:when>
    <c:when test="${score>=80}">
      你的成绩为一般
    </c:when>
    <c:when test="${score>=70}">
      你的成绩为良好
    </c:when>
    <c:when test="${score<=60}">
      你的成绩为不及格
    </c:when>
  </c:choose>

</body>

c: para cada uno

<%
    ArrayList<String> peoples = new ArrayList<>();
    peoples.add(0,"张三");
    peoples.add(1,"李四");
    peoples.add(2,"王五");
    peoples.add(3,"赵六");
    peoples.add(4,"田六");
    request.setAttribute("list",peoples);
%>


<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin,   哪里开始
end,     到哪里
step,   步长
--%>
    
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>

<hr>

<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/> <br>
</c:forEach>

9、JavaBean

La clase de entidad
JavaBean tiene una forma específica de escribir:

  • Debe haber un constructor sin parámetros.
  • Las propiedades deben ser privadas.
  • Debe haber métodos get/set correspondientes;

Generalmente se utiliza para asignar ORM a campos de bases de datos;
ORM: Mapeo relacional de objetos

  • Tabla—>Clase
  • Campos–>Propiedades
  • Registro de fila---->Objeto

mesa de personas

identificación nombre edad DIRECCIÓN
1 Qinjiang No. 1 3 Xi'an
2 Qinjiang No. 2 18 Xi'an
3 Qinjiang No. 3 100 Xi'an
class People{
    
    
    private int id;
    private String name;
    private int id;
    private String address;
}

class A{
    
    
    new People(1,"秦疆1号",3"西安");
    new People(2,"秦疆2号",3"西安");
    new People(3,"秦疆3号",3"西安");
}

imagen.png

10. Arquitectura MVC de tres niveles

  • Qué es MVC: vista de modelo Modelo de controlador, vista, controlador
    • Modelo: correspondencia correspondiente entre tablas y clases de bases de datos
    • Ver: página jsp
    • Controlador: servlet

10.1 Arquitectura anterior

imagen.png
Los usuarios acceden directamente a la capa de control, y la capa de control puede operar directamente la base de datos;

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护  
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的!
程序猿调用
↑
JDBC (实现该接口)
↑
Mysql Oracle SqlServer ....(不同厂商)

10.2 Arquitectura MVC de tres niveles

imagen.png
Modelo

  • Procesamiento empresarial: lógica empresarial (servicio)
  • Capa de persistencia de datos: CRUD (Dao - objeto de persistencia de datos)

Vista

  • mostrar datos
  • Proporcione un enlace para iniciar una solicitud de Servlet (a, formulario, img...)

Controlador (servlet)

  • Recibir solicitud del usuario: (req: parámetros de solicitud, información de sesión...)
  • Entréguelo a la capa empresarial para procesar el código correspondiente.
  • Controla el salto de la vista.
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库

11. Filtro (punto clave)

Por ejemplo, la tecnología del marco de seguridad de Shiro se implementa mediante
Filter: Filter, que se utiliza para filtrar datos del sitio web;

  • Manejar caracteres chinos confusos
  • Autenticación de inicio de sesión….

(Por ejemplo, para filtrar malas palabras en Internet, me jodo 0-0)
imagen.png
Pasos de desarrollo del filtro:

  1. Paquete de guía
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
    </dependencies>
  1. Escribe un filtro
    1. No hagas el paquete de guía equivocado (nota)

imagen.png
Implemente la interfaz Filter y reescriba el método correspondiente.

package org.example.filter;

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

public class CharacterEncodingFilter implements Filter {
    
    

    //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("CharacterEncodingFilter初始化");
    }

    //Chain : 链
       /*
       1. 过滤中的所有代码,在过滤特定请求的时候都会执行
       2. 必须要让过滤器继续执行
           chain.doFilter(request,response);
        */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        System.out.println("CharacterEncodingFilter执行前....");
        chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
        System.out.println("CharacterEncodingFilter执行后....");
    }

    //销毁:web服务器关闭的时候,过滤器会销毁
    public void destroy() {
    
    
        System.out.println("CharacterEncodingFilter销毁");
    }
}

  1. Configurar filtro en web.xml
<filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>org.example.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <!--只要是下方的请求,就会经过过滤器-->
  <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

12. Oyente

Implementar una interfaz de escucha; (hay n tipos de escuchas)

  1. Escriba un oyente para implementar la interfaz del oyente... el paquete jar dependienteimagen.png
  2. Registrar oyente en web.xml
  3. ¡Depende de la situación si usarlo!
//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {
    
    

    //创建session监听: 看你的一举一动
    //一旦创建Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se) {
    
    
        ServletContext ctx = se.getSession().getServletContext();

        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
    
    
            onlineCount = new Integer(1);
        }else {
    
    
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }

    //销毁session监听
    //一旦销毁Session就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se) {
    
    
        ServletContext ctx = se.getSession().getServletContext();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
    
    
            onlineCount = new Integer(0);
        }else {
    
    
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }


    /*
Session销毁:
1. 手动销毁  getSession().invalidate();
2. 自动销毁
*/
}
<!--注册监听器-->
<listener>
  <listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
当前在线人数:<%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>

13. Aplicaciones comunes de filtros y oyentes.

Oyente: utilizado a menudo en programación GUI;

public class TestPanel {
    
    
    public static void main(String[] args) {
    
    
        Frame frame = new Frame("中秋节快乐");  //新建一个窗体
        Panel panel = new Panel(null); //面板
        frame.setLayout(null); //设置窗体的布局

        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,255)); //设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,0)); //设置背景颜色

        frame.add(panel);

        frame.setVisible(true);

        //监听事件,监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
    
    
            @Override
            public void windowClosing(WindowEvent e) {
    
    
                super.windowClosing(e);
            }
        });

    }
}

¡Solo después de que el usuario inicie sesión podrá ingresar a la página de inicio! Después de que el usuario cierra sesión, no puede ingresar a la página de inicio.

  1. Después de que el usuario inicie sesión, coloque los datos del usuario en Sesison.
  2. Al ingresar a la página de inicio, es necesario determinar si el usuario ha iniciado sesión; requisito: ¡implementado en el filtro!

imagen.png

// error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>没有权限或者密码错误</h1>
<a href="./login.jsp"> 请登录</a>
</body>
</html>

// login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
${pageContext.request.contextPath}
<form action="${pageContext.request.contextPath}/login" method="get">
    请输入用户名:<input type="text" name="username">
    <input type="submit">
</form>
</body>
</html>

// success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
<a href="${pageContext.request.contextPath}/logout">注销</a>
</body>
</html>
public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        System.out.println("进入LoginServlet->doGet");
        System.out.println(req.getContextPath());
        // 如果是管理员登录,跳转到成功页面
        if (req.getParameter("username").equals("admin")){
    
    
            // 设置Session
            req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
            // 重定向需要获得根目录
            resp.sendRedirect(req.getContextPath()+"/security/success.jsp");
        }else{
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }
}

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

        System.out.println("LogoutServlet->doGet");
        // 销毁Session 或者 移除其中一个属性(建议后者,开销小
        Object userSession = req.getSession().getAttribute("USER_SESSION");

        if (userSession!=null){
    
    
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect(req.getContextPath()+"/login.jsp");
        }else {
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }
}

public class LogoutFilter implements Filter {
    
    
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        Object userSession = req.getSession().getAttribute("USER_SESSION");
        if (userSession==null){
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
        filterChain.doFilter(req,resp);
    }
    public void destroy() {
    
    
    }
}
<!--登录验证-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>org.example.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>logout</servlet-name>
    <servlet-class>org.example.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>logout</servlet-name>
    <url-pattern>/logout</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>LogoutFilter</filter-name>
    <filter-class>org.example.filter.LogoutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LogoutFilter</filter-name>
    <url-pattern>/security/*</url-pattern>
</filter-mapping>

14、JDBC

¿Qué es JDBC: conexión Java a la base de datos?
imagen.png
Requiere soporte para paquetes jar:

  • java.sql
  • javax.sql
  • mysql-connecter-java… controlador de conexión (debe importarse)

Configuración del entorno experimental

CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
  id INT PRIMARY KEY,
  `name` VARCHAR(40),
  `password` VARCHAR(40),
  email VARCHAR(60),
  birthday DATE
);

INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','[email protected]','2000-01-01');


SELECT	* FROM users;

Importar dependencias de bases de datos

<!--mysql的驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

Conexión a la base de datos en IDEA:
imagen.png
pasos fijos de JDBC:

  1. Controlador de carga
  2. Conectarse a la base de datos, representar la base de datos.
  3. Enviar declaración de objeto SQL a la base de datos: CRUD
  4. Escribir SQL (diferente SQL según negocio)
  5. Ejecutar SQL
  6. Cerrar la conexión (abrir primero y luego cerrar)
package org.example;

import java.sql.*;

public class TestJdbc {
    
    
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
        Statement statement = connection.createStatement();

        //4.编写SQL
        String sql = "select * from users";

        //5.执行查询SQL,返回一个 ResultSet  : 结果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
    
    
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        rs.close();
        statement.close();
        connection.close();
    }
}

SQL precompilado

package org.example;
import java.sql.*;

public class TestJdbc2 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        String sql = "insert into  users(id, name, password, email, birthday) values (?,?,?,?,?);";

        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        // 注意这里第一个是ID,有没有自增,或者用不用赋值
        preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1;
        preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
        preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
        preparedStatement.setString(4,"[email protected]");//给第四个占位符? 的值赋值为1;
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());

        //5.执行SQL
        int i = preparedStatement.executeUpdate();

        if (i>0){
    
    
            System.out.println("插入成功@");
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        preparedStatement.close();
        connection.close();
    }
}

¡O todo
tiene éxito o todo fracasa!
Principio ACID: garantizar la seguridad de los datos.

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务

转账:
A:1000
B:1000

A(900)   --100-->   B(1100) 


Dependencias de pruebas unitarias Junit

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
</dependency>

El simple uso
de la anotación @Test solo es efectivo en los métodos. Siempre que se agregue el método con esta anotación, se puede ejecutar directamente.
¿Usar anotaciones para la reflexión?

import org.junit.Test;

@Test
public void test(){
    
    
    System.out.println("Hello");
}

imagen.png
Es rojo cuando falla:
imagen.png
construye un ambiente

CREATE TABLE account(
    id INT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(40),
    money FLOAT
    );

INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
package org.example;


import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestJdbc3 {
    
    

    @Test
    public void test() {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        Connection connection = null;

        //1.加载驱动
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.连接数据库,代表数据库
            connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
            //int i = 1/0;

            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
    
    
            try {
    
    
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
    
    
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                connection.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

15. SMBMS (proyecto de gestión de supermercados)

Experimento del proyecto SMBMS en los episodios 30 ~ 37

Aplicación extendida

1. Carga de archivos

En las aplicaciones web, las funciones de carga y descarga de archivos son funciones muy comunes, hoy implementaremos las funciones de carga y descarga de archivos en JavaWeb.

1. Preparación

Para cargar archivos, el navegador envía el archivo al servidor en forma de secuencia durante el proceso de carga.
Generalmente, elige utilizar el componente de carga de archivos de la herramienta de código abierto common-fileupload de Apache.
common-fileupload depende del paquete common-io, por lo que también debe descargar este paquete.
Descargue el último paquete jar
https://mvnrepository.com/artifact/commons-io/commons-io
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
imagen.png

2. Introducción a las clases de uso.

[Notas sobre la carga de archivos]

  1. Para garantizar la seguridad del servidor, los archivos cargados deben colocarse en un directorio al que el mundo exterior no pueda acceder directamente, como el directorio WEB-INF.
  2. Para evitar la sobrescritura de archivos, se debe generar un nombre de archivo único para el archivo cargado.
  3. Para limitar el tamaño máximo de los archivos cargados.
  4. Puede limitar el tipo de archivos cargados y, al recibir el nombre del archivo cargado, determinar si el nombre del sufijo es legal.

[Explicación detallada de las clases que se utilizarán]
ServletFileUpload es responsable de procesar los datos del archivo cargado y encapsular cada elemento de entrada en el formulario en un objeto FileItem . Cuando se utiliza el objeto ServletFileUpload para analizar la solicitud, se requiere el objeto DiskFileItemFactory . Por lo tanto, necesitamos construir el objeto DiskFileItemFactory antes del análisis y establecer la propiedad fileItemFactory del objeto ServletFileUpload mediante el método de construcción del objeto ServletFileUpload o el método setFileItemFactory()== .

Clase de elemento de archivo

Debe haber name <input type="file" name="filename">
un formulario en la entrada de la página HTML. Si contiene una entrada de carga de archivos, el atributo enctype de este formulario debe establecerse en multipart/form-data.
Si el tipo de formulario del navegador es multipart/form-data, si desea para obtener datos en el lado del servidor, Para pasar la secuencia.


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <%--通过表单上传
      get:上传文件大小有限制
      post: 上传文件大小没有限制--%>
      <form action = "" method = "post" enctype="multipart/form-data">
        上传用户:<input type="text" name="username"><br/>
        <p><input type="file" name="file1"></p>
        <p><input type="file" name="file2"></p>
        <p><input type="submit"> |<input type="reset"></p>
      </form>
  </body>
</html>

[Introducción a los métodos comunes]

//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();

//getFieldName方法用于返回表单标签name属性的值。
String getFieldName();

//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();

//getName方法用于获得文件上传字段中的文件名。
String getName();

//以流的形式返回上传文件的数据内容。
InputStream getInputStream();

//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();
ServletFileUpload

ServletFileUpload es responsable de procesar los datos del archivo cargado y encapsular cada elemento de entrada en el formulario en un objeto FileItem . Utilice su método parseRequest (HttpServletRequest) para encapsular los datos enviados a través de cada etiqueta HTML en el formulario en un objeto FileItem y luego use Returned en la forma de lista de lista. Este método es simple y fácil de usar para cargar archivos.

3. Escritura de código

SubirServlet

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;

public class UploadServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request, response);
    }

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

        try {
    
    
            //判断上传的文件是普通的表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
    
    
                return;//如果是普通文件,我们可以直接返回
            } //如果通过了这个if,说明我们的表单是带文件上传的;

            //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
    
    //如果目录不存在,创建这样一个目录;
                uploadFile.mkdir();
            }

            //临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File file = new File(tmpPath);
            if (!file.exists()) {
    
    //如果目录不存在,创建这样一个目录;
                file.mkdir();
            }

            //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
            //但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 commons-io组件;

            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            //2.获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3.处理上传的文件
            String msg = uploadParseRequest(upload, request, uploadPath);

            //servlet请求转发消息
            request.setAttribute("msg",msg);
            request.getRequestDispatcher("msg.jsp").forward(request,response);

        } catch (FileUploadException e) {
    
    
            e.printStackTrace();
        }

    }


    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
    
    
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
        factory.setSizeThreshold(1024 * 1024); //缓存区大小为1M
        factory.setRepository(file);//临时目录的保存目录,需要一个File
        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
    
    
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件上传进度;
        upload.setProgressListener(new ProgressListener() {
    
    
            @Override
            //pBytesRead:已经读取到的文件大小
            //pContentLength : 文件大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
    
    
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });

        //处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //设置总共能够上传文件的大小
        //1024 = 1kb * 1024 = 1M * 10 = 10M
        upload.setSizeMax(1024 * 1024 * 10);

        return upload;
    }


    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath)
    throws FileUploadException, IOException {
    
    

        String msg = "";

        //3.把前端请求解析,封装成一个FileItem对象
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
    
    
            if (fileItem.isFormField()){
    
     //判断上传的文件是普通的表单还是带文件的表单
                //getFieldName指的是前端表单控件的name;
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8"); //处理乱码
                System.out.println(name+":"+value);
            }else {
    
     //判断它是上传的文件

                //=======================处理文件===============================//

                //拿到文件名字
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名:"+uploadFileName);

                if (uploadFileName.trim().equals("")||uploadFileName==null){
    
    
                    continue;
                }

                //获得上传的文件名  /images/girl/paojie.png
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
                //获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                /*
如果文件后缀名 fileExtName 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对。
*/

                System.out.println("文件信息 [件名:"+fileName+"---文件类型"+fileExtName+"]");

                //可以使用UUID(唯一识别的通用码),保证文件名唯一;
                //UUID.randomUUID(),随机生一个唯一识别的通用码;
                String uuidPath = UUID.randomUUID().toString();

                //=======================处理文件完毕===============================//

                //存到哪? uploadPath
                //文件真实存在的路径 realPath
                String realPath =   uploadPath+"\\"+uuidPath;
                //给每个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()){
    
    
                    realPathFile.mkdir();
                }

                //=======================存放地址完毕===============================//

                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流
                //realPath = 真实的文件夹;
                //差了一个文件; 加上输出文件的名字+"/"+uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath+"\\"+fileName);

                //创建一个缓冲区
                byte[] buffer = new byte[1024*1024];

                //判断是否读取完毕
                int len = 0;
                //如果大于0说明还存在数据;
                while ((len=inputStream.read(buffer))>0){
    
    
                    fos.write(buffer,0,len);
                }

                //关闭流
                fos.close();
                inputStream.close();

                msg = "文件上传成功!";
                fileItem.delete(); //上传成功,清除临时文件
                //=======================文件传输完毕===============================//
            }
        }

        return msg;
    }
}

cargar.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>文件上传</title>
    </head>
    <body>
      <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件1:<input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        <input type="submit" value="提交">
      </form>
    </body>
  </html>

msg.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>消息提示</title>
    </head>
    <body>
      ${msg}
    </body>
  </html>

web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"         
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
  http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"          
  version="4.0">    
  <servlet>         
    <servlet-name>upload</servlet-name>         
    <servlet-class>com.kuang.servlet.UploadFileServlet</servlet-class>     
  </servlet>     
  <servlet-mapping>         
    <servlet-name>upload</servlet-name>         
    <url-pattern>/upload.do</url-pattern>     
  </servlet-mapping> </web-app> 

Envío y recepción de correo electrónico

correo electrónico

Para implementar la función de correo en la red, es necesario un servidor de correo dedicado.
Estos servidores de correo son similares a las oficinas de correos de la vida real: son los principales responsables de recibir los correos entregados por los usuarios y entregarlos a los buzones de correo electrónico de los destinatarios.
Dirección del servidor SMTP : generalmente smtp.xxx.com , por ejemplo, el buzón 163 es smtp.163.com y el buzón qq es smtp.qq.com .
Para obtener una dirección de correo electrónico (dirección de correo electrónico), debe solicitarla en el servidor de correo. Por ejemplo, si queremos utilizar el buzón QQ, debemos activar la función de buzón;
imagen.png

Protocolo de transferencia

Protocolo SMTP
para enviar correos electrónicos:
normalmente llamamos servidores SMTP (servidores de envío de correo electrónico) al servidor que maneja las solicitudes SMTP (solicitudes de envío de correo electrónico) de los usuarios.
Protocolo POP3
para recibir correo:
normalmente llamamos al servidor que maneja las solicitudes pop3 del usuario (solicitudes de recepción de correo) un servidor POP3 (servidor de recepción de correo).
Principios de envío y recepción de correos electrónicos.
imagen.png

  1. Da Kuangshen se conecta al servidor Smtp a través del protocolo SMTP y luego envía un correo electrónico al servidor de correo de NetEase.
  2. El análisis de NetEase encontró que es necesario ir al servidor de correo de QQ y reenviar el correo al servidor Smtp de QQ a través del protocolo SMTP.
  3. Las tiendas QQ recibieron correos electrónicos en el espacio de la cuenta de correo electrónico [email protected]
  4. Xiaokuangshen se conecta al servidor Pop3 a través del protocolo Pop3 para recopilar correos electrónicos
  5. Recuperar correos electrónicos desde el espacio de la cuenta de correo electrónico [email protected]
  6. El servidor Pop3 enviará el correo electrónico recuperado al pequeño dios loco.

[Nota] Es posible que su dirección de destinatario, dirección de remitente y otra información sean correctas y la consola imprima la información correcta, pero no pueda recibir la información en la bandeja de entrada. Esto se debe a que es posible que el servidor de la bandeja de entrada haya rechazado el correo electrónico que envió (por ejemplo, cree que su correo electrónico es un anuncio). En este momento, es posible que se encuentre en la papelera, pero es posible que no se encuentre. La solución no es enviar contenido de correo electrónico duplicado varias veces ni intentar cambiar su bandeja de entrada.

Enviar correo electrónico usando Java

Descripción general

Utilizaremos el código para completar el envío del correo electrónico. Esto se usa ampliamente en proyectos reales. Por ejemplo, el registro requiere enviar un correo electrónico para la activación de la cuenta. Otro ejemplo es el uso de correos electrónicos para recordatorios de tareas en proyectos OA.
Enviar correo electrónico utilizando Java es muy sencillo, pero primero debe preparar la API JavaMail y el marco de activación de Java.
Obtenga dos paquetes de frascos:

  • correo.jar
  • activación.jar

JavaMail es un conjunto de paquetes de desarrollo estándar proporcionados por Sun Corporation (ahora adquirida por Oracle) para facilitar a los desarrolladores de Java implementar funciones de envío y recepción de correo electrónico en las aplicaciones. Admite algunos protocolos de correo electrónico de uso común, como SMTP mencionado anteriormente, POP3, IMAP, y MIME, etc. Cuando usamos la API de JavaMail para escribir correos electrónicos, no necesitamos considerar los detalles de implementación subyacentes del correo electrónico, solo necesitamos llamar a la clase API correspondiente en el kit de desarrollo de JavaMail.
Podemos intentar enviar primero un correo electrónico simple para asegurarnos de que la computadora pueda conectarse a la red.

  • Cree un objeto de sesión que contenga información de conexión de red para el servidor de correo.
  • Cree un objeto Mensaje que represente el contenido del correo electrónico.
  • Cree un objeto de transporte, conéctese al servidor, envíe un mensaje y cierre la conexión

Hay principalmente cuatro clases principales. Cuando escribimos un programa, si recordamos estas cuatro clases principales, será fácil escribir un programa de procesamiento de correo Java.
imagen.png

correo electrónico de texto plano

Primero, importe el buzón QQ del paquete jar al proyecto
imagen.png
para obtener los permisos correspondientes.
El buzón QQ requiere verificación de seguridad y necesitamos obtener sus permisos correspondientes;
buzón QQ–>configuración del buzón–>
imagen.png
imagen.png
código de prueba de escritura de cuenta

import com.sun.mail.util.MailSSLSocketFactory;

import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class SendEmail {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码

        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        //使用JavaMail发送邮件的5个步骤
        //创建定义整个应用程序所需的环境信息的 Session 对象

        Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    
            public PasswordAuthentication getPasswordAuthentication() {
    
    

                //发件人邮件用户名、授权码
                return new PasswordAuthentication("[email protected]", "授权码");

            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com", "[email protected]", "授权码");
        //4、创建邮件
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
        //邮件的标题
        message.setSubject("只包含文本的简单邮件");
        //邮件的文本内容
        message.setContent("你好啊!", "text/html;charset=UTF-8");
        //5、发送邮件
        ts.sendMessage(message, message.getAllRecipients());
        ts.close();
    }
}

Correos electrónicos con imágenes y archivos adjuntos.

Primero, conozcamos dos clases y un sustantivo:
MIME (Tipo de extensión de correo de Internet multipropósito) Clase
MimeBodyPart La
clase javax.mail.internet.MimeBodyPart representa un mensaje MIME que, al igual que la clase MimeMessage, se hereda de la interfaz Part.
La clase MimeMultipart
javax.mail.internet.MimeMultipart es una subclase de implementación de la clase abstracta Multipart, que se utiliza para combinar múltiples mensajes MIME. Un objeto MimeMultipart puede contener varios objetos MimeBodyPart que representan mensajes MIME.
imagen.png
Crear un correo electrónico que contenga imágenes incrustadas
En el ejemplo anterior, se usó HTML o contenido de texto sin formato solo, pero a veces necesitamos mostrar algunas imágenes en línea en texto sin formato, por lo que necesitamos combinar texto sin formato e imágenes incrustadas. Simplemente guárdelo por separado en MimeBodyPart y luego guárdelo en un objeto Mimemultipart.

import com.sun.mail.util.MailSSLSocketFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;

public class SendImageEmail {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码

        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        //使用JavaMail发送邮件的5个步骤
        //1、创建定义整个应用程序所需的环境信息的 Session 对象
        Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    
            public PasswordAuthentication getPasswordAuthentication() {
    
    
                //发件人邮件用户名、授权码
                return new PasswordAuthentication("[email protected]", "授权码");
            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com", "[email protected]", "授权码");
        //4、创建邮件
        //创建邮件
        MimeMessage message = new MimeMessage(session);
        // 设置邮件的基本信息
        //发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
    //邮件标题
    message.setSubject("带图片的邮件");
    // 准备邮件数据
    // 准备图片数据
    MimeBodyPart image = new MimeBodyPart();
    DataHandler dh = new DataHandler(new FileDataSource("src/resources/bz.jpg"));
    image.setDataHandler(dh);
    image.setContentID("bz.jpg");
    // 准备正文数据
    MimeBodyPart text = new MimeBodyPart();
    text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件", "text/html;charset=UTF-8");
    // 描述数据关系
    MimeMultipart mm = new MimeMultipart();
    mm.addBodyPart(text);
    mm.addBodyPart(image);
    mm.setSubType("related");
    //设置到消息中,保存修改
    message.setContent(mm);
    message.saveChanges();
    //5.发送邮件
    ts.sendMessage(message, message.getAllRecipients());
    ts.close();
    }
}

Envíe correos electrónicos complejos con imágenes y archivos adjuntos

import com.sun.mail.util.MailSSLSocketFactory;



 



import javax.activation.DataHandler;



import javax.activation.FileDataSource;



import javax.mail.*;



import javax.mail.internet.InternetAddress;



import javax.mail.internet.MimeBodyPart;



import javax.mail.internet.MimeMessage;



import javax.mail.internet.MimeMultipart;



import java.security.GeneralSecurityException;



import java.util.Properties;



 



public class SendFileMail {
    
    



    public static void main(String[] args) throws MessagingException, GeneralSecurityException {
    
    



 



        //创建一个配置文件保存并读取信息



        Properties properties = new Properties();



 



        //设置qq邮件服务器



        properties.setProperty("mail.host","smtp.qq.com");



        //设置发送的协议



        properties.setProperty("mail.transport.protocol","smtp");



        //设置用户是否需要验证



        properties.setProperty("mail.smtp.auth", "true");



 



 



        //=================================只有QQ存在的一个特性,需要建立一个安全的链接



        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可



        MailSSLSocketFactory sf = new MailSSLSocketFactory();



        sf.setTrustAllHosts(true);



        properties.put("mail.smtp.ssl.enable", "true");



        properties.put("mail.smtp.ssl.socketFactory", sf);



 



        //=================================准备工作完毕



 



        //1.创建一个session会话对象;



        Session session = Session.getDefaultInstance(properties, new Authenticator() {
    
    



            @Override



            protected PasswordAuthentication getPasswordAuthentication() {
    
    



                return new PasswordAuthentication("[email protected]", "授权码");



            }



        });



 



        //可以通过session开启Dubug模式,查看所有的过程



        session.setDebug(true);



 



 



        //2.获取连接对象,通过session对象获得Transport,需要捕获或者抛出异常;



        Transport tp = session.getTransport();



 



        //3.连接服务器,需要抛出异常;



        tp.connect("smtp.qq.com","[email protected]","授权码");



 



        //4.连接上之后我们需要发送邮件;



        MimeMessage mimeMessage = imageMail(session);



 



        //5.发送邮件



        tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());



 



        //6.关闭连接



        tp.close();



 



    }



 



 



    public static MimeMessage imageMail(Session session) throws MessagingException {
    
    



 



        //消息的固定信息



        MimeMessage mimeMessage = new MimeMessage(session);



 



        //邮件发送人



        mimeMessage.setFrom(new InternetAddress("[email protected]"));



        //邮件接收人,可以同时发送给很多人,我们这里只发给自己;



        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));



        mimeMessage.setSubject("我也不知道是个什么东西就发给你了"); //邮件主题



 



 



        /*



        编写邮件内容



        1.图片



        2.附件



        3.文本



         */



 



        //图片



        MimeBodyPart body1 = new MimeBodyPart();



        body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/yhbxb.png")));



        body1.setContentID("yhbxb.png"); //图片设置ID



 



        //文本



        MimeBodyPart body2 = new MimeBodyPart();



        body2.setContent("请注意,我不是广告<img src='cid:yhbxb.png'>","text/html;charset=utf-8");



 



        //附件



        MimeBodyPart body3 = new MimeBodyPart();



        body3.setDataHandler(new DataHandler(new FileDataSource("src/resources/log4j.properties")));



        body3.setFileName("log4j.properties"); //附件设置名字



 



        MimeBodyPart body4 = new MimeBodyPart();



        body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));



        body4.setFileName(""); //附件设置名字



 



        //拼装邮件正文内容



        MimeMultipart multipart1 = new MimeMultipart();



        multipart1.addBodyPart(body1);



        multipart1.addBodyPart(body2);



        multipart1.setSubType("related"); //1.文本和图片内嵌成功!



 



        //new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体



        MimeBodyPart contentText =  new MimeBodyPart();



        contentText.setContent(multipart1);



 



        //拼接附件



        MimeMultipart allFile =new MimeMultipart();



        allFile.addBodyPart(body3); //附件



        allFile.addBodyPart(body4); //附件



        allFile.addBodyPart(contentText);//正文



        allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed;



 



 



        //放到Message消息中



        mimeMessage.setContent(allFile);



        mimeMessage.saveChanges();//保存修改



 



 



        return mimeMessage;



 



    }



 



}

JavaWebEnviar correo electrónico

Muchos sitios web ahora ofrecen funciones de registro de usuarios. Por lo general, después de un registro exitoso, recibiremos un correo electrónico del sitio web de registro. El contenido del correo electrónico puede incluir información como nuestro nombre de usuario y contraseña registrados, así como un hipervínculo para activar la cuenta. Hoy también implementaremos dicha función. Después de que el usuario se registre exitosamente, la información de registro del usuario se enviará al buzón de correo registrado del usuario en forma de correo electrónico. Para implementar la función de envío de correo electrónico, debemos usar JavaMail.
Código:

  1. Cree un nuevo proyecto JavaWeb, configure Tomcat y agregue paquetes jar
    imagen.png
  2. Escriba la clase de entidad de usuario correspondiente
package com.kuang.pojo;



 



public class User {
    
    



 



    private String username;



    private String password;



    private String email;



 



    public User() {
    
    



    }



 



    public User(String username, String password, String email) {
    
    



        this.username = username;



        this.password = password;



        this.email = email;



    }



 



    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;



    }



    public String getEmail() {
    
    



        return email;



    }



    public void setEmail(String email) {
    
    



        this.email = email;



    }



 



    @Override



    public String toString() {
    
    



        return "User{" +



                "username='" + username + '\'' +



                ", password='" + password + '\'' +



                ", email='" + email + '\'' +



                '}';



    }



}
  1. Página de registro frontal
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



<html>



<head>



    <title>注册</title>



</head>



<body>



 



<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">



    用户名:<input type="text" name="username"><br/>



    密码:<input type="password" name="password"><br/>



    邮箱:<input type="text" name="email"><br/>



    <input type="submit" value="注册">



</form>



 



</body>



</html>
  1. Herramientas de envío de correo electrónico
package com.kuang.utils;



 



import com.kuang.pojo.User;



import com.sun.mail.util.MailSSLSocketFactory;



 



import javax.mail.*;



import javax.mail.internet.InternetAddress;



import javax.mail.internet.MimeMessage;



import java.util.Properties;



 



public class Sendmail extends Thread {
    
    



 



    //用于给用户发送邮件的邮箱



    private String from = "[email protected]";



    //邮箱的用户名



    private String username = "[email protected]";



    //邮箱的密码



    private String password = "授权码";



    //发送邮件的服务器地址



    private String host = "smtp.qq.com";



 



    private User user;



    public Sendmail(User user){
    
    



        this.user = user;



    }



 



    //重写run方法的实现,在run方法中发送邮件给指定的用户



    @Override



    public void run() {
    
    



        try{
    
    



            Properties prop = new Properties();



            prop.setProperty("mail.host", host);



            prop.setProperty("mail.transport.protocol", "smtp");



            prop.setProperty("mail.smtp.auth", "true");



 



            // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可



            MailSSLSocketFactory sf = new MailSSLSocketFactory();



            sf.setTrustAllHosts(true);



            prop.put("mail.smtp.ssl.enable", "true");



            prop.put("mail.smtp.ssl.socketFactory", sf);



 



            //1、创建定义整个应用程序所需的环境信息的 Session 对象



            Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    



                public PasswordAuthentication getPasswordAuthentication() {
    
    



                    //发件人邮件用户名、授权码



                    return new PasswordAuthentication("[email protected]", "授权码");



                }



            });



 



            //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态



            session.setDebug(true);



 



            //2、通过session得到transport对象



            Transport ts = session.getTransport();



 



            //3、使用邮箱的用户名和授权码连上邮件服务器



            ts.connect(host, username, password);



 



            //4、创建邮件



            MimeMessage message = new MimeMessage(session);



            message.setFrom(new InternetAddress(from)); //发件人



            message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail())); //收件人



            message.setSubject("用户注册邮件"); //邮件的标题



 



            String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";



 



            message.setContent(info, "text/html;charset=UTF-8");



            message.saveChanges();



 



            //发送邮件



            ts.sendMessage(message, message.getAllRecipients());



            ts.close();



        }catch (Exception e) {
    
    



            throw new RuntimeException(e);



        }



    }



}
  1. Escriba la clase de procesamiento de servlet correspondiente.
package com.kuang.servlet;



 



import com.kuang.pojo.User;



import com.kuang.utils.Sendmail;



 



import javax.servlet.ServletException;



import javax.servlet.http.HttpServlet;



import javax.servlet.http.HttpServletRequest;



import javax.servlet.http.HttpServletResponse;



import java.io.IOException;



 



public class RegisterServlet extends HttpServlet {
    
    



    @Override



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



        try {
    
    



            //接收用户请求,封装成对象



            String username = request.getParameter("username");



            String password = request.getParameter("password");



            String email = request.getParameter("email");



            User user = new User(username,password,email);



 



            //用户注册成功之后,给用户发送一封邮件



            //我们使用线程来专门发送邮件,防止出现耗时,和网站注册人数过多的情况;



            Sendmail send = new Sendmail(user);



            //启动线程,线程启动之后就会执行run方法来发送邮件



            send.start();



 



            //注册用户



            request.setAttribute("message", "注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");



            request.getRequestDispatcher("info.jsp").forward(request, response);



        } catch (Exception e) {
    
    



            e.printStackTrace();



            request.setAttribute("message", "注册失败!!");



            request.getRequestDispatcher("info.jsp").forward(request, response);



        }



    }



 



 



    @Override



    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    



        doGet(req, resp);



    }



}
  1. Configurar web.xml
<?xml version="1.0" encoding="UTF-8"?>



<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"



         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"



         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"



         version="4.0">



    <servlet>



        <servlet-name>register</servlet-name>



        <servlet-class>com.kuang.servlet.RegisterServlet</servlet-class>



    </servlet>



    



    <servlet-mapping>



        <servlet-name>register</servlet-name>



        <url-pattern>/RegisterServlet.do</url-pattern>



    </servlet-mapping>



</web-app>
  1. Enviar página de comentarios de éxito o fracaso
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



<html>



<head>



    <title>提示信息</title>



</head>



<body>



    ${message}



</body>



</html>

¡Ejecute la prueba de Tomcat!
El correo electrónico se envió correctamente, ¡OK!

Supongo que te gusta

Origin blog.csdn.net/qq_53517370/article/details/128861163
Recomendado
Clasificación