项目导入
选择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;
--创建表
复制提供好的sql
注册功能
页面效果
功能分析
代码实现
前台代码实现
User具体类
package cn.itcast.travel.domain;import java.io.Serializable;/*** 用户实体类*/
public class User implements Serializable {private int uid;//用户idprivate 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,发生异常返回falseprivate 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.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.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>//constantsconst 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"//methodfunction 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);}//logicfunction 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>
后台
后台代码实现
编写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 {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected 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对象序列化为jsonjsonWrite(request,response,info);}//对象序列化为json 并写回客户端public void jsonWrite(HttpServletRequest request,HttpServletResponse response ,ResultInfo info) throws IOException {//将info对象序列化为jsonObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(info);//将json数据写回客户端
// 设置content-typeresponse.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*/@Overridepublic 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;}@Overridepublic boolean active(String code) {//1.根据激活码查询用户对象User user = userDao.findByCode(code);if (user !=null) {//2.调用dao的修改激活状态的方法userDao.updateStatus(user);return true;}else {return false;}}@Overridepublic 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());@Overridepublic 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;}@Overridepublic 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());}@Overridepublic 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;}@Overridepublic void updateStatus(User user) {String sql = "update tab_user set status ='Y' where uid =?";template.update(sql, user.getUid());}@Overridepublic 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 {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected 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.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 {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected 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.判断用户对象是否为nullif(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 {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected 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 {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.getSession().invalidate();response.sendRedirect(request.getContextPath()+"/login.html");}
}