SpringBoot+网易邮箱登录注册

news2024/12/23 9:34:22

文章目录

  • SpringBoot+网易邮箱登录注册
    • pom.xml
    • application.yml
    • sql
    • UserEmail.java
    • UserEmailMapper.java
    • UserEmailMapper.xml
    • EmailService.java
    • UserEmailService.java
    • UserEmailServiceImpl.java
    • UserEmailController.java
    • register1.html

编写前参考

SpringBoot+网易邮箱登录注册

pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sin</groupId>
    <artifactId>RedisMailMessage</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <packaging>war</packaging>

    <name>RedisMailMessage</name>

    <description>RedisMailMessage</description>

    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <!--
            邮箱业务:
                用于操作邮件功能的
         -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>
        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--
            对SpringBoot应用的监控
         -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--
            SpringBoot框架的启动器
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!--
            SpringBoot框架的测试库
         -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- Java提供的工具库 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>




    </dependencies>

    <build>
        <plugins>
            <!--
                SpringBoot应用打包为可执行的jar文件
             -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--
                单元测试的插件
                    配置为逃过运行测试
             -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo
    username: root
    password: 123456
  redis:
    # 地址
    host: 192.168.226.137
    # 端口
    port: 6379
    # 密码
    password: 123456
    # 超时时间 5000毫秒
    timeout: 5000
    jedis:
    # 连接池
      pool:
      # 连接池最小空闲连接
        min-idle: 0
      # 连接池的最大空闲连接
        max-idle: 8
      # 连接池最大阻塞等待时间(使用负数表示没有限制)
        max-wait: -1
      # 连接池最大连接数(使用负数表示没有限制)
        max-active: 8

  mail:
    # 配置SMTP服务器地址
    host: smtp.126.com
    # 配置端口号465或者25
    port: 25
    # 发送者邮箱(根据自己邮箱填写)
    username: sin8023@126.com
    #  配置密码,注意是开启POP3/SMTP的授权密码(根据自己的授权密码填写)
    password: RVJJ****NTPUEHO

    properties:
      mail:
        smtp:
          auth: true
          enable: true
          ssl:
            # 设为true时 端口号设为 465 设为false时 端口号设为25
            enable: false
          socketFactoryClass: javax.net.ssl.SSLSocketFactory
        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
        debug: true
    # 邮箱编码格式
    default-encoding: UTF-8
#  thymeleaf:
#    prefix: classpath:/templates/
#    suffix: .html
#    mode: HTML
#    encoding: utf-8
#    servlet.content-type: text/html
#    check-template-location: true  #检查模板路径是否存在
#    cache: false

# mybatis配置
mybatis:
  # 获取配置文件的地址
  mapper-locations: classpath:/mapper/*.xml
  # 获取实体类的地址
  type-aliases-package: com.sin.pojo
  configuration:
    # 开启驼峰命名
    map-underscore-to-camel-case: true

logging:
  level:
    org.mybatis: debug

sql

create table user_email
(
    id       int auto_increment primary key comment '主键id',
    name     varchar(20) character set utf8mb4 not null comment '用户名',
    password varchar(20) character set utf8mb4 not null comment '密码',
    email    varchar(20) character set utf8mb4 not null comment '邮箱',
    code_status int default 0 comment '邮箱验证状态 1 = 未注册 ,1 = 已经注册 其余数字为无效标识符'
)charset = utf8mb4;



insert into user_email(name,password,email,code_status) select email,'aaa' from user where email='123@qq.com';

insert into user_email(name,password,email,code_status) value ('admin','123456','123@qq.com',1);

select * from user_email where name = 'admin' and password = '123456' and code_status = 1;

UserEmail.java

package com.sin.pojo;


public class UserEmail {

  private long id;
  private String name;
  private String password;

  private String email;

  private int codeStatus;

  public UserEmail() {
  }

  public UserEmail(String name, String password, String email) {
    this.name = name;
    this.password = password;
    this.email = email;
  }

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  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;
  }

  public int getCode_status() {
    return codeStatus;
  }

  public void setCode_status(int codeStatus) {
    this.codeStatus = codeStatus;
  }


  @Override
  public String toString() {
    return "UserEmail{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", password='" + password + '\'' +
            ", email='" + email + '\'' +
            ", codeStatus='" + codeStatus + '\'' +
            '}';
  }
}

UserEmailMapper.java

package com.sin.mapper;

import com.sin.pojo.UserEmail;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * @createTime 2023/10/23 15:39
 * @createAuthor SIN
 * @use  数据访问层,数据访问的核心任务
 */
@Mapper
public interface UserEmailMapper {

    /**
     * 添加数据
     * @param userEmail
     * @return
     */
    int insertUserEmail(UserEmail userEmail);


    /**
     * 根据用户名进行查找数据
     * @param userEmail
     * @return
     */
    UserEmail findUserByName(String userEmail);

    /**
     * 查询所有数据
     * @return
     */
    List<UserEmail> seletctUserEmail();

    /**
     * 根据邮箱进行查询
     * @param email
     * @return
     */
    UserEmail findAllByEmail(String email);


    /**
     * 更新数据
     * @param email
     * @return
     */
    void updateCodeStatus(String email);

    /**
     * 根据邮箱查询数据
     * @param email
     * @return
     */
    UserEmail findByEmail(String email);
}

UserEmailMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sin.mapper.UserEmailMapper">
    <!--
        resultMap通过将查询结果集中的列名和Java对象中的属性名进行映射,实现了结果集的自动映射。
        同时,它还可以解决列名和属性名不匹配的问题,支持复杂类型映射,提高了查询性能。
     -->
    <resultMap id="UserMap" type="com.sin.pojo.UserEmail">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="password" column="password"/>
        <result property="email" column="email"/>
        <result property="codeStatus" column="code_status"/>
    </resultMap>

    <!-- 添加数据 -->
    <insert id="insertUserEmail" parameterType="com.sin.pojo.UserEmail">
        insert into user_email(name,password,email,code_status)

        values (#{name},#{password},#{email},#{codeStatus})
    </insert>
    <update id="updateCodeStatus"  parameterType="com.sin.pojo.UserEmail">
        update user_email set code_status = 2 where email = #{email};
    </update>

    <!-- 根据姓名密码查询数据 -->
    <select id="findUserByName" resultMap="UserMap">
        select name from user where name = #{name} and password = #{password} and code_status = 1
    </select>



    <!-- 查询所有数据 -->
    <select id="seletctUserEmail" resultMap="UserMap">
        select * from user_email
    </select>

    <!-- code_status = 1时,表明用户已经存在但未完成注册操作 -->
    <select id="findAllByEmail" resultMap="UserMap">
        select * from user_email where email = #{email} and code_status = 1
    </select>

    <!-- code_status = 2时,表明用户已经完成注册操作可以进行登录操作 -->
    <select id="findByEmail" parameterType="string"  resultMap="UserMap">
        select * from user_email where email = #{email} and code_status = 2
    </select>


</mapper>

EmailService.java

package com.sin.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

/**
 * @createTime 2023/11/21 10:18
 * @createAuthor SIN
 * @use
 */

@Service
public class EmailService {


    @Autowired(required = false)
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String userName;


    /**
     * 发送信息邮件
     * @param to 收件人
     * @param subject 邮箱标题
     * @param content 邮箱内容
     */
    public void sendMail(String to, String subject, String content) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        //邮箱发送者
        helper.setFrom(userName);
        //收件人,可以为多个收件人,收件人之间用逗号隔开
        helper.setTo(to);
        // 邮箱标题
        helper.setSubject(subject);
        // 邮箱内容
        helper.setText(content, true);
        mailSender.send(message);
    }
}

UserEmailService.java

package com.sin.service;

import com.sin.exception.EmailAlreadyExistsException;
import com.sin.pojo.UserEmail;

import javax.mail.MessagingException;
import java.util.List;

/**
 * @createTime 2023/11/20 17:25
 * @createAuthor SIN
 * @use
 */
public interface UserEmailService {


    /**
     * 添加数据
     * @param userEmail
     * @return
     */
    int insertUserEmail(UserEmail userEmail) throws MessagingException, EmailAlreadyExistsException;


    /**
     * 根据用户名进行查找数据
     * @param userEmail
     * @return
     */
    UserEmail findUserByName(String userEmail);


    /**
     * 查询所有数据
     * @return
     */
    List<UserEmail> seletctUserEmail();

    /**
     * 根据邮箱进行查询
     * @param email
     * @return
     */
    UserEmail findAllByEmail(String email);


    /**
     * 发送验证码
     * @return
     */
    String sendCode(String email) throws MessagingException;


    /**
     * 获取验证码
     * @return
     */
    Object getCode(String email);


    /**
     * 更新数据
     * @param email
     * @return
     */
    void updateCodeStatus(String email);


    /**
     * 根据邮箱查询数据
     * @return
     */
    boolean loginUser(String email, String password);

}

UserEmailServiceImpl.java

package com.sin.service.impl;

import com.sin.mapper.UserEmailMapper;
import com.sin.pojo.UserEmail;
import com.sin.exception.EmailAlreadyExistsException;
import com.sin.service.EmailService;
import com.sin.service.UserEmailService;
import com.sin.utils.RandomCodeUtil;
import com.sin.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import java.util.List;

/**
 * @createTime 2023/11/20 17:25
 * @createAuthor SIN
 * @use
 */
@Service
public class UserEmailServiceImpl implements UserEmailService {

    @Autowired
    private UserEmailMapper userEmailMapper;


    @Autowired
    private EmailService emailService;


    @Override
    public int insertUserEmail(UserEmail userEmail) throws MessagingException, EmailAlreadyExistsException {


        // 1,查询要添加的数据如果没有数据就添加
        UserEmail allByEmail = this.findAllByEmail(userEmail.getEmail());
        if (allByEmail != null){
            throw new EmailAlreadyExistsException("该邮箱以注册,请登录");
        }else {
            System.out.println("数据添加成功");
            userEmail.setCode_status(1);
            emailService.sendMail(userEmail.getEmail(),"验证码","<a href=\"http://localhost:8080/update/"+userEmail.getEmail()+"\">激活请点击:</a>");
            return  userEmailMapper.insertUserEmail(userEmail);
        }
    }

    @Override
    public UserEmail findAllByEmail(String email) {
        return userEmailMapper.findAllByEmail(email);
    }

    @Override
    public String sendCode(String email) throws MessagingException {
        UserEmail allByEmail = this.findAllByEmail(new UserEmail().getEmail());
        return "";

    }

    @Override
    public Object getCode(String email) {
        if (email != null){
            Object o = redisUtil.get(email);
            System.out.println(o);
            return o;
        }else {
            return "未填写邮箱";
        }


    }

    @Override
    public void updateCodeStatus(String email) {
         userEmailMapper.updateCodeStatus(email);
    }

    @Override
    public boolean loginUser(String email, String password) {
        UserEmail userByName = userEmailMapper.findByEmail(email);
        return userByName != null && userByName.getPassword().equals(password);
    }


    @Override
    public UserEmail findUserByName(String userEmail) {
        return null;
    }

    @Override
    public List<UserEmail> seletctUserEmail() {
        return userEmailMapper.seletctUserEmail();
    }


}

UserEmailController.java

package com.sin.controller;

import com.sin.exception.EmailAlreadyExistsException;
import com.sin.mapper.UserEmailMapper;
import com.sin.pojo.UserEmail;
import com.sin.service.UserEmailService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.mail.MessagingException;

/**
 * @createTime 2023/11/22 11:47
 * @createAuthor SIN
 * @use
 */
@Controller
public class UserEmailController {

    @Autowired
    private UserEmailService userEmailService;

    @GetMapping("/register")
    public String login(Model model){
        UserEmail userEmail = new UserEmail();
        model.addAttribute("userEmail",userEmail);
        // 设置成功消息
        model.addAttribute("successMessage", "邮件已发送,请注意查收");
        return "register1";
    }

    @PostMapping("/register")
    // @ModelAttribut : 将请求参数绑定到模型对象上,
    public String login(@ModelAttribute("userEmail") UserEmail userEmail, Model model) throws MessagingException {
        try{
            int result = userEmailService.insertUserEmail(userEmail); // 执行用户注册
            System.out.println(result);

        }catch (EmailAlreadyExistsException e){
            String errorMessage = e.getMessage();
            System.out.println(errorMessage);
            model.addAttribute("errorMessage",errorMessage);
        }
        return "redirect:/register";
    }

    @GetMapping("/update/{email}")
    @ResponseBody
    public String updateCodeStatus(@PathVariable("email") String email){
        userEmailService.updateCodeStatus(email);
        return "SUCCESS";
    }

    @PostMapping("/login")
    public String loginUser(@RequestParam("email") String email, @RequestParam("password") String password) {
        boolean isValid = userEmailService.loginUser(email, password);
        System.out.println(isValid);
        // 登录成功后返回到/dashboard页面
        if (isValid) {
            return "SUCCESS";
        } else {  // 登录失败返回该页面
            return "login";
        }
    }



}

register1.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录/注册</title>
    <style>
        :root {
            /* COLORS */
            --white: #e9e9e9;
            --gray: #333;
            --blue: #0367a6;
            --lightblue: #008997;

            /* RADII */
            --button-radius: 0.7rem;

            /* SIZES */
            --max-width: 758px;
            --max-height: 420px;

            font-size: 16px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
            Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
        }

        body {
            align-items: center;
            background-color: var(--white);
            background: url("https://res.cloudinary.com/dbhnlktrv/image/upload/v1599997626/background_oeuhe7.jpg");
            /* 决定背景图像的位置是在视口内固定,或者随着包含它的区块滚动。 */
            /* https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-attachment */
            background-attachment: fixed;
            background-position: center;
            background-repeat: no-repeat;
            background-size: cover;
            display: grid;
            height: 100vh;
            place-items: center;
        }

        .form__title {
            font-weight: 300;
            margin: 0;
            margin-bottom: 1.25rem;
        }

        .link {
            color: var(--gray);
            font-size: 0.9rem;
            margin: 1.5rem 0;
            text-decoration: none;
        }

        .container {
            background-color: var(--white);
            border-radius: var(--button-radius);
            box-shadow: 0 0.9rem 1.7rem rgba(0, 0, 0, 0.25),
            0 0.7rem 0.7rem rgba(0, 0, 0, 0.22);
            height: var(--max-height);
            max-width: var(--max-width);
            overflow: hidden;
            position: relative;
            width: 100%;
        }

        .container__form {
            height: 100%;
            position: absolute;
            top: 0;
            transition: all 0.6s ease-in-out;
        }

        .container--signin {
            left: 0;
            width: 50%;
            z-index: 2;
        }

        .container.right-panel-active .container--signin {
            transform: translateX(100%);
        }

        .container--signup {
            left: 0;
            opacity: 0;
            width: 50%;
            z-index: 1;
        }

        .container.right-panel-active .container--signup {
            animation: show 0.6s;
            opacity: 1;
            transform: translateX(100%);
            z-index: 5;
        }

        .container__overlay {
            height: 100%;
            left: 50%;
            overflow: hidden;
            position: absolute;
            top: 0;
            transition: transform 0.6s ease-in-out;
            width: 50%;
            z-index: 100;
        }

        .container.right-panel-active .container__overlay {
            transform: translateX(-100%);
        }

        .overlay {
            background-color: var(--lightblue);
            background: url("https://cdn.pixabay.com/photo/2018/08/14/13/23/ocean-3605547_1280.jpg");
            background-attachment: fixed;
            background-position: center;
            background-repeat: no-repeat;
            background-size: cover;
            height: 100%;
            left: -100%;
            position: relative;
            transform: translateX(0);
            transition: transform 0.6s ease-in-out;
            width: 200%;
        }

        .container.right-panel-active .overlay {
            transform: translateX(50%);
        }

        .overlay__panel {
            align-items: center;
            display: flex;
            flex-direction: column;
            height: 100%;
            justify-content: center;
            position: absolute;
            text-align: center;
            top: 0;
            transform: translateX(0);
            transition: transform 0.6s ease-in-out;
            width: 50%;
        }

        .overlay--left {
            transform: translateX(-20%);
        }

        .container.right-panel-active .overlay--left {
            transform: translateX(0);
        }

        .overlay--right {
            right: 0;
            transform: translateX(0);
        }

        .container.right-panel-active .overlay--right {
            transform: translateX(20%);
        }

        .btn {
            background-color: var(--blue);
            background-image: linear-gradient(90deg, var(--blue) 0%, var(--lightblue) 74%);
            border-radius: 20px;
            border: 1px solid var(--blue);
            color: var(--white);
            cursor: pointer;
            font-size: 0.8rem;
            font-weight: bold;
            letter-spacing: 0.1rem;
            padding: 0.9rem 4rem;
            text-transform: uppercase;
            transition: transform 80ms ease-in;
        }

        .form>.btn {
            margin-top: 1.5rem;
        }

        .btn:active {
            transform: scale(0.95);
        }

        .btn:focus {
            outline: none;
        }

        .form {
            background-color: var(--white);
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            padding: 0 3rem;
            height: 100%;
            text-align: center;
        }

        .input {
            background-color: #fff;
            border: none;
            padding: 0.9rem 0.9rem;
            margin: 0.5rem 0;
            width: 100%;
        }

        @keyframes show {

            0%,
            49.99% {
                opacity: 0;
                z-index: 1;
            }

            50%,
            100% {
                opacity: 1;
                z-index: 5;
            }
        }
        .error-message{
            color: red;
        }
    </style>
</head>

<body>
<div class="container right-panel-active">
    <!-- 注册 -->
    <div class="container__form container--signup">
        <form method="post" th:action="@{/register}" th:object="${userEmail}"  class="form" id="form1">

            <h2 class="form__title">注册</h2>
            <input type="text" placeholder="用户" th:field="*{name}" class="input" />
            <input type="password" placeholder="密码" th:field="*{password}" class="input" />
            <input type="email" placeholder="邮箱" th:field="*{email}" class="input" />
            <div class="error-message" th:if="${errorMessage}"> <!-- 修改变量名为 "errorMessage" -->
                <p id = "aaa" th:text="${errorMessage}"></p>
            </div>
            <button  class="btn" type="submit">注册</button>
        </form>
    </div>
    <div class="success-message" th:if="${successMessage}">
        <p th:text="${successMessage}"></p>
    </div>


    <!-- 登录 -->
    <div class="container__form container--signin">
        <form method="post" th:action="@{/login}" class="form" id="form2">
            <h2 class="form__title">登录</h2>
            <input type="email" placeholder="Email" name="email" class="input" />
            <input type="password" placeholder="Password" name="password" class="input" />
            <a href="#" class="link">忘记密码了?</a>
            <button class="btn" type="submit" >注册</button>
        </form>
    </div>

    <!-- Overlay -->
    <div class="container__overlay">
        <div class="overlay">
            <div class="overlay__panel overlay--left">
                <button class="btn" id="signIn">登录</button>
            </div>
            <div class="overlay__panel overlay--right">
                <button class="btn" id="signUp">注册</button>
            </div>
        </div>
    </div>
</div>

<script>
    const signInBtn = document.getElementById("signIn");
    const signUpBtn = document.getElementById("signUp");

    const container = document.querySelector(".container");


    signInBtn.addEventListener("click", () => {
        container.classList.remove("right-panel-active");
    });

    signUpBtn.addEventListener("click", () => {
        container.classList.add("right-panel-active");
    });

    // 获取页面元素
    const form = document.getElementById("form1");
    const errorMessage = document.getElementById("errorMessage");

    // 提交表单时,禁用按钮并显示加载状态
    form.addEventListener("submit", function() {
        const button = form.querySelector("button[type=submit]");
        button.disabled = true;
        button.innerText = "加载中...";
    });

    // 如果页面存在错误消息,则弹出消息框
    if (errorMessage) {
        alert(errorMessage.innerText);
    }

</script>
</body>

</html>

在这里插入图片描述

邮箱

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1265999.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

webpack如何设置兼容浏览器的范围​browserslist

Browserslist 是前端工程化不可或缺的工具&#xff0c;无论是处理 js 的 babel 还是处理 css 的 postcss&#xff0c;他们背后都有Browserslist 的身影。 一、如何查看查看所有浏览器和它的市场占有率 我们如何知道现在的浏览器那些被废弃、那些市场占有率高&#xff0c;可以…

第13关 解决K8s中Ingress Nginx控制器无法获取真实客户端IP的问题

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维。 这节课带大家探索并分享最全面的解决在使用Kubernetes&#xff08;K8s&#xff09;和Ingress-Nginx-Controller中无法获取客户端真实IP问题的视频教程&#xff0c;帮助你快速理解并解决这一问…

SpringBoot项目整合Redis,Rabbitmq发送、消费、存储邮件

&#x1f4d1;前言 本文主要是【Rabbitmq】——SpringBoot项目整合Redis&#xff0c;Rabbitmq发送、消费、存储邮件的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页…

一起学docker系列之十四Dockerfile微服务实践

目录 1 前言2 创建微服务模块2.1 **创建项目模块**2.2 **编写业务代码** 3 编写 Dockerfile4 构建 Docker 镜像5 运行 Docker 容器6 测试微服务7 总结8 参考地址 1 前言 微服务架构已经成为现代软件开发中的一种重要方式。而 Docker 提供了一种轻量级、便携式的容器化解决方案…

贵州乾辰谷材 以科技创新引领绝缘材料领域的新发展

贵州乾辰谷材科技有限公司&#xff0c;这家于2018年10月18日成立的贵州本地企业&#xff0c;已经在绝缘材料领域崭露头角。乾辰谷材不仅在成立短短几年内实现了快速成长&#xff0c;更以其科技创新能力和卓越产品性能赢得了业界和用户的广泛赞誉。 乾辰谷材的创始人王金斗先生&…

RFID资产管理系统全功能详解!高效管理从这里开始!

在现代商业环境中&#xff0c;RFID资产管理系统正成为企业管理不可或缺的先进工具。现代企业管理正处于数字化的浪潮中&#xff0c;而RFID资产管理系统正是这场浪潮中的一颗璀璨明珠。在这篇文章中&#xff0c;我们将全方位解析RFID资产管理系统的功能&#xff0c;助您深入了解…

Vue框架学习笔记——绑定class样式和绑定style样式

文章目录 前文提要class样式的三种绑定方法&#xff08;图片来自参考链接&#xff09;style样式&#xff08;内联形式&#xff09;总结 前文提要 本人仅做个人学习记录&#xff0c;如有错误&#xff0c;请多包涵 主要学习链接&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨vuejs从…

redis运维(二十二)redis 的扩展应用 lua(四)

一 最佳实践 ① 铺垫 最佳实践&#xff1a;1、把redis操作所需的key通过KEYS进行参数传递2、其它的lua脚本所需的参数通过ARGV进行传递. redis lua脚本原理 Redis Lua脚本的执行原理 ② 删除指定的脚本缓存 ③ redis集群模式下使用lua脚本注意事项 1、常见报错现象 C…

超卓航科聚国内外专家学者,共推冷喷涂技术的发展与应用

11月24日——26日&#xff0c;冷喷涂技术及其在增材制造中的应用专题会在襄阳召开&#xff0c;来自国内外200多名科技工作者齐聚一堂&#xff0c;共同交流冷喷涂技术的研究与应用。 本次专题研讨会由中国机械工程学会表面工程分会主办&#xff0c;湖北超卓航空科技股份有限公司…

LeetCode.24两两交换链表中的节点

LeetCode.24两两交换链表中的节点 1.问题描述2.解题思路3.代码 1.问题描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示…

Hive数据库与表操作

文章目录 一、准备工作二、Hive数据库操作&#xff08;一&#xff09;Hive数据存储&#xff08;二&#xff09;创建数据库&#xff08;三&#xff09;查看数据库&#xff08;四&#xff09;修改数据库信息 一、准备工作 二、Hive数据库操作 &#xff08;一&#xff09;Hive数据…

Ultipa参加国际科学会议KGSWC2023

近日&#xff0c;领先的国际科学会议 KGSWC 2023&#xff0c;在西班牙萨拉戈萨大学召开&#xff0c;Ultipa Graph参加。 KGSWC2023是第五届伊比利亚-美洲会议和第四届印度-美洲知识图谱与语义网大会的联合论坛。自2019年成立以来&#xff0c;KGSWC一直是一个重要的学术活动&am…

通过流量监控分析某个部门或客户端网络性能

在当今数字化时代&#xff0c;网络已经成为组织和企业不可或缺的基础设施之一。作为信息传输和数据交互的关键载体&#xff0c;网络的性能对于保障业务的稳定运行和提升工作效率至关重要。因此&#xff0c;对某个部门或客户端网络的性能进行分析和评估&#xff0c;有助于了解当…

PyTorch入门教学——加载数据(Dataset)

1、简介 PyTorch中如何读取数据主要涉及到两个类&#xff0c;分别为Dataset和Dataloader。 Dataset&#xff1a;创建可被Pytorch使用的数据集Dataloader&#xff1a;向模型传递数据本文主要讲解Dataset的使用方法。 2、Dataset 2.1、查看使用方法 打开Anaconda Prompt&…

在表格中显示字典的内容(根据后端返回的数据)vue3

进入页面&#xff0c;调接口&#xff0c;后端返回数据&#xff0c;indexType为0或者1&#xff0c;要用这个数据显示字典的内容 用插槽拿到数据 写一个函数&#xff0c;在模板中使用 const { proxy } getCurrentInstance(); // 字典-指标类型 const { index_type } proxy.u…

java:jpa、Hibernate、Spring Data JPA、ORM以及和mybatis的区别

文章目录 Java连接数据库几种方式JPAHibernate和Spring Data JPAORM框架jpa和mybatis区别Spring Boot JPA使用例子1、创建库和表2、添加依赖3、配置数据源和Hibernate属性4、配置实体类5、创建一个继承JpaRepository的接口&#xff1a;6、创建一个控制器&#xff08;Controller…

混合云案例:利用 Databend Cloud 高效加速私有 Databend 的策略与实施

背景 Databend 是一款基于对象存储的存算分离湖仓产品&#xff0c;已成为云上大数据分析中高效且低成本的首选解决方案。目前&#xff0c;Databend 在多个用户场景中得到广泛应用&#xff0c;包括&#xff1a; 新媒体行业数据分析及大屏数据展示云上 CDH 替代以减少本地磁盘和…

DDD 系统间的七种关系梳理与实践

系统间的七种关系 本节将根据耦合度从高到低逐一探讨这些关系。耦合度高有时并不是坏事&#xff0c;它能够让团队内部的系统更加内聚&#xff0c;而不是无法整合的碎块。我们应该根据具体情况进行选择。 因为系统间关系往往也是组织架构的反映&#xff0c;此处每种关系除了描…

9.Spring 整合 Redis

引入依赖&#xff1a;spring-boot-starter-data-redis配置 Redis&#xff1a;配置数据库参数、编写配置类&#xff0c;构造 RedisTemplate访问 Redis&#xff1a; redisTemplate.opsForValue() redisTemplate.opsForHash() redisTemplate.opsForList() redisTemplate.opsForSe…

vue3默认插槽、具名插槽以及作用域插槽实现父子组件通信

默认插槽与具名插槽 父组件 <template><div><h1>我是父组件</h1><child><div style"color: red">我是从父元素插入的值(默认插槽)</div><template #juming><div style"color: green">我是从父元素…