SpringBoot+Mybatis+JavaMail+HtmlUnit实现模拟登陆+邮箱验证码发送

版权声明:欢迎转载,转载请注明原博客网址 https://blog.csdn.net/qq_37497322/article/details/83064440

由于我们学校的hustoj版本久远,业务和视图混在一起,可扩展性较差,正好缺一个账号找回功能,然后我就写了一个另外的web项目挂在了自己的服务器上以解决这个问题。因为mysql中的密码是经过几次加密写进去的,不可以直接用数据库修改,然后我就想到了用htmlunit模拟登陆我自己(管理员),模拟使用changepassword功能,同理使用这个功能核对要找回的账号和写的邮箱(邮箱只有自己知道),然后使用JavaMail对账号的邮箱发送随机的验证码对邮箱进行验证,输入对了就可以进行修改。验证码的写法还比较简单,将验证码获得时间写入数据库(只要设置default update就行了,不用代码处理),每次有人核对成功要获得验证码时,检查该账户是否已经获取过验证码了。如果获取过,取出时间,和当前的时间做一个减法,如果时差大于2分钟就判定验证码失效,删掉原来记录重新写入一个新的,没获取过就直接插入信息,或者获取过但是还在2分钟有效期内,就发出提示信息并不允许再获得验证码。同理核对验证码正确性也要做一个验证码的时效检查,验证码一旦使用过就直接删掉。

效果图:

数据库脚本:

DROP DATABASE server ;
CREATE DATABASE IF NOT EXISTS server DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
use server
create table user(
      id varchar(20) primary key not null,
     code varchar(20) not null,
     mail varchar(30) not null,
     time TIMESTAMP DEFAULT CURRENT_TIMESTAMP  ON UPDATE CURRENT_TIMESTAMP
)engine=innodb default charset=utf8;

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

这是一条分界线,就在我前几天准备写这篇博客的时候,我惊奇得发现我把项目代码给删了。。然后从服务器端传回来,反编译一下,一堆报错和乱七八糟的注释。。绝望得我只好重新写了这个项目,正好优化一下,这次我用的

是springboot+mybatis+JavaMail+HtmlUnit,项目写好后测试响应时间大概是1s,多的时候是3.5s,其中有3s是模拟管理员登陆花费的时间。。。没办法优化了,只能以后发现oj的加密方法直接对数据库来操作应该会快很多。

ps:由于服务器运行内存只有1g,经常出现卡死状态qaq。

重写效果图:

核心代码:

项目框架:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.wust</groupId>
	<artifactId>servlet</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>servlet</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.5.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>

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

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

		<!--数据库相关-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<!--spring操作数据库jpa  用于将数据存入数据库的类和方法的集-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>net.sourceforge.htmlunit</groupId>
			<artifactId>htmlunit</artifactId>
			<version>2.33</version>
		</dependency>
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>javax.mail-api</artifactId>
			<version>1.6.2</version>
		</dependency>
		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>javax.mail</artifactId>
			<version>1.6.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.activation</groupId>
			<artifactId>activation</artifactId>
			<version>1.1.1</version>
		</dependency>
		<!-- JDBC连接池依赖 -->
		<dependency><groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.2</version>
		</dependency>
		<!-- 添加对 mybatis 的依赖 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>

		<!-- 添加对 JDBC 的支持 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

主类(要标注各种包的扫描情况):

package com.wust.servlet;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

@SpringBootApplication
@ComponentScan("controller")
@ComponentScan("entity")
@ComponentScan("service")
@ComponentScan("conf")
@MapperScan("mapper")
@EnableAutoConfiguration
public class ServletApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServletApplication.class, args);
	}
}

SpringBoot的配置文件,,里面写一些数据库配置相关的信息:

spring.thymeleaf.cache=false
# 设置数据库相关
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/server
spring.datasource.username =root
spring.datasource.password =666666

# 设置 c3p0 数据源
spring.datasource.type=com.mchange.v2.c3p0.ComboPooledDataSource
# 设置 MyBatis mapper 的别名所在的包
mybatis.type-aliases-package=mapper
server.port=80

Mybatis的Mapper类:

package mapper;

import entity.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface UserMapper{
    @Select("select * from user where id = #{id}")
    public User findUser(String id);
    @Insert("insert into user(id,code,mail,time) values(#{id},#{code},#{mail},default)")
    public int insertUser(User user);
    @Delete("delete from user where id = #{id}")
    public int deleteUser(String id);
}

配置连接池和sqlsession的Bean:

package conf;


import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;

import java.beans.PropertyVetoException;

@SpringBootConfiguration
public class DataSourceConfiguration {

    @Value("${spring.datasource.driverClassName}")
    private String jdbcDriver;
    @Value("${spring.datasource.url}")
    private String jdbcUrl;
    @Value("${spring.datasource.username}")
    private String jdbcUser;
    @Value("${spring.datasource.password}")
    private String jdbcPassword;

    @Bean
    public ComboPooledDataSource createDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        dataSource.setDriverClass(jdbcDriver);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setUser(jdbcUser);
        dataSource.setPassword(jdbcPassword);
        // 关闭连接后不自动提交
        dataSource.setAutoCommitOnClose(false);

        return dataSource;
    }
}

User的pojo类,其中重写了equals方法之后会用到:

package entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.persistence.Entity;
import java.util.Date;
@Component
@Entity
public class User {
    private String id;
    private String code;
    private String mail;
    private Date time;

    public String getId() {
        return id;
    }

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

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMail() {
        return mail;
    }

    public void setMail(String mail) {
        this.mail = mail;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof User)) {
            return false;
        }
        User user = (User)o;
        return (user.getId().equals(this.id)) && (user.getCode().equals(this.code)) && (user.getMail().equals(this.mail));
    }
}

Admin类,主要用于用htmlunit模拟管理员登陆,进行账号邮箱确认和密码修改的模拟:

package service;

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.util.Cookie;
import org.springframework.stereotype.Service;

@Service
public class Admin
{
    public void ChangePwd(String user_id, String new_pwd) throws java.io.IOException
    {
        WebClient webclient = new WebClient();
        webclient.getOptions().setCssEnabled(false);
        webclient.getOptions().setJavaScriptEnabled(false);
        webclient.getOptions().setRedirectEnabled(true);
        webclient.getCookieManager().setCookiesEnabled(true);
        HtmlPage htmlpage = (HtmlPage)webclient.getPage("http://acm.wust.edu.cn/loginpage.php");
        HtmlForm form = (HtmlForm)htmlpage.getForms().get(0);
        HtmlElement button = (HtmlElement)htmlpage.getElementByName("submit");
        HtmlTextInput nameField = (HtmlTextInput)form.getInputByName("user_id");
        nameField.setValueAttribute("自己的账号");
        HtmlPasswordInput pwdField = (HtmlPasswordInput)form.getInputByName("password");
        pwdField.setValueAttribute("自己的密码");
        button.click();
        java.util.Set<Cookie> cookies = webclient.getCookieManager().getCookies();
        java.util.Map<String, String> responseCookies = new java.util.HashMap();
        for (Cookie c : cookies) {
            responseCookies.put(c.getName(), c.getValue());
        }
        HtmlPage nextPage = (HtmlPage)webclient.getPage("保密");//之后是分析页面获取按钮模拟修改密码
        HtmlForm form1 = (HtmlForm)nextPage.getForms().get(0);
        HtmlTextInput name = (HtmlTextInput)form1.getInputByName("user_id");
        HtmlTextInput pwd = (HtmlTextInput)form1.getInputByName("passwd");
        com.gargoylesoftware.htmlunit.html.HtmlInput btn = (HtmlInput)form1.getInputsByValue("xxxx").get(0);
        name.setValueAttribute(user_id);
        pwd.setValueAttribute(new_pwd);
        String result = nextPage.asXml();
        btn.click();
        webclient.close();
    }
public boolean checkExist(String id, String Mail) throws java.io.IOException
{
    WebClient webclient = new WebClient();
    webclient.getOptions().setCssEnabled(false);
    webclient.getOptions().setJavaScriptEnabled(false);
    webclient.getOptions().setRedirectEnabled(true);
    webclient.getCookieManager().setCookiesEnabled(true);
    HtmlPage htmlpage = (HtmlPage)webclient.getPage("http://acm.wust.edu.cn/loginpage.php");
    HtmlForm form = (HtmlForm)htmlpage.getForms().get(0);
    HtmlElement button = (HtmlElement)htmlpage.getElementByName("submit");
    HtmlTextInput nameField = (HtmlTextInput)form.getInputByName("user_id");
    nameField.setValueAttribute("自己的账号");
    HtmlPasswordInput pwdField = (HtmlPasswordInput)form.getInputByName("password");
    pwdField.setValueAttribute("自己的密码");
    button.click();
    java.util.Set<Cookie> cookies = webclient.getCookieManager().getCookies();
    java.util.Map<String, String> responseCookies = new java.util.HashMap();
    for (Cookie c : cookies) {
        responseCookies.put(c.getName(), c.getValue());
    }
    HtmlPage nextPage = (HtmlPage)webclient.getPage("http://acm.wust.edu.cn/userinfo.php?user=" + id);
    if (nextPage.getByXPath("/html/body/div[@id='wrapper']/div[@id='main']/center/font[1]").size() == 0)//这里是xpath表达式获取页面元素
    {
        return false;
    }
    HtmlElement item = (HtmlElement)nextPage.getByXPath("/html/body/div[@id='wrapper']/div[@id='main']/center/font[1]").get(0);
    String xml = item.asXml();
    String mail = "";
    String regex = "[a-zA-z\\.[0-9]]*@[a-zA-z[0-9]]*\\.com";
    java.util.regex.Pattern p = java.util.regex.Pattern.compile(regex);
    java.util.regex.Matcher m = p.matcher(xml);
    int num = 0;
    while (m.find()) {
        mail = m.group().toString();
    }
    webclient.close();
    if (Mail.equals(mail))
        return true;
    return false;
    }
}

CodeHandle类主要用于核对数据库里的验证码有效性,以及验证2分钟的有效期:

 package service;

 import java.util.Date;

 import entity.User;
 import mapper.UserMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;


 @Service
 public class CodeHandle
 {
     @Autowired
     private UserMapper userMapper;
     @Autowired
     @Transactional
      public  boolean CheckValid(User user)
       {
           User user1 = userMapper.findUser(user.getId());
         if (user.equals(user1))
         {
           return true;
         }
         return false;
       }
       @Autowired
       @Transactional
       public boolean CheckRepeat(User user)
       {
         User user1 = userMapper.findUser(user.getId());
         if (user1 == null)
           return false;
         Date d1 = new Date();
         Date d2 = user1.getTime();
         if (d1.getTime() - d2.getTime() >= 120000)
         {
           userMapper.deleteUser(user.getId());
           return false;
         }
         return true;
       }
 }

Mail类,主要用于发送验证码:

package service;
import com.sun.mail.util.MailSSLSocketFactory;
import entity.User;
import mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
import java.util.Random;
@Service
public class Mail
 {
    @Autowired
     UserMapper userMapper;
     @Transactional
     public  void sendCode(User user)
   {
     try
     {
       Properties prop = new Properties();
       prop.setProperty("mail.debug", "true");//设置debug信息打印
       prop.setProperty("mail.host", "smtp.qq.com");
       prop.setProperty("mail.smtp.auth", "true");
       prop.setProperty("mail.transport.protocol", "smtp");
       MailSSLSocketFactory sf = new MailSSLSocketFactory();
       sf.setTrustAllHosts(true);
       prop.put("mail.smtp.ssl.enable", "true");
       prop.put("mail.smtp.ssl.socketFactory", sf);
       Session session = Session.getInstance(prop);
       Transport ts = session.getTransport();
       ts.connect("smtp.qq.com", "qq号", "这里填邮箱里的授权码(没有的要去qq邮箱那设置)");
       Message message = createSimpleMail(user, session);
       ts.sendMessage(message, message.getAllRecipients());
       ts.close();
     }
     catch (Exception e) {
       e.printStackTrace();
     }
   }
   @Transactional
   public  MimeMessage createSimpleMail(User user, Session session) throws Exception
   {
     MimeMessage message = new MimeMessage(session);
     message.setFrom(new InternetAddress("这里填发件人的邮箱"));
     message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getMail()));
     message.setSubject("OJ账号找回");
     Random rand = new Random();
     Integer t = Integer.valueOf(rand.nextInt(90000) + 10000);//生成5位随机数
     user.setCode(t.toString());
     userMapper.insertUser(user);
     message.setContent("本次的修改密码验证码为:" + t + ",2分钟内有效。若非本人操作,请尽快联系WUSTOJ管理员,qq:845723932 ", "text/html;charset=UTF-8");
     return message;
   }
 }

Controller,用于调度service和请求回复:

package controller;

import entity.User;
import mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import service.Admin;
import service.CodeHandle;
import service.Mail;

import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/")
public class PageController {
    @Autowired
    Admin admin;
    @Autowired
    CodeHandle codeHandle;
    @Autowired
    Mail mail;
    @Autowired
    UserMapper userMapper;

    @GetMapping("/index")
    public String index() {
        return "index";
    }

    @PostMapping("/GetCode")
    @ResponseBody
    public Map<String,String> GetCode(HttpSession httpSession, User user) throws IOException {
        Map<String,String>map=new HashMap<String,String>();
        String msg="未知错误";
        try {
            if(user.getId()==null||user.getMail()==null||(user.getId().equals("")) || (user.getMail().equals("")))
            {
                msg="账号或邮箱未填!";
            }
            else if (admin.checkExist(user.getId(), user.getMail())) {
                httpSession.setAttribute("uid", user.getId());
                httpSession.setAttribute("umail", user.getMail());
                if (codeHandle.CheckRepeat(user)) {
                    msg="你已获得过验证码!";
                } else {
                    mail.sendCode(user);
                    msg="获取验证码成功!";
                }
            } else {
                msg="输入的账号或邮箱信息有误!";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        map.put("msg",msg);
        return map;
    }

    @PostMapping("/CheckCode")
    @ResponseBody
    public Map<String,String> CheckCode(HttpSession httpSession,User user, @RequestParam("pwd") String pwd) throws IOException {
        Map<String,String>map=new HashMap<String,String>();
        if(httpSession.getAttribute("uid")!=null)
        {
            user.setId((String)httpSession.getAttribute("uid"));
        }
        if(httpSession.getAttribute("umail")!=null)
        {
            user.setMail((String)httpSession.getAttribute("umail"));
        }
        if (user.getId()==null||user.getMail()==null||(user.getId().equals("")) || (user.getMail().equals(""))) {
            map.put("msg", "账号和邮箱不能为空!");
        }
        else if(user.getCode()==null||pwd==null||user.getCode().equals("")||pwd.equals(""))
        {
            map.put("msg","验证码或密码不能为空");
        }
        else if (codeHandle.CheckRepeat(user)) {
            if (codeHandle.CheckValid(user)) {
                try {
                    admin.ChangePwd(user.getId(), pwd);
                    map.put("msg", "修改密码成功!");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                userMapper.deleteUser(user.getId());
            } else {
                map.put("msg", "输入验证码有误!");
            }
        } else {
            map.put("msg", "验证码过期或没有获得过验证码!");
        }
        return map;
    }
}

最后是自己写的前端页面,用ajax来请求,设置了获得成功后的倒计时,关掉了异步,因为是局部更新,异步没办法呈现alert信息,采用thymeleaf来实现回填:

<!DOCTYPE html>
<html lang = "chi">
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=8">
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    <meta name="viewport" content="width=device-width, initial-scale=0.5, maximun-scale=1, minimum-scale=1, user-scaleable=no">
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>

    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <style>
        /*web background*/
        .container{
            display:table;
            height:100%;
            width: 300px;
        }
    </style>
    <title>WUSTOJ账号找回</title>
    <script type="text/javascript">
        $(document).ready(function () {
            $('#codeButton').click(function () {
                $.ajax({
                    async: false,
                    type: "POST",
                    url:'/GetCode',
                    dataType: "json",
                    data:$("#f1").serialize(),
                    success: function (data) {
                        if(data.msg!=null)
                            alert(data.msg);
                        if('获取验证码成功!'==data.msg)
                        {
                            timer(120);
                        }
                    },
                    error: function () {
                    }
                })
            })
            $("#sub").click(function () {
                $.ajax({
                    async: false,
                    type: "POST",
                    url:'/CheckCode',
                    dataType: "json",
                    data:$("#f2").serialize(),
                    success: function (data) {
                        if(data.msg!=null)
                            alert(data.msg);
                    },
                    error: function () {
                    }
                })
            })

        })
        function timer(time) {
            var btn = $("#codeButton");
            btn.attr("disabled", true); //按钮禁止点击
            btn.html(time <= 0 ? "发送验证码" : ("" + (time--) + "秒后可发送"));
            var hander = setInterval(function() {
                if (time <= 0) {
                    clearInterval(hander); //清除倒计时
                    btn.html("发送验证码");
                    btn.attr("disabled", false);
                    return false;
                }else {
                    btn.html("" + (time--) + "秒后可发送");
                }
            }, 1000);
        }
    </script>
</head>
<body style="width: 100%">
<div class="panel panel-info center-block" style="width: 500px">
    <div class="form-group text-center panel panel-heading">
        <h3>WUSTOJ账号找回</h3>
    </div>
    <div class="container">
        <form id="f1" class="form-horizontal" role="form">
            <div class="form-group input-group">
                <span class="input-group-addon">账号</span>
                <input type="text" class="form-control" placeholder="请输入账号" name="id" th:value="${session.uid}"/>
            </div>
            <div class="form-group input-group">
                <span class="input-group-addon ">邮箱</span>
                <input type="text" class="form-control" placeholder="请输入邮箱" name="mail" th:value="${session.umail}"/>
            </div>
            <div class="form-group input-group">
                <div>
                    <button id="codeButton" class="btn btn-success">获得验证码</button>
                </div>
            </div>
        </form>
        <form id="f2" class="form-horizontal" role="form">
            <div class="form-group input-group">
                <span class="input-group-addon">验证码</span>
                <input class="form-control" type="text" placeholder="请输入验证码" name="code"/>
            </div>
            <div class="form-group input-group">
                <span class="input-group-addon ">新密码</span>
                <input  class="form-control" placeholder="请输入新密码" name="pwd"/>
            </div>
            <div class="form-group input-group">
                <div >
                    <button id="sub" class="btn btn-info">密码修改</button>
                </div>
            </div>
        </form>
    </div>
</div>
</body>
</html>

ps:

打包方法:在maven界面,右击package,build一下,target处会打包一个jar包

由于spring boot内置了tomcat,直接用java -jar servlet.jar包就可以部署了

也可以自己写一个shell脚本:

startup.sh(同时写入日志到log.file中):

 #!/bin/bash
   echo starting
   java -jar servlet.jar > log.file 2>&1 &

stop的脚本我写的出错了。。

然后是手动用ps -ef|grep servlet查出id直接kill -9 id来杀的进程。。。

有人知道正确写法么orz

然后restart.sh写法:

#!/bin/bash
echo stop application
source stop.sh
echo start application
source startup.sh

github项目源码(当然是修改过的不会暴露信息版):https://github.com/iunique/IdeaProject/tree/master/servlet

总结:

本次项目复习了springboot搭建java web,thymeleaf,mybatis的使用,然后新学了htmlunit爬虫模拟浏览器操作,javamail发送邮件,以及验证码的实现方法,springboot的服务部署,明明是后台又锻炼了一下基础的前端。。还是很有收获的

----------------------------------------------------------------------------------------------------------------------------------------------------------

10月19日更

今天终于发现了为什么ajax异步请求时出错,在index.html中的timer函数清除倒计时那用在hander定义的时候在内部用了hander,通过chorme单步js查查出了这个错。。还有就是发现之前的明明指定了是post方法最后传的却是get,原因是ajax提交的时候form表单会自动提交,form不写method默认为了get,然后解决方法是把button的type设置成button就不会出错了,还有发现貌似还用不到thymeleaf,直接通过jquery来修改元素值的value或者设置表单不刷新就行了,这样响应速度会快一些,下面是修改过的index.html代码:

<!DOCTYPE html>
<html lang = "chi">
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=8">
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    <meta name="viewport" content="width=device-width, initial-scale=0.5, maximun-scale=1, minimum-scale=1, user-scaleable=no">
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>

    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <style>
        /*web background*/
        .container{
            display:table;
            height:100%;
            width: 300px;
        }
    </style>
    <title>WUSTOJ账号找回</title>
    <script type="text/javascript">
        function timer(time) {
            var btn = $("#codeButton");
            btn.attr("disabled", true); //按钮禁止点击
            btn.html(time <= 0 ? "发送验证码" : ("" + (time--) + "秒后可发送"));
            var hander = setInterval(function() {
                if (time <= 0) {
                    clearInterval(this); //清除倒计时
                    btn.html("发送验证码");
                    btn.attr("disabled", false);
                    return false;
                }else {
                    btn.html("" + (time--) + "秒后可发送");
                }
            }, 1000);
        }
        $(document).ready(function () {
            $('#codeButton').click(function () {
                $.ajax({
                    async: true,
                    type: "POST",
                    url:'/GetCode',
                    dataType: "json",
                    data:$("#f1").serialize(),
                    success: function (data) {
                        if(data.msg!=null)
                            alert(data.msg);
                        if('获取验证码成功!'==data.msg)
                        {
                            timer(120);
                            $("#i1").val(data.id);
                            $("#i2").val(data.mail);
                        }
                    },
                    error: function () {
                        alert("操作异常!");
                    }
                })
            })
            $("#sub").click(function () {
                $.ajax({
                    async: true,
                    type: "POST",
                    url:'/CheckCode',
                    dataType: "json",
                    data:$("#f2").serialize(),
                    success: function (data) {
                        if(data.msg!=null)
                            alert(data.msg);
                    },
                    error: function () {
                        alert("操作异常");
                    }
                })
            })

        })
    </script>
</head>
<body style="width: 100%">
<div class="panel panel-info center-block" style="width: 500px">
    <div class="form-group text-center panel panel-heading">
        <h3>WUSTOJ账号找回</h3>
    </div>
    <div class="container">
        <form id="f1" class="form-horizontal" role="form">
            <div class="form-group input-group">
                <span class="input-group-addon">账号</span>
                <input id="i1"type="text" class="form-control" placeholder="请输入账号" name="id" />
            </div>
            <div class="form-group input-group">
                <span class="input-group-addon ">邮箱</span>
                <input id="i2" type="text" class="form-control" placeholder="请输入邮箱" name="mail" />
            </div>
            <div class="form-group input-group">
                <div>
                    <button id="codeButton" class="btn btn-success" type="button">获得验证码</button>
                </div>
            </div>
        </form>
        <form id="f2" class="form-horizontal" role="form">
            <div class="form-group input-group">
                <span class="input-group-addon">验证码</span>
                <input class="form-control" type="text" placeholder="请输入验证码" name="code"/>
            </div>
            <div class="form-group input-group">
                <span class="input-group-addon ">新密码</span>
                <input  class="form-control" placeholder="请输入新密码" name="pwd"/>
            </div>
            <div class="form-group input-group">
                <div >
                    <button id="sub" class="btn btn-info" type="button">密码修改</button>
                </div>
            </div>
        </form>
    </div>
</div>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

10月23日更,今天发现项目又挂了,上去看日志发现报的是socket time out,大概是数据库连接超时了,没有设置重连,然后找到了这几篇文章,修改更新了下项目~

https://blog.csdn.net/qq_33792843/article/details/74746416

https://blog.csdn.net/feeltouch/article/details/80470172

还有就是在用htmlunit的时候

webclient.getOptions().setTimeout(0);

表示连接不失效

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

10月24日更,今天去看又挂了,貌似是html的webclient那一直报time out,我直接把admin方法全改成了static方法,去掉了以前bean的方式,暂时还没有挂,希望这次能彻底解决问题

猜你喜欢

转载自blog.csdn.net/qq_37497322/article/details/83064440