19、Javaweb案例-登录功能

项目导入

选择travel项目的pom.xml文件,点击ok,完成项目导入。需要等待一小会,项目初始化完成。

启动项目

方式一:

 方式二:配置maven快捷启动

技术选型

Web层

  1. Servlet:前端控制器
  2. html:视图
  3. Filter:过滤器
  4. BeanUtils:数据封装
  5. Jackson:json序列化工具

Service层

  1. Javamail:java发送邮件工具
  2. Redis:nosql内存数据库
  3. Jedis:java的redis客户端

Dao层

  1. Mysql:数据库
  2. Druid:数据库连接池
  3. JdbcTemplate:jdbc的工具

创建数据库

-- 创建数据库

CREATE DATABASE travel;

-- 使用数据库

USE travel;

--创建表

复制提供好的sql

注册功能

页面效果

 功能分析

 代码实现

前台代码实现

User具体类

package cn.itcast.travel.domain;

import java.io.Serializable;

/**
 * 用户实体类
 */
public class User implements Serializable {
    private int uid;//用户id
    private String username;//用户名,账号
    private String password;//密码
    private String name;//真实姓名
    private String birthday;//出生日期
    private String sex;//男或女
    private String telephone;//手机号
    private String email;//邮箱
    private String status;//激活状态,Y代表激活,N代表未激活
    private String code;//激活码(要求唯一)

    /**
     * 无参构造方法
     */
    public User() {
    }

    /**
     * 有参构方法
     * @param uid
     * @param username
     * @param password
     * @param name
     * @param birthday
     * @param sex
     * @param telephone
     * @param email
     * @param status
     * @param code
     */
    public User(int uid, String username, String password, String name, String birthday, String sex, String telephone, String email, String status, String code) {
        this.uid = uid;
        this.username = username;
        this.password = password;
        this.name = name;
        this.birthday = birthday;
        this.sex = sex;
        this.telephone = telephone;
        this.email = email;
        this.status = status;
        this.code = code;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    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 getName() {
        return name;
    }

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

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getCode() {
        return code;
    }

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

响应信息具体类

package cn.itcast.travel.domain;

import java.io.Serializable;
import java.util.Objects;

/**
 * 用于封装后端返回前端数据对象
 */
public class ResultInfo implements Serializable {
    private boolean flag;//后端返回结果正常为true,发生异常返回false
    private Object data;//后端返回结果数据对象
    private String errorMsg;//发生异常的错误消息

    //无参构造方法
    public ResultInfo() {
    }
    public ResultInfo(boolean flag) {
        this.flag = flag;
    }
    /**
     * 有参构造方法
     * @param flag
     * @param errorMsg
     */
    public ResultInfo(boolean flag, String errorMsg) {
        this.flag = flag;
        this.errorMsg = errorMsg;
    }
    /**
     * 有参构造方法
     * @param flag
     * @param data
     * @param errorMsg
     */
    public ResultInfo(boolean flag, Object data, String errorMsg) {
        this.flag = flag;
        this.data = data;
        this.errorMsg = errorMsg;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public ResultInfo setResultInfo(ResultInfo info,boolean flag, Object data, String errorMsg) {
        info.setFlag(flag);
        info.setData(data);
        info.setErrorMsg(errorMsg);
        return info;
    }

}

JDBCUtils工具类

UuidUtil:产生UUID随机字符串工具类

邮箱工具类详情

验证码

引入外部html

index.css

.search_input {
	height: 40px;
}
/*精选*/
#content {
	margin-bottom: 60px;
}
.hemai_jx{
	width: 1200px;
	overflow: hidden;
	margin: 0 auto;
}
.jx_top{
	width: 1200px;
	height: 35px;
	line-height: 35px;
	margin: 0 auto;
}

.jx_top {
	margin-top: 35px;
	border-bottom: 2px solid #ffc900;
}
.jx_tit, .jx_tabs {
	float: left;
	
}
.jx_tit {
	width:100px;
	height: 35px;
	line-height: 35px;
}
.jx_tit img{
	vertical-align: top;
	float: left;
}
.jx_tabs {
	list-style: none;
	margin-bottom: 0;
	height: 35px;
	margin-left: 120px;
}
.jx_tabs li {
	float: left;
	height: 35px;
	position: relative;			
}
.jx_tabs li span{
	display: inline-block;
    width: 110px;
    height: 33px;  
    border: 1px solid #f0f0f0;
    border-bottom: none;
    transform: skew(-30deg);
}
.jx_tabs li a{
	width: 110px;
    height: 35px;
    line-height: 35px;
    text-align: center;
    position: absolute;
    top: 0px;
    z-index: 99;
    text-decoration: none;
    color: #000;
    font-size: 16px;
}
.jx_tabs .active span {
	background: #ffc900;
	border:none;
}
.jx_tabs .active a{
	  color: #fff;
}


.jx_content .row, .guone_r .row {
    margin-right: -8px;
}
.jx_content a, .guone_r a{
	text-decoration: none;
	display: block;	
}
.jx_content .has_border, .guone_r .has_border{		
	border: 1px solid #eee;
	padding: 0 6px;
}
.jx_content h3, .guone_r h3 {
	margin: 5px 0;
    padding-right: 11px;
    font-size: 14px;
    color: #000;
    line-height: 24px;   
    overflow: hidden;
    font-weight: normal;
    background-color: #fff;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}
.jx_content img, .guone_r .row img {
	display: block;
    width: 100%;
}
.price {
	font-size: 12px;
	color: #666;
	padding-bottom: 17px;
}
.price em {
    font-size: 12px;
    font-style: normal;
    color: #ff4848;
}
.price strong {
    font-size: 18px;
    color: #ff4848;
}
.tab-content {
	margin-top: 10px;
}



/*国内游*/


.heima_gn{
	width: 100%;
    overflow: hidden;
}
.guonei_l, 
.guone_r {
	float: left;
}
.guonei_l {
	width:360px;
	height: 490px;
	margin-right: 50px;
	margin-top: 10px;
}
.guone_r {
	width:790px;
	height: 490px;
}
.guone_r .row>div {
	margin-top: 10px;
}


.fl {
	float: left;
	
}


index.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>
    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="css/common.css">
    <link rel="stylesheet" type="text/css" href="css/index.css">
	
	<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="js/jquery-3.3.1.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
    <!--导入布局js,共享header和footer-->
    <script type="text/javascript" src="js/include.js"></script>
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
	<!--引入头部-->
    <div id="header"></div>
    <!-- banner start-->
    <section id="banner">
        <div id="carousel-example-generic" class="carousel slide" data-ride="carousel" data-interval="2000">
            <!-- Indicators -->
            <ol class="carousel-indicators">
                <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
                <li data-target="#carousel-example-generic" data-slide-to="1"></li>
                <li data-target="#carousel-example-generic" data-slide-to="2"></li>
            </ol>
            <!-- Wrapper for slides -->
            <div class="carousel-inner" role="listbox">
                <div class="item active">
                    <img src="images/banner_1.jpg" alt="">
                </div>
                <div class="item">
                    <img src="images/banner_2.jpg" alt="">
                </div>
                <div class="item">
                    <img src="images/banner_3.jpg" alt="">
                </div>
            </div>
            <!-- Controls -->
            <a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
			    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
			    <span class="sr-only">Previous</span>
			  </a>
            <a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
			    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
			    <span class="sr-only">Next</span>
			  </a>
        </div>
    </section>
    <!-- banner end-->
    <!-- 旅游 start-->
    <section id="content">
         <!-- 精选start-->
        <section class="hemai_jx">
            <div class="jx_top">
                <div class="jx_tit">
                    <img src="images/icon_5.jpg" alt="">
                    <span>精选</span>
                </div>
                <!-- Nav tabs -->
                <ul class="jx_tabs" role="tablist">
                    <li role="presentation" class="active">
                        <span></span>
                        <a href="#popularity" aria-controls="popularity" role="tab" data-toggle="tab">人气旅游</a>
                    </li>
                    <li role="presentation">
                        <span></span>
                        <a href="#newest" aria-controls="newest" role="tab" data-toggle="tab">最新旅游</a>
                    </li>
                    <li role="presentation">
                        <span></span>
                        <a href="#theme" aria-controls="theme" role="tab" data-toggle="tab">主题旅游</a>
                    </li>
                </ul>
            </div>
            <div class="jx_content">
                <!-- Tab panes -->
                <div class="tab-content">
                    <div role="tabpanel" class="tab-pane active" id="popularity">
                        <div class="row">
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_4.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_4.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_4.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_4.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                        </div>
                    </div>
                    <div role="tabpanel" class="tab-pane" id="newest">
                        <div class="row">
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_1.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_1.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_1.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_1.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                        </div>
                    </div>
                    <div role="tabpanel" class="tab-pane" id="theme">
                        <div class="row">
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_2.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_2.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_2.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                            <div class="col-md-3">
                                <a href="javascript:;">
                                    <img src="images/jiangxuan_2.jpg" alt="">
                                    <div class="has_border">
                                        <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
                                        <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
                                    </div>
                                </a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
        <!-- 精选end-->
        <!-- 国内游 start-->
        <section class="hemai_jx">
            <div class="jx_top">
                <div class="jx_tit">
                    <img src="images/icon_6.jpg" alt="">
                    <span>国内游</span>
                </div>
            </div>
            <div class="heima_gn">
                <div class="guonei_l">
                    <img src="images/guonei_1.jpg" alt="">
                </div>
                <div class="guone_r">
                    <div class="row">
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
									<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                    </div>
                </div>
            </div>
        </section>
        <!-- 国内游 end-->
        <!-- 境外游 start-->
        <section class="hemai_jx">
            <div class="jx_top">
                <div class="jx_tit">
                    <img src="images/icon_7.jpg" alt="">
                    <span>境外游</span>
                </div>
            </div>
            <div class="heima_gn">
                <div class="guonei_l">
                    <img src="images/jiangwai_1.jpg" alt="">
                </div>
                <div class="guone_r">
                    <div class="row">
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
									<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                        <div class="col-md-4">
                            <a href="route_detail.html">
								<img src="images/jiangxuan_4.jpg" alt="">
								<div class="has_border">
									<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
									<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>									
								</div>
							</a>
                        </div>
                    </div>
                </div>
            </div>
        </section>
        <!-- 境外游 end-->
    </section>
    <!-- 旅游 end-->
   <!--导入底部-->
    <div id="footer"></div>

</body>
</html>

footer.html

 <!-- 尾部 start-->
    <footer id="footer">
        <div class="why_select">
            <dl>
                <dt class="fl">
                    <img src="images/icon_1.jpg" alt="">
                </dt>
                <dd>
                    <h1>产品齐全</h1>
                    <h2>产品全自主选,随心买</h2>
                </dd>
            </dl>
            <dl>
                <dt class="fl">
                    <img src="images/icon_2.jpg" alt="">
                </dt>
                <dd>
                    <h1>便利快捷</h1>
                    <h2>24小时不打烊,随时买</h2>
                </dd>
            </dl>
            <dl>
                <dt class="fl">
                    <img src="images/icon_3.jpg" alt="">
                </dt>
                <dd>
                    <h1>安全支付</h1>
                    <h2>知名支付工具,放心买</h2>
                </dd>
            </dl>
            <dl>
                <dt class="fl">
                    <img src="images/icon_4.jpg" alt="">
                </dt>
                <dd style="margin-right:0px;">
                    <h1>贴心服务</h1>
                    <h2>客服全年无休,安心买</h2>
                </dd>
            </dl>
        </div>
        <div class="company">
            <p>大熊科技股份有限公司 版权所有Copyright 2006-2018, All Rights Reserved 苏ICP备16007882</p>
        </div>
    </footer>

maven配置文件:pop.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>cn.itcast</groupId>
  <artifactId>travel</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <!--servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>


        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>3.1.1</version>
            <scope>compile</scope>
        </dependency>

        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>
        <!--jdbcTemplate-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.0.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.0.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>6.0.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>6.0.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
            <scope>compile</scope>
        </dependency>
        <!--beanUtils-->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
            <scope>compile</scope>
        </dependency>
        <!--jackson-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.14.1</version>
        </dependency>


<!--        &lt;!&ndash;javaMail&ndash;&gt;-->
        <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>
        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>

    </dependencies>


    <build>
        <!--maven插件-->
        <plugins>
            <!--jdk编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <!--tomcat插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <!-- tomcat7的插件, 不同tomcat版本这个也不一样 -->
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 -->
                    <port>80</port>
                    <!-- 项目访问路径  本例:localhost:9090,  如果配置的aa, 则访问路径为localhost:9090/aa-->
                    <path>/travel</path>
                </configuration>
            </plugin>

        </plugins>
    </build>
</project>

前台

表单校验

提升用户体验,并减轻服务器压力。

异步(ajax)提交表单

在此使用异步提交表单是为了获取服务器响应的数据。因为我们前台使用的是html作为视图层,不能够直接从servlet相关的域对象获取值,只能通过ajax获取响应数据

注册页面
register.css

.rg_layout{
	width: 100%;
	height: 585px;
	background: url(../images/register_bg.png) no-repeat center;
	background-size: 100% 780px;
	overflow: hidden;
}
.rg_layout .rg_form{
	width: 886px;
	height: 534px;
	background-color: #fff;
	margin:24px auto;
	border:8px solid #eeeeee;
	box-sizing: border-box;
}

.rg_layout .rg_form > .rg_form_left{
	width:256px;
	float: left;
	padding-top:20px;
	padding-left: 20px;
	box-sizing: border-box;
}
.rg_layout .rg_form > .rg_form_center{
	width:358px;
	float: left;
	padding-top:10px;
	box-sizing: border-box;
	font-size: 14px;
}
.rg_layout .rg_form > .rg_form_right{
	width:256px;
	float: right;
}

.rg_form > .rg_form_left > p:first-child{
	font-size: 20px;
	color:#ffcd26;
	
}
.rg_form > .rg_form_left > p:last-child{
	font-size: 20px;
	color: #a6a6a6;
}
.rg_form > .rg_form_center .td_left{
	width: 65px;
	text-align: right;
}
.rg_form > .rg_form_center table{
	vertical-align: top;
}
.rg_form > .rg_form_center table tr{
	height: 50px;
}
.rg_form > .rg_form_center .td_right{
	width: 293px;
}
.rg_form_center .td_right > input[type="text"],.rg_form_center .td_right > input[type="date"]{
	width: 256px;
	height: 32px;
	line-height: 32px;
	box-sizing: border-box;
	padding: 6px 12px;
	border-radius: 4px;
	border:1px solid #a6a6a6;
	float: right;
}
.rg_form > .rg_form_center .td_right.gender{
	padding-left: 40px;
	box-sizing: border-box;
}
.rg_form > .rg_form_center .td_right.check{
	padding-left: 36px;
	box-sizing: border-box;
}
.rg_form > .rg_form_center .td_right > .check{
	width: 118px;
	float: left;
	margin-right:14px;
}
.rg_form > .rg_form_center .td_right > .submit{
	width: 120px;
	height: 36px;
	line-height: 36px;
	background-color: #ffc900;
	font-size: 14px;
}
.rg_form > .rg_form_right >p{
	float: right;
	font-size: 14px;
	padding: 20px 12px 0 0;
	box-sizing: border-box;
}
.rg_form > .rg_form_right >p >a{
	color: #fc8989;
}

register.html

<!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">
		<!--导入jquery-->
		<script src="js/jquery-3.3.1.js"></script>
    </head>
	<script>
		//constants
		const username = "#username";
		const password = "#password";
		const notarize_password = "#notarizepassword";
        const email = "#email";
		const name="#name";
		const telephone = "#telephone";
		const birthday = "#birthday"
		const check_code_info = "#check";
		const errorMsg = "#errorMsg"
		const registerForm = "#registerForm"
		//method
		function border_null(value) {
			return $(value).css("border", "") && true
		}
		function border_red(value) {
			return $(value).css("border", "1px solid red") && false
		}
		function check(value,reg){
			return reg.test($(value).val())
					? border_null(value)
					: border_red(value);
		}
		function checkLength(value,length){
			let $value = $(value);
			return $value.val().length==length
					? border_null(value)
					: border_red(value);
		}
		//logic
		function checkUsername(){
			let reg_value = /^\w{8,20}$/;
			return check(username, reg_value);
		}
		function checkPassword(){
			let reg_value = /^\w{8,20}$/;
			return check(password, reg_value);
		}
		function checkNotarizePassword() {
			let npswdval = $(notarize_password);
			return npswdval.val() == $(password).val()
					? border_null(notarize_password)
					: border_red(notarize_password);
		}
		function checkEmail(){
			let reg_value = /^\w+@\w+\.\w+$/;
			return check(email,reg_value)
		}
		function checkName(){
			let reg_value = /^[a-zA-Z0-9_\u4e00-\u9fa5]{3,50}$/;
			return check(name,reg_value)
		}
		function checkTelePhone(){
			let reg_value = /^[1-9]{11}$/;
			return check(telephone,reg_value)
		}
		function checkBirthDay(){
			return checkLength(birthday, 10)
		}
		function checkCode(){
			return checkLength(check_code_info, 4)
		}
		function ischeck(){
			return checkUsername()
					&& checkPassword()
					&& checkNotarizePassword()
					&& checkEmail()
					&& checkName()
					&& checkTelePhone()
					&& checkBirthDay()
					&& checkCode()
		}
		//execute
		$(()=>{
			$(registerForm).submit(function (){
				if(ischeck()){
					$.post('registerUserServlet',$(this).serialize(),function(data){
						data.flag
								?location.href="register_ok.html"
								:$(errorMsg).html(data.errorMsg).css("color", "red");
					})
				}
				return false;
			})
			//失去焦点
			$(username).blur(checkUsername);
			$(password).blur(checkPassword);
			$(notarize_password).blur(checkNotarizePassword);
			$(email).blur(checkEmail);
			$(name).blur(checkName);
			$(telephone).blur(checkTelePhone);
			$(birthday).blur(checkBirthDay);
			$(check_code_info).blur(checkCode);
			//清除错误消息
			$(registerForm).click(()=>$(errorMsg).html('').css("color", ""))
		})
	</script>
	<body>
	<!--引入头部-->
	<div id="header"></div>
        <!-- 头部 end -->
    	<div class="rg_layout">
    		<div class="rg_form clearfix">
    			<div class="rg_form_left">
    				<p>新用户注册</p>
    				<p>USER REGISTER</p>
    			</div>
    			<div class="rg_form_center">
					<div id="errorMsg"></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="password">确认密码</label>
								</td>
								<td class="td_right">
									<input type="text" id="notarizepassword"  placeholder="请输入密码">
								</td>
							</tr>
    						<tr>
    							<td class="td_left">
    								<label for="email">Email</label>
    							</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>
		<!--导入布局js,共享header和footer-->
		<script type="text/javascript" src="js/include.js"></script>
    	
    </body>
</html>

注册成功页面

<!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">
		<!--导入jquery-->
		<script src="js/jquery-3.3.1.js"></script>
    </head>
    <body>
    <!--引入头部-->
    <div id="header"></div>
        <!-- 头部 end -->
    	<div style="text-align:center;red:yellow;font-weight:bold;height:150px;padding-top:100px;font-size:30px;">
    		<h4>恭喜,注册成功!请登录您的注册邮箱进行激活您的账号,激活后才能登录。</h4>
    	</div>
        <!--引入尾部-->
    	<div id="footer"></div>
    <!--导入布局js,共享header和footer-->
    <script type="text/javascript" src="js/include.js"></script>
    </body>
</html>

register_ok.html

<!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">
		<!--导入jquery-->
		<script src="js/jquery-3.3.1.js"></script>
    </head>
    <body>
    <!--引入头部-->
    <div id="header"></div>
        <!-- 头部 end -->
    	<div style="text-align:center;red:yellow;font-weight:bold;height:150px;padding-top:100px;font-size:30px;">
    		<h4>恭喜,注册成功!请登录您的注册邮箱进行激活您的账号,激活后才能登录。</h4>
    	</div>
        <!--引入尾部-->
    	<div id="footer"></div>
    <!--导入布局js,共享header和footer-->
    <script type="text/javascript" src="js/include.js"></script>
    </body>
</html>


后台
后台代码实现

编写RegistUserServlet

servlet

package cn.itcast.travel.web.servlet;

import cn.itcast.travel.domain.ResultInfo;
import cn.itcast.travel.domain.User;
import cn.itcast.travel.service.UserService;
import cn.itcast.travel.service.impl.UserServiceImpl;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;


import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Map;

@WebServlet(name = "registerUserServlet", value = "/registerUserServlet")
public class RegisterUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //验证校验
        String check = request.getParameter("check");
        //从session中获取验证码
        HttpSession session = request.getSession();
        String checkcode_session = (String)session.getAttribute("CHECKCODE_SERVER");
        session.removeAttribute("CHECKCODE_SERVER");
        if (checkcode_session == null || !checkcode_session.equalsIgnoreCase(check)) {
            ResultInfo info = new ResultInfo();
            info.setFlag(false);
            info.setErrorMsg("验证码错误");
            jsonWrite(request,response,info);
            return;
        }
        //调用注册用户接口
        register(request,response);
    }
    //注册用户
    public void register(HttpServletRequest request,HttpServletResponse response) throws IOException {
        //        获取数据
        Map<String, String[]> map = request.getParameterMap();
//        封装对象
        User user = new User();
        try {
            BeanUtils.populate(user, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
//        调用service完成注册
        UserService service = new UserServiceImpl();
        boolean flag = service.regist(user);
        ResultInfo info = new ResultInfo();
        if(flag){
            info.setFlag(true);
        }else {
            info.setFlag(false);
            info.setErrorMsg("注册失败");
        }
//        //将info对象序列化为json
        jsonWrite(request,response,info);
    }
    //对象序列化为json 并写回客户端
    public void jsonWrite(HttpServletRequest request,HttpServletResponse response ,ResultInfo info) throws IOException {
        //将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);
        response.getOutputStream().write(json.getBytes());
    }
}

servlet实现类

编写UserService以及UserServiceImpl

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) {
        //根据用户名查询用户对象
        User u = userDao.findByUsername(user.getUsername());
        //判断u是否为空
        if (u!= null) {
            //用户名存在,注册失败
            return false;
        }
        //置激活码,唯一字符串
        user.setCode(UuidUtil.getUuid());
        System.out.println(user.getCode());
        user.setStatus("N");
        //保存注册信息
        userDao.save(user);
        //激活邮件发送,邮件正文
        String content="<a href='http://localhost/travel/activeUserServlet?code="+user.getCode()+"'>点击激活码,完成激活</a>";
        MailUtils.sendMail(user.getEmail(),content,"激活邮件");
        System.out.println("发送成功");
        return true;
    }

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

    @Override
    public User login(User user) {
        return userDao.findByUsernameAndPassword(user.getUsername(), user.getPassword());
    }
}

dao实现类

编写UserDao以及UserDaoImpl

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 {
            String sql = "select * from tab_user where username =?";
            user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class), username);
        } catch (Exception e) {
        }
        return user;
    }
    @Override
    public void save(User user) {
        String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email,status,code) values(?,?,?,?,?,?,?,?,?)";
        int update = template.update(sql, user.getUsername(),
                user.getPassword(),
                user.getName(),
                user.getBirthday(),
                user.getSex(),
                user.getTelephone(),
                user.getEmail(),
                user.getStatus(),
                user.getCode()
        );
    }

    @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);
//            String sql = "select * from tab_user where code =?";
//            user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class), code);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }

    @Override
    public void updateStatus(User user) {
        String sql = "update tab_user set status ='Y' where uid =?";
        template.update(sql, user.getUid());
    }

    @Override
    public User findByUsernameAndPassword(String username, String password) {
        User user = null;
        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) {

        }

        return user;
    }
}

邮件激活

为什么要进行邮件激活?为了保证用户填写的邮箱是正确的。将来可以推广一些宣传信息,到用户邮箱中。

发送邮件

  1. 申请邮箱
  2. 开启授权码
  3. 在MailUtils中设置自己的邮箱账号和密码(授权码)

 邮件工具类:MailUtils,调用其中sendMail方法可以完成邮件发送

用户点击邮件激活

经过分析,发现,用户激活其实就是修改用户表中的status为‘Y’

 分析

 发送邮件代码:

 修改保存Dao代码,加上存储status和code 的代码逻辑

 激活代码实现:

ActiveUserServlet

package cn.itcast.travel.web.servlet;

import cn.itcast.travel.service.impl.UserServiceImpl;

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


@WebServlet(name = "activeUserServlet", value = "/activeUserServlet")
public class ActiveUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取激活码
        String code = request.getParameter("code");
        if (code != null){
            //2.调用service完成激活
            UserServiceImpl service = new UserServiceImpl();
            boolean flag =  service.active(code);

            //3.判断标记
            String msg = flag ?"激活成功,请<a href='login.html'>登录</a>":"激活失败,请联系管理员";
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(msg);
        }
    }
}

登录

分析

代码实现

前台代码

login.css

#login_wrap {
    width:100%;
    min-width: 1300px;
    overflow: hidden;
    position: relative;
}

.login-box {
    width: 360px;
    height: 450px;
    position: absolute;
    top: 50px;
    right:170px;
    background: #fff;
}
.title {
    height: 80px;
    line-height: 80px;
    background: #ffc900;
    font-size: 22px;
    padding:0 30px; 
}
.title img {
    float: left;
    margin-top: 12px;
    margin-right: 15px;
}
.login_inner {    
    overflow: hidden;
    padding: 10px 50px;    
}

.alert {
    margin: 0 auto;
    padding: 6px 10px;
    border: 1px solid transparent;   
    text-align: left;
    color: #a94442;
    background-color: #f2dede;
    border-color: #ebccd1;
    margin-bottom: 17px;
    font-size: 12px;
}
.login_inner form{
    width: 100%;
    overflow: hidden;
    padding-bottom: 15px;
    border-bottom: 1px solid #eee;
}
.login_inner input {
    display: inline-block;
    width: 246px;
    height: 26px;
    border: 1px solid #d8d8d8;   
    font-size: 14px;
    color: #666;
    line-height: 28px;
    padding: 6px 0 6px 12px;
    box-shadow: 0 0 5px #fff;
    outline: none;
    transition: box-shadow 0.25s linear 0s;
    -webkit-transition: box-shadow 0.25s linear 0s;
    margin-bottom: 17px;
}
.verify input {
    width: 95px;
    margin-right: 20px;
    float: left;
    margin-bottom: 0;
}

.submit_btn button {
    width: 120px;
    height: 40px;
    border: none;
    background-color: #ffa800;   
    text-align: center;
    line-height: 40px;
    color: #000;
    font-size: 18px;
    font-weight: bold;
    cursor: pointer;
    float: left;
}
.auto_login {
   margin-top: 15px;
}
.submit_btn .checkbox {
    float: left;
    width: 17px;
    margin: 7px 5px 0 54px;
}
.submit_btn  span {
    line-height: 35px;
}

.reg {
    border-top: 1px solid #eeeeee;
    margin-top: 15px;
    width: 100%;
    height: 40px;
    line-height: 40px;
    background: #f1f1f1;
    text-align: center;
    font-size: 16px;
}
.reg a {
    color: #fc7f7f;
}

login.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">
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
      <!--导入angularJS文件-->
    <script src="js/angular.min.js"></script>
	<!--导入jquery-->
	<script src="js/jquery-3.3.1.js"></script>
	<script>
		const btn_sub = "#btn_sub";
		const loginForm = "#loginForm";
		const errorMsg = "#errorMsg";
		$(()=>{
			$(btn_sub).click(function(){
				$.post("loginServlet",$(loginForm).serialize(),function (data){
					data.flag
							?location.href ="index.html"
							:$(errorMsg).html(data.errorMsg);
				})
			})
		})
	</script>
</head>

<body>
<!--引入头部-->
<div id="header"></div>
    <!-- 头部 end -->
    <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>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="js/jquery-1.11.0.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
    <!--导入布局js,共享header和footer-->
    <script type="text/javascript" src="js/include.js"></script>
</body>

</html>

后台代码
LoginServlet

package cn.itcast.travel.web.servlet;

import cn.itcast.travel.domain.ResultInfo;
import cn.itcast.travel.domain.User;
import cn.itcast.travel.service.impl.UserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet(name = "loginServlet", value = "/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取用户名和密码数据
        Map<String, String[]> map = request.getParameterMap();
        //2.封装User对象
        User user = new User();
        try {
            BeanUtils.populate(user, map);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        //3.调用Service查询
        UserServiceImpl service = new UserServiceImpl();
        User u = service.login(user);
        ResultInfo info = new ResultInfo();
        //4.判断用户对象是否为null
        if(u==null) {
            //用户名密码或错误
            info.setResultInfo(info,false, null, "用户名密码或错误");
        }
        //5.判断用户是否激活
        if (u!=null && "Y".equals(u.getStatus())){
            info.setResultInfo(info,false, null, "您尚未激活,请激活");
        }
        //6.判断登录成功
        if(u!=null && "Y".equals(u.getStatus())){
            request.getSession().setAttribute("user",u);
            info.setFlag(true);
        }
        //响应数据
        ObjectMapper mapper = new ObjectMapper();
        response.setContentType("application/json;charset=UTF-8");
        mapper.writeValue(response.getOutputStream(),info);
    }

}

index页面中用户姓名的提示信息功能

效果:

 header.html代码

<!-- 头部 start -->
<script>
    const span_username = "#span_username";
    const login = "#login";
    $(()=>{
        $.get("findUserServlet",{},function (data){
            let msg = "欢迎回来:"+data.name;
            $(span_username).html(msg)
            $(login).css("display","none")
        })
    })
</script>
    <header id="header">
        <div class="top_banner">
            <img src="images/top_banner.jpg" alt="">
        </div>
        <div class="shortcut">
            <!-- 未登录状态  -->
            <div class="login_out" id="login">
                <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-9090</p>
                    </div>
                </div>
            </div>
        </div>
    </header>
    <!-- 头部 end -->
     <!-- 首页导航 -->
    <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代码

package cn.itcast.travel.web.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;

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

@WebServlet(name = "findUserServlet", value = "/findUserServlet")
public class FindUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    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);
    }
}

退出

什么叫做登录了?session中有user对象。

实现步骤:

      1. 访问servlet,将session销毁
      2. 跳转到登录页面

代码实现:

Header.html

见上。
Servlet:

package cn.itcast.travel.web.servlet;

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

@WebServlet(name = "exitServlet", value = "/exitServlet")
public class ExitServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getSession().invalidate();
        response.sendRedirect(request.getContextPath()+"/login.html");
    }
}

猜你喜欢

转载自blog.csdn.net/qq1092881420/article/details/128752537