用户注册的逻辑流程图如下:
用户邮箱激活的分析:
用户登录功能分析:
用文字我们大概可以这样描述:
1.客户端浏览器先访问我们的注册页面 regist.html
2.填写完数据后我们用ajax方式把表单数据提交过去(前提是表单数据格式没毛病,通过了正则的校验)
3.然后向registUserServlet发送一次请求,registUserServlet拿到表单数据
4.registUserServlet让自己的秘书UserService拿着这些数据去帮远方的客户办理一下注册业务(他可不管自己的秘书的怎样干完的)
5.秘书UserService帮忙解决某业务逻辑,如根据用户名去查找用户,去数据库跑腿的脏活累活让小弟UserDao去做
6.UserDao帮忙查完数据库后,结果返回给UserService,UserService再把结果告诉Servlet,servlet把结果封装为json数据再返还给前端
这些功能我直接系统的来进行讲解:
前端代码如下,这里我们使用了js验证表单,用ajax异步交互数据:
DOCTYPE html 注册页面>
<html lang="en">
<head>
<meta charset="utf-8">
<title>注册title>
<link rel="stylesheet" type="text/css" href="css/common.css">
<link rel="stylesheet" href="css/register.css">
<script src="js/jquery-3.3.1.js">script>
<script>
/*
表单校验:
1.用户名:单词字符,长度8到20位
2.密码:单词字符,长度8到20位
3.email:邮件格式
4.姓名:非空
5.手机号:手机号格式
6.出生日期:非空
7.验证码:非空
*/
//校验用户名
//单词字符,长度8到20位
function checkUsername() {
//1.获取用户名值
var username = $("#username").val();
//2.定义正则
var reg_username = /^\w{8,20}$/;
//3.判断,给出提示信息
var flag = reg_username.test(username);
if(flag){
//用户名合法
$("#username").css("border","");
}else{
//用户名非法,加一个红色边框
$("#username").css("border","1px solid red");
}
return flag;
}
//校验密码
function checkPassword() {
//1.获取密码值
var password = $("#password").val();
//2.定义正则
var reg_password = /^\w{8,20}$/;
//3.判断,给出提示信息
var flag = reg_password.test(password);
if(flag){
//密码合法
$("#password").css("border","");
}else{
//密码非法,加一个红色边框
$("#password").css("border","1px solid red");
}
return flag;
}
//校验邮箱
function checkEmail(){
//1.获取邮箱
var email = $("#email").val();
//2.定义正则 itcast@163.com
var reg_email = /^\w+@\w+\.\w+$/;
//3.判断
var flag = reg_email.test(email);
if(flag){
$("#email").css("border","");
}else{
$("#email").css("border","1px solid red");
}
return flag;
}
$(function () {
//当表单提交时,调用所有的校验方法
$("#registerForm").submit(function(){
//1.发送数据到服务器
if(checkUsername() && checkPassword() && checkEmail()){
//校验通过,发送ajax请求,提交表单的数据 username=zhangsan&password=123
$.post("registUserServlet",$(this).serialize(),function(data){
//处理服务器响应的数据 data {flag:true,errorMsg:"注册失败"}
if(data.flag){
//注册成功,跳转成功页面
location.href="register_ok.html";
}else{
//注册失败,给errorMsg添加提示信息
$("#errorMsg").html(data.errorMsg);
}
});
}
//2.不让页面跳转
return false;
//如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交
});
//当某一个组件失去焦点是,调用对应的校验方法
$("#username").blur(checkUsername);
$("#password").blur(checkPassword);
$("#email").blur(checkEmail);
});
script>
head>
<body>
<div id="header">div>
<div class="rg_layout">
<div class="rg_form clearfix">
<div class="rg_form_left">
<p>新用户注册p>
<p>USER REGISTERp>
div>
<div class="rg_form_center">
<div id="errorMsg" style="color:red;text-align: center">div>
<form id="registerForm" action="user">
<input type="hidden" name="action" value="register">
<table style="margin-top: 25px;">
<tr>
<td class="td_left">
<label for="username">用户名label>
td>
<td class="td_right">
<input type="text" id="username" name="username" placeholder="请输入账号">
td>
tr>
<tr>
<td class="td_left">
<label for="password">密码label>
td>
<td class="td_right">
<input type="text" id="password" name="password" placeholder="请输入密码">
td>
tr>
<tr>
<td class="td_left">
<label for="email">Emaillabel>
td>
<td class="td_right">
<input type="text" id="email" name="email" placeholder="请输入Email">
td>
tr>
<tr>
<td class="td_left">
<label for="name">姓名label>
td>
<td class="td_right">
<input type="text" id="name" name="name" placeholder="请输入真实姓名">
td>
tr>
<tr>
<td class="td_left">
<label for="telephone">手机号label>
td>
<td class="td_right">
<input type="text" id="telephone" name="telephone" placeholder="请输入您的手机号">
td>
tr>
<tr>
<td class="td_left">
<label for="sex">性别label>
td>
<td class="td_right gender">
<input type="radio" id="sex" name="sex" value="男" checked> 男
<input type="radio" name="sex" value="女"> 女
td>
tr>
<tr>
<td class="td_left">
<label for="birthday">出生日期label>
td>
<td class="td_right">
<input type="date" id="birthday" name="birthday" placeholder="年/月/日">
td>
tr>
<tr>
<td class="td_left">
<label for="check">验证码label>
td>
<td class="td_right check">
<input type="text" id="check" name="check" class="check">
<img src="checkCode" height="32px" alt="" onclick="changeCheckCode(this)">
<script type="text/javascript">
//图片点击事件
function changeCheckCode(img) {
img.src="checkCode?"+new Date().getTime();
}
script>
td>
tr>
<tr>
<td class="td_left">
td>
<td class="td_right check">
<input type="submit" class="submit" value="注册">
<span id="msg" style="color: red;">span>
td>
tr>
table>
form>
div>
<div class="rg_form_right">
<p>
已有账号?
<a href="#">立即登录a>
p>
div>
div>
div>
<div id="footer">div>
<script type="text/javascript" src="js/include.js">script>
body>
html>
DOCTYPE html 登录页面>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>黑马旅游网-登录title>
<link rel="stylesheet" type="text/css" href="css/common.css">
<link rel="stylesheet" type="text/css" href="css/login.css">
<script src="js/jquery-3.3.1.js">script>
<script>
$(function () {
//1.给登录按钮绑定单击事件
$("#btn_sub").click(function () {
//2.发送ajax请求,提交表单数据
$.post("loginServlet",$("#loginForm").serialize(),function (data) {
//data : {flag:false,errorMsg:''}
if(data.flag){
//登录成功
location.href="index.html";
}else{
//登录失败
$("#errorMsg").html(data.errorMsg);
}
});
});
});
//3.处理响应结果
script>
head>
<body>
<div id="header">div>
<section id="login_wrap">
<div class="fullscreen-bg" style="background: url(images/login_bg.png);height: 532px;">
div>
<div class="login-box">
<div class="title">
<img src="images/login_logo.png" alt="">
<span>欢迎登录黑马旅游账户span>
div>
<div class="login_inner">
<div id="errorMsg" class="alert alert-danger" >div>
<form id="loginForm" action="" method="post" accept-charset="utf-8">
<input type="hidden" name="action" value="login"/>
<input name="username" type="text" placeholder="请输入账号" autocomplete="off">
<input name="password" type="text" placeholder="请输入密码" autocomplete="off">
<div class="verify">
<input name="check" type="text" placeholder="请输入验证码" autocomplete="off">
<span><img src="checkCode" alt="" onclick="changeCheckCode(this)">span>
<script type="text/javascript">
//图片点击事件
function changeCheckCode(img) {
img.src="checkCode?"+new Date().getTime();
}
script>
div>
<div class="submit_btn">
<button type="button" id="btn_sub">登录button>
<div class="auto_login">
<input type="checkbox" name="" class="checkbox">
<span>自动登录span>
div>
div>
form>
<div class="reg">没有账户?<a href="javascript:;">立即注册a>div>
div>
div>
section>
<div id="footer">div>
<script src="js/jquery-1.11.0.min.js">script>
<script src="js/bootstrap.min.js">script>
<script type="text/javascript" src="js/include.js">script>
body>
html>
<script>
$(function () {
$.get("findUserServlet",{},function (data) {
//{uid:1,name:'李四'}
var msg = "欢迎回来,"+data.name;
$("#span_username").html(msg);
});
});
script>
<header id="header">
<div class="top_banner">
<img src="images/top_banner.jpg" alt="">
div>
<div class="shortcut">
<div class="login_out">
<a href="login.html">登录a>
<a href="register.html">注册a>
div>
<div class="login">
<span id="span_username">span>
<a href="myfavorite.html" class="collection">我的收藏a>
<a href="javascript:location.href='exitServlet';">退出a>
div>
div>
<div class="header_wrap">
<div class="topbar">
<div class="logo">
<a href="/"><img src="images/logo.jpg" alt="">a>
div>
<div class="search">
<input name="" type="text" placeholder="请输入路线名称" class="search_input" autocomplete="off">
<a href="javascript:;" class="search-button">搜索a>
div>
<div class="hottel">
<div class="hot_pic">
<img src="images/hot_tel.jpg" alt="">
div>
<div class="hot_tel">
<p class="hot_time">客服热线(9:00-6:00)p>
<p class="hot_num">400-618-9090p>
div>
div>
div>
div>
header>
<div class="navitem">
<ul class="nav">
<li class="nav-active"><a href="index.html">首页a>li>
<li><a href="route_list.html">门票a>li>
<li><a href="route_list.html">酒店a>li>
<li><a href="route_list.html">香港车票a>li>
<li><a href="route_list.html">出境游a>li>
<li><a href="route_list.html">国内游a>li>
<li><a href="route_list.html">港澳游a>li>
<li><a href="route_list.html">抱团定制a>li>
<li><a href="route_list.html">全球自由行a>li>
<li><a href="favoriterank.html">收藏排行榜a>li>
ul>
div>
// 用于注册的servlet
@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//验证校验
String check = request.getParameter("check");
//从sesion中获取验证码
HttpSession session = request.getSession();
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
//比较
if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
//验证码错误
ResultInfo info = new ResultInfo();
//注册失败
info.setFlag(false);
info.setErrorMsg("验证码错误");
//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return;
}
//1.获取数据
Map<String, String[]> map = request.getParameterMap();
//2.封装对象
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//3.调用service完成注册
UserService service = new UserServiceImpl();
boolean flag = service.regist(user);
ResultInfo info = new ResultInfo();
//4.响应结果
if(flag){
//注册成功
info.setFlag(true);
}else{
//注册失败
info.setFlag(false);
info.setErrorMsg("注册失败!");
}
//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
//将json数据写回客户端
//设置content-type
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
//用来登录的servlet
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String[]> map = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//调用service查询
UserServiceImpl service = new UserServiceImpl();
User u = service.login(user);
ResultInfo info = new ResultInfo();
//判断用户对象是否为null
if (u == null){
//用户名密码错误
info.setFlag(false);
info.setErrorMsg("用户名或密码错误");
}
// 判断用户是否激活
if (u!=null && !"Y".equals(u.getStatus())){
//用户尚未激活
info.setFlag(false);
info.setErrorMsg("您尚未激活,请激活");
}
//判断登录成功
if (u!=null && "Y".equals(u.getStatus())){
HttpSession session = request.getSession();
session.setAttribute("user",u);
//登录成功
info.setFlag(true);
}
/* //响应数据
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
String json = mapper.writeValueAsString(info);
response.getWriter().write(json);*/
//响应数据
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),info);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
// 查找用户的servlet
@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从session中获取登录用户
Object user = request.getSession().getAttribute("user");
//将user写回客户端
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
// 用来退出的servlet
@WebServlet("/exitServlet")
public class ExitServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.销毁session
request.getSession().invalidate();
//2.跳转登录页面
response.sendRedirect(request.getContextPath()+"/login.html");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
service层代码如下:
package cn.itcast.travel.service.impl;
import cn.itcast.travel.dao.UserDao;
import cn.itcast.travel.dao.impl.UserDaoImpl;
import cn.itcast.travel.domain.User;
import cn.itcast.travel.service.UserService;
import cn.itcast.travel.util.MailUtils;
import cn.itcast.travel.util.UuidUtil;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
/**
* 注册用户
* @param user
* @return
*/
@Override
public boolean regist(User user) {
//1.根据用户名查询用户对象
User u = userDao.findByUsername(user.getUsername());
//判断u是否为null
if(u != null){
//用户名存在,注册失败
return false;
}
//2.保存用户信息
//2.1设置激活码,唯一字符串
user.setCode(UuidUtil.getUuid());
//2.2设置激活状态
user.setStatus("N");
userDao.save(user);
//3.激活邮件发送,邮件正文?
String content="点击激活【黑马旅游网】";
MailUtils.sendMail(user.getEmail(),content,"激活邮件");
return true;
}
/**
* 激活用户
* @param code
* @return
*/
@Override
public boolean active(String code) {
//1.根据激活码查询用户对象
User user = userDao.findByCode(code);
if(user != null){
//2.调用dao的修改激活状态的方法
userDao.updateStatus(user);
return true;
}else{
return false;
}
}
/**
* 登录方法
* @param user
* @return
*/
@Override
public User login(User user) {
return userDao.findByUsernameAndPassword(user.getUsername(),user.getPassword());
}
}
package cn.itcast.travel.dao.impl;
import cn.itcast.travel.dao.UserDao;
import cn.itcast.travel.domain.User;
import cn.itcast.travel.util.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDaoImpl implements UserDao {
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
@Override
public User findByUsername(String username) {
User user = null;
try {
//1.定义sql
String sql = "select * from tab_user where username = ?";
//2.执行sql
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username);
} catch (Exception e) {
}
return user;
}
@Override
public void save(User user) {
//1.定义sql
String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email,status,code) values(?,?,?,?,?,?,?,?,?)";
//2.执行sql
template.update(sql, user.getUsername(),
user.getPassword(),
user.getName(),
user.getBirthday(),
user.getSex(),
user.getTelephone(),
user.getEmail(),
user.getStatus(),
user.getCode()
);
}
/**
* 根据激活码查询用户对象
*
* @param code
* @return
*/
@Override
public User findByCode(String code) {
User user = null;
try {
String sql = "select * from tab_user where code = ?";
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), code);
} catch (DataAccessException e) {
e.printStackTrace();
}
return user;
}
/**
* 修改指定用户激活状态
*
* @param user
*/
@Override
public void updateStatus(User user) {
String sql = " update tab_user set status = 'Y' where uid=?";
template.update(sql, user.getUid());
}
/**
* 根据用户名和密码查询的方法
*
* @param username
* @param password
* @return
*/
@Override
public User findByUsernameAndPassword(String username, String password) {
User user = null;
//定义sql
try {
String sql = "select * from tab_user where username=? and password=?";
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username, password);
}catch (Exception e){
//执行sql
}
return user;
}
}
/**
* 发邮件工具类
*/
public final class MailUtils {
private static final String USER = "907312887@qq.com"; // 发件人称号,同邮箱地址
private static final String PASSWORD = "********"; // 这是我自己qq邮箱的授权码,这里就不予展示了
/**
*
* @param to 收件人邮箱
* @param text 邮件正文
* @param title 标题
*/
/* 发送验证信息的邮件 */
public static boolean sendMail(String to, String text, String title){
try {
final Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", "smtp.qq.com");
// 发件人的账号
props.put("mail.user", USER);
//发件人的密码
props.put("mail.password", PASSWORD);
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用环境属性和授权信息,创建邮件会话
Session mailSession = Session.getInstance(props, authenticator);
// 创建邮件消息
MimeMessage message = new MimeMessage(mailSession);
// 设置发件人
String username = props.getProperty("mail.user");
InternetAddress form = new InternetAddress(username);
message.setFrom(form);
// 设置收件人
InternetAddress toAddress = new InternetAddress(to);
message.setRecipient(Message.RecipientType.TO, toAddress);
// 设置邮件标题
message.setSubject(title);
// 设置邮件的内容体
message.setContent(text, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
public static void main(String[] args) throws Exception { // 做测试用
MailUtils.sendMail("yangjiaxing130283@163.com","你好,这是一封测试邮件,无需回复。","测试邮件");
System.out.println("发送成功");
}
}
package cn.itcast.travel.util;
import java.util.UUID;
/**
* 产生UUID随机字符串工具类
*/
public final class UuidUtil {
private UuidUtil(){}
public static String getUuid(){
return UUID.randomUUID().toString().replace("-","");
}
/**
* 测试
*/
public static void main(String[] args) {
System.out.println(UuidUtil.getUuid());
System.out.println(UuidUtil.getUuid());
System.out.println(UuidUtil.getUuid());
System.out.println(UuidUtil.getUuid());
}
}