项目导入
选择travel项目的pom.xml文件,点击ok,完成项目导入。需要等待一小会,项目初始化完成。
启动项目
方式一:
方式二:配置maven快捷启动
技术选型
Web层
- Servlet:前端控制器
- html:视图
- Filter:过滤器
- BeanUtils:数据封装
- Jackson:json序列化工具
Service层
- Javamail:java发送邮件工具
- Redis:nosql内存数据库
- Jedis:java的redis客户端
Dao层
- Mysql:数据库
- Druid:数据库连接池
- JdbcTemplate:jdbc的工具
创建数据库
-- 创建数据库
CREATE DATABASE travel;
-- 使用数据库
USE travel;
--创建表
注册功能
页面效果
功能分析
代码实现
前台代码实现
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;
}
}
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>
<!-- <!–javaMail–>-->
<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;
}
}
邮件激活
为什么要进行邮件激活?为了保证用户填写的邮箱是正确的。将来可以推广一些宣传信息,到用户邮箱中。
发送邮件
- 申请邮箱
- 开启授权码
- 在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对象。
实现步骤:
-
-
- 访问servlet,将session销毁
- 跳转到登录页面
-
代码实现:
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");
}
}