javaee之黑马旅游网1

这是一个用来锻炼javaweb基础知识的项目,先来导入一些我们准备好的文件

下面这些东西是我们项目必备的,我们提前准备好了 ,这个我会上传到我的资源,你们可以自己去下载

利用maven来创建一个项目

选择无骨架创建项目,域名、项目名、版本号

 把该导入的东西全部导入进来

上面的初级项目我会直接打包放到资源里面,你们可以直接Maven导入就行

导入完了项目之后, 我们用maven运行一下项目

然后去访问下面这个位置

 展示

下面我们来说一下整体需要用到的技术,从三个层面来进行分析

web层:

service层:

dao层:

下面主要是先来做注册与登录的功能

先来创建数据库和相应的数据表

这里涉及到大量插入的sql数据,文章数据太大粘贴不上来,我还是放到资源里面去,可以直接下载,这里就贴一部分

set names utf8;

drop table if exists tab_favorite;
drop table if exists tab_route_img;
drop table if exists tab_route;
drop table if exists tab_category;
drop table if exists tab_seller;
drop table if exists tab_user;

/*==============================================================*/
/* Table: tab_category                                          */
/*==============================================================*/
create table tab_category
(
   cid                  int not null auto_increment,
   cname                varchar(100) not null,
   primary key (cid),
   unique key AK_nq_categoryname (cname)
);

/*==============================================================*/
/* Table: tab_favorite                                          */
/*==============================================================*/
create table tab_favorite
(
   rid                  int not null,
   date                 date not null,
   uid                  int not null,
   primary key (rid, uid)
);

/*==============================================================*/
/* Table: tab_route                                             */
/*==============================================================*/
create table tab_route
(
   rid                  int not null auto_increment,
   rname                varchar(500) not null,
   price                double not null,
   routeIntroduce       varchar(1000),
   rflag                char(1) not null,
   rdate                varchar(19),
   isThemeTour          char(1) not null,
   count                int default 0,
   cid                  int not null,
   rimage               varchar(200),
   sid                  int,
   sourceId             varchar(50),
   primary key (rid),
   unique key AK_nq_sourceId (sourceId)
);

/*==============================================================*/
/* Table: tab_route_img                                         */
/*==============================================================*/
create table tab_route_img
(
   rgid                 int not null auto_increment,
   rid                  int not null,
   bigPic               varchar(200) not null,
   smallPic             varchar(200),
   primary key (rgid)
);

/*==============================================================*/
/* Table: tab_seller                                            */
/*==============================================================*/
create table tab_seller
(
   sid                  int not null auto_increment,
   sname                varchar(200) not null,
   consphone            varchar(20) not null,
   address              varchar(200),
   primary key (sid),
   unique key AK_Key_2 (sname)
);

/*==============================================================*/
/* Table: tab_user                                              */
/*==============================================================*/
create table tab_user
(
   uid                  int not null auto_increment,
   username             varchar(100) not null,
   password             varchar(32) not null,
   name                 varchar(100),
   birthday             date,
   sex                  char(1),
   telephone            varchar(11),
   email                varchar(100),
   status               char(1) ,
   code					varchar(50),
   
   primary key (uid),
   unique key AK_nq_username (username),
   unique key AK_nq_code (code)
);

alter table tab_favorite add constraint FK_route_favorite foreign key (rid)
      references tab_route (rid) on delete restrict on update restrict;

alter table tab_favorite add constraint FK_user_favorite foreign key (uid)
      references tab_user (uid) on delete restrict on update restrict;

alter table tab_route add constraint FK_category_route foreign key (cid)
      references tab_category (cid) on delete restrict on update restrict;

alter table tab_route add constraint FK_seller_route foreign key (sid)
      references tab_seller (sid) on delete restrict on update restrict;

alter table tab_route_img add constraint FK_route_routeimg foreign key (rid)
      references tab_route (rid) on delete restrict on update restrict;
	  
	  
insert  into `tab_category`(`cid`,`cname`) values (8,'全球自由行'),(5,'国内游'),(4,'处境游'),(7,'抱团定制'),(6,'港澳游'),(2,'酒店'),(1,'门票'),(3,'香港车票');
insert  into `tab_seller`(`sid`,`sname`,`consphone`,`address`) values (1,'黑马程序员','12345678901','传智播客javaEE学院');


/*Data for the table `tab_route` */

insert  into `tab_route`(`rid`,`rname`,`price`,`routeIntroduce`,`rflag`,`rdate`,`isThemeTour`,`count`,`cid`,`rimage`,`sid`,`sourceId`) values (1,'【旅展 半价特惠 重走丝路•漫游宁夏 双飞4天】银川西部影视城 穆民新村 中卫沙坡头【品美酒 回族学唱花儿 感悟民俗】',999,'走进【宁夏沙坡头】,感受西北大漠风情、体会“大漠孤烟直,长河落日圆”的塞上风光!','1','2018-02-09 01:13:16','0',0,5,'img/product/small/m304b69a4c8328f7d6b8d5dadef020fe07.jpg',1,'23677')

先按照上面给的创建表与数据的语句,把表和数据插入进去,后来再来分析表与表之间的关系,在次之前我们需要创建一个项目对应的库。比如travel

拿到这个数据库之后,再来执行相应的sql语句,把这些表都创建好 

 

上面这些表也可以先不用创建,我们等会直接采用source sql语句位置 ,先来看一下我这个sql语句的位置

直接导入这个语句的位置

先来实现注册功能

注册功能实现原理

下面再来说一下,表单校验需要注意的一些问题:

        1.用户名:单词字符,长度8到20位

        2.密码:单词字符,长度8到20位

        3.email:邮件格式

        4.姓名:非空

        5.手机号:十一位全数字,第一位按照1开头

        6.出生日期:非空

        7.验证码:非空

先看一下前端界面

上面这些框都要做一些检查,也就是会单独写一个js函数来判断是否合理,有一点我们需要注意的是,当表单框失去焦点的时候,就要调用这个函数进行判断

先把这部分代码给贴过来

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>
		<script type="text/javascript">
			//先来检验用户名
			function checkUsername() {
				//拿到用户名的值
				//这里通过jquery来获取值
				var username = $("#username").val();//输入框里面的值
				//定义一个正则,规定输入格式
				//这里的意思就是匹配字母数字下划线,最少8个,最多20个
				var regUsername = /^\w{8,20}$/;//这就是一个正则表达式对象
				//这里调用js对象里面的test判断字符串与正则是否匹配
				var flag = regUsername.test(username);
				//
				if(flag) {
					//输入正确,就成正常的颜色,
					//你这如果啥也不做,那么一旦框变红了
					//那就不能变回来啦
					$("#username").css("border","");
				} else {
					//输入错误,让边框变成红色
					$("#username").css("border","1px solid red");
				}
				return flag;//决定表单能否提交
			}

			//检验密码
			function checkPassword() {
				//获取密码
				var password = $("#password").val();
				//定义正则,和上面一样操作
				var regPassword = /^\w{8,20}$/;
				//用test判断
				var flag = regPassword.test(password);
				if(flag) {
					//也不能啥也不做
					$("#password").css("border","");
				} else {
					//把边框变成红色
					$("#password").css("border","1px solid red");
				}
				return flag;
			}

			//检验邮件
			function checkEmail() {
				//获取邮件
				//邮件的操作性质与上面基本一样
				var email = $("#email").val();
				var regEmail = /^\w+@\w+\.\w+$/;
				var flag = regEmail.test(email);
				if(flag) {
					$("#email").css("border","");
				} else {
					$("#email").css("border","1px solid red");
				}
				return flag;
			}

			//然后要进行异步的ajax请求
			//当失去焦点的时候,就要进行一个检验
			//利用jquery来实现ajax对吗
			$(function(){
				//当表单提交的时候,我们要干嘛
				//是不是要提交检测,也就是上面js做的一些检测函数
				//如果返回false,是不是就相当于说,你不能提交
				//获取表单,然后添加一个提交事件
				$("#registerForm").submit(function (){
					//上面函数都有一个布尔类型的值
					//这里进行一个联合判断
					return checkUsername() && checkPassword() && checkEmail();
				});

				//当失去焦点的时候,进行一个正则检查
				//也就是说是否符合规则
				//拿到这个input框框,然后给一个失去焦点的事件
				$("#username").blur(checkUsername);
				$("#password").blur(checkPassword);
				$("#email").blur(checkEmail);
			});

		</script>
    </head>
	<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">
					
					<!--注册表单-->
    				<form id="registerForm">
						<!--提交处理请求的标识符-->
						<input type="hidden" name="action" value="register">
    					<table style="margin-top: 25px;">
    						<tr>
    							<td class="td_left">
    								<label for="username">用户名</label>
    							</td>
    							<td class="td_right">
    								<input type="text" id="username" name="username" placeholder="请输入账号">
    							</td>
    						</tr>
    						<tr>
    							<td class="td_left">
    								<label for="password">密码</label>
    							</td>
    							<td class="td_right">
    								<input type="text" id="password" name="password" placeholder="请输入密码">
    							</td>
    						</tr>
    						<tr>
    							<td class="td_left">
    								<label for="email">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>

那么上面还有一部分我们需要修改

 这里一点击注册,就必须给我们提交数据啊,也就是我们需要在这里做一个异步的ajax请求

直接改动上面的register.htm里面的这部分代码

$(function(){
				//当表单提交的时候,我们要干嘛
				//是不是要提交检测,也就是上面js做的一些检测函数
				//如果返回false,是不是就相当于说,你不能提交
				//获取表单,然后添加一个提交事件
				$("#registerForm").submit(function (){
					//上面的正则检测全部通过,就提交请求
					if(checkEmail() && checkPassword() && checkUsername()) {
						//第二个直接把表单序列化成格式字符串往服务器传递
						$.post("registUserServlet",$(this).serialize(),function(data){

						});
					}
					//上面没有通过,这里就不提交表单,直接返回false
					return false;
				});

也就是说,上面的页面是往registUserServlet提交的,那么我们就要后台实现这个页面

我们知道一个servlet页面后面都会跟着访问servcie层,然后访问dao层,所以这里先把每一个层的文件实现出来,就是这个图下面的所有文件

把相应的文件先全部创建出来

先来做RegistUserServlet文件 

package web.servlet;

import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取从前端传过来的数据
        Map<String,String[]> map = request.getParameterMap();
        //把这些集合数据封装成一个对象
        //这里利用BeanUtils工具
        User user = new User();//这个user类之前就已经做好了
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //调用service中的方法完成注册
        UserService service = new UserServiceImpl();
        //内部我们先假定存在一个regist方法
        boolean flag = service.regist(user);
        //响应结果
        

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

代码写到上面这样,我们就必须来说一下,我们假定了一个regist方法在service里面,那么我们就要去到service里面实现这样的方法

去到我们的UserService里面

package service;

import domain.User;

public interface UserService {
    /**
     * @describe 注册用户
     * @param user
     * @return
     */
    boolean regist(User user);
}

然后在UserServiceImpl里面实现这个方法

package service.impl;

import domain.User;
import service.UserService;

public class UserServiceImpl implements UserService {

    /**
     * @describe 注册用户
     * @param user
     * @return
     */
    @Override
    public boolean regist(User user) {
        //这里大致分成两步走,每一步都对应dao的两个功能
        //第一步根据用户名来查询对象

        //第二步保存用户信息

        return false;
    }
}

当我们去分析service里面的regist方法的时候,发现需要去调用dao层的两个方法,一个是通过用户名来查询用户,另外一个是保存用户信息,那么我们又要去到dao层实现这两个方法

先来看UserDao

package dao;

import domain.User;

public interface UserDao {

    /**
     * 通过用户名查找用户
     * @param name
     * @return
     */
    public User findByUsername(String name);

    /**
     * 保存
     * @param user
     */
    public void save(User user);
}

再去看UserDaoImpl

package dao.impl;

import dao.UserDao;
import domain.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import util.JDBCUtils;

public class UserDaoImpl implements UserDao {

    //这里要操作数据库,所以我们需要一个JdbcTemplate模板
    //这个模板大家都知道需要一个连接池Druid的连接池
    //我们已经在JDBCUtils里面做好了
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 根据用户名查找用户
     *
     * @param name
     * @return
     */
    @Override
    public User findByUsername(String name) {
        //1.定义sql
        String sql = "select * from tab_user where username = ?";
        //2.执行sql
        //这里必须清楚我们要用到JdbcTemplate模板中的哪一个方法
        //比如这里通过用户名查询只会返回一个对象,就用queryForObject(sql,BeanPropertyRowMapper)
        //注意这个方法存在很多重载的方法
        User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), name);
        return user;
    }

    /**
     * 保存用户信息到数据库中
     * 这里在做数据库插入的时候,注意数据要与数据表中的数据一一匹配
     * @param user
     */
    @Override
    public void save(User user) {
        //1.定义sql
        String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email)" +
                "values (?,?,?,?,?,?,?)";
        //执行sql,获取响应的数据然后插进去
        template.update(sql,user.getUsername(),
                user.getPassword(),
                user.getName(),
                user.getSex(),
                user.getTelephone(),
                user.getEmail());
    }

}

然后再去完成我们的service层,这一层主要是去调用dao层的方法

这里就是UserServiceImpl.java

package service.impl;

import dao.UserDao;
import dao.impl.UserDaoImpl;
import domain.User;
import service.UserService;

public class UserServiceImpl implements UserService {

    private UserDao userDao = new UserDaoImpl();
    /**
     * @describe 注册用户
     * @param user
     * @return
     */
    @Override
    public boolean regist(User user) {
        //这里大致分成两步走,每一步都对应dao的两个功能
        //第一步根据用户名来查询对象
        User u = userDao.findByUsername(user.getUsername());
        //这里需要判断一下用户是否注册成功
        if(u != null) {
            //用户名存在,注册失败
            return false;
        }
        //第二步保存用户信息
        userDao.save(u);
        return true;
    }
}

有个地方我们需要注意

这里findByUsername能不能返回null,去看一下这个位置 

上面红色箭头指向的位置,会抛出一个异常,换句话也就是说,这里如果查询失败不会给我们返回一个NULL,所以必须把这个位置捕获一下异常

也就是说在UserDaoImpl文件中,把这个findByUsername方法修改一下

 /**
     * 根据用户名查找用户
     *
     * @param name
     * @return
     */
    @Override
    public User findByUsername(String name) {
        User user = null;//先定义一个null,等会好返回
        //1.定义sql
        String sql = "select * from tab_user where username = ?";
        //2.执行sql
        //这里必须清楚我们要用到JdbcTemplate模板中的哪一个方法
        //比如这里通过用户名查询只会返回一个对象,就用queryForObject(sql,BeanPropertyRowMapper)
        //注意这个方法存在很多重载的方法
        try {
            user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), name);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return user;
    }

上面做完了之后,基本上就可以实现用户的添加注册了,把RegistUserServlet页面修改一下,因为这个页面给我们的提示信息不够完整,比如找到用户给我们返回一个什么信息,没找到用户又给我们返回一个什么信息

首先我们到domain包里面去看一个类ResultInfo

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

上面也就是说,把后端传递给前端的信息,封装到一个对象里面,后面我们可以把这个对象转换成json对象,返回给前端,前端就可以通过这个对象来得到相应的数据,比如通过falg去判断是否查找正常,通过errorMsg来打印出相应的错误信息。

然后我们来看修改之后的RegisterUserServlet

package web.servlet;

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //验证校验

        //获取从前端传过来的数据
        Map<String,String[]> map = request.getParameterMap();
        //把这些集合数据封装成一个对象
        //这里利用BeanUtils工具
        User user = new User();//这个user类之前就已经做好了
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //调用service中的方法完成注册
        UserService service = new UserServiceImpl();
        //内部我们先假定存在一个regist方法
        boolean flag = service.regist(user);
        //做一个信息结果返回的对象
        ResultInfo info = new ResultInfo();
        //响应结果
        //注册成功返回true,失败返回false
        if(flag) {
            //成功
            //成功
            info.setFlag(true);
        } else {
            info.setFlag(false);
            info.setErrorMsg("注册失败");
        }

        //将info对象序列化为json对象
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(info);

        //将json数据写回给客户端
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

我们现在去把验证码的东西做一下,还是去到RegistUserServlet里面,进行一个验证码校验,这里的意思就是,验证码不通过,啥都免谈

验证码之前我们已经做好了,我们把这个CheckCodeServlet页面给贴过来

package web.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * 验证码
 */
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		
		//服务器通知浏览器不要缓存
		response.setHeader("pragma","no-cache");
		response.setHeader("cache-control","no-cache");
		response.setHeader("expires","0");
		
		//在内存中创建一个长80,宽30的图片,默认黑色背景
		//参数一:长
		//参数二:宽
		//参数三:颜色
		int width = 80;
		int height = 30;
		BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		
		//获取画笔
		Graphics g = image.getGraphics();
		//设置画笔颜色为灰色
		g.setColor(Color.GRAY);
		//填充图片
		g.fillRect(0,0, width,height);
		
		//产生4个随机验证码
		String checkCode = getCheckCode();
		//将验证码放入HttpSession中
		request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
		
		//设置画笔颜色为黄色
		g.setColor(Color.YELLOW);
		//设置字体的小大
		g.setFont(new Font("黑体",Font.BOLD,24));
		//向图片上写入验证码
		g.drawString(checkCode,15,25);
		
		//将内存中的图片输出到浏览器
		//参数一:图片对象
		//参数二:图片的格式,如PNG,JPG,GIF
		//参数三:图片输出到哪里去
		ImageIO.write(image,"PNG",response.getOutputStream());
	}
	/**
	 * 产生4位随机字符串 
	 */
	private String getCheckCode() {
		String base = "0123456789ABCDEFGabcdefg";
		int size = base.length();
		Random r = new Random();
		StringBuffer sb = new StringBuffer();
		for(int i=1;i<=4;i++){
			//产生0到size-1的随机值
			int index = r.nextInt(size);
			//在base字符串中获取下标为index的字符
			char c = base.charAt(index);
			//将c放入到StringBuffer中去
			sb.append(c);
		}
		return sb.toString();
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request,response);
	}
}



下面去完善一下RegistUserServlet.java页面,加入验证码检验功能

package web.servlet;

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //验证校验
        String check = request.getParameter("check");
        //从session中获取验证码
        //这个是做验证码的时候,就给我们放到服务器里面了
        String checkcodeServer = (String)request.getSession().getAttribute("CHECKCODE_SERVER");
        //这里判断一下验证码是否是正确的,如果不正确,直接return结束
        if(checkcodeServer == null || !check.equalsIgnoreCase(checkcodeServer)) {
            //这里验证码错误
            //还是调用一个后端结果信息处理对象
            ResultInfo resultInfo = new ResultInfo();
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("验证码错误");
            //将resultInfo对象转变为json对象,响应给请求端
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(resultInfo);

            //设置响应格式并且传送数据
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json);
            //让程序在这个位置结束,不往下执行了
            return;
        }
        //获取从前端传过来的数据
        Map<String,String[]> map = request.getParameterMap();
        //把这些集合数据封装成一个对象
        //这里利用BeanUtils工具
        User user = new User();//这个user类之前就已经做好了
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //调用service中的方法完成注册
        UserService service = new UserServiceImpl();
        //内部我们先假定存在一个regist方法
        boolean flag = service.regist(user);
        //做一个信息结果返回的对象
        ResultInfo info = new ResultInfo();
        //响应结果
        //注册成功返回true,失败返回false
        if(flag) {
            //成功
            //成功
            info.setFlag(true);
        } else {
            info.setFlag(false);
            info.setErrorMsg("注册失败");
        }

        //将info对象序列化为json对象
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(info);

        //将json数据写回给客户端
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

上面基本上就能够实现了数据库注册了,我们修改一下前端页面,改写异步向服务器registUserServlet页面提交数据

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>
		<script type="text/javascript">
			//先来检验用户名
			function checkUsername() {
				//拿到用户名的值
				//这里通过jquery来获取值
				var username = $("#username").val();//输入框里面的值
				//定义一个正则,规定输入格式
				//这里的意思就是匹配字母数字下划线,最少8个,最多20个
				var regUsername = /^\w{8,20}$/;//这就是一个正则表达式对象
				//这里调用js对象里面的test判断字符串与正则是否匹配
				var flag = regUsername.test(username);
				//
				if(flag) {
					//输入正确,就成正常的颜色,
					//你这如果啥也不做,那么一旦框变红了
					//那就不能变回来啦
					$("#username").css("border","");
				} else {
					//输入错误,让边框变成红色
					$("#username").css("border","1px solid red");
				}
				return flag;//决定表单能否提交
			}

			//检验密码
			function checkPassword() {
				//获取密码
				var password = $("#password").val();
				//定义正则,和上面一样操作
				var regPassword = /^\w{8,20}$/;
				//用test判断
				var flag = regPassword.test(password);
				if(flag) {
					//也不能啥也不做
					$("#password").css("border","");
				} else {
					//把边框变成红色
					$("#password").css("border","1px solid red");
				}
				return flag;
			}

			//检验邮件
			function checkEmail() {
				//获取邮件
				//邮件的操作性质与上面基本一样
				var email = $("#email").val();
				var regEmail = /^\w+@\w+\.\w+$/;
				var flag = regEmail.test(email);
				if(flag) {
					$("#email").css("border","");
				} else {
					$("#email").css("border","1px solid red");
				}
				return flag;
			}

			//然后要进行异步的ajax请求
			//当失去焦点的时候,就要进行一个检验
			//利用jquery来实现ajax对吗
			$(function(){
				//当表单提交的时候,我们要干嘛
				//是不是要提交检测,也就是上面js做的一些检测函数
				//如果返回false,是不是就相当于说,你不能提交
				//获取表单,然后添加一个提交事件
				$("#registerForm").submit(function (){
					//上面的正则检测全部通过,就提交请求
					if(checkEmail() && checkPassword() && checkUsername()) {
						//第二个直接把表单序列化成格式字符串往服务器传递
						//通过ajax进行异步提交数据
						$.post("registUserServlet",$(this).serialize(),function(data){
							//处理服务器的响应结果
							//服务器给我们响应的数据

						});
					}
					//上面没有通过,这里就不提交表单,直接返回false
					return false;
				});

				//当失去焦点的时候,进行一个正则检查
				//也就是说是否符合规则
				//拿到这个input框框,然后给一个失去焦点的事件
				$("#username").blur(checkUsername);
				$("#password").blur(checkPassword);
				$("#email").blur(checkEmail);
			});

		</script>
    </head>
	<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">
					
					<!--注册表单-->
    				<form id="registerForm">
						<!--提交处理请求的标识符-->
						<input type="hidden" name="action" value="register">
    					<table style="margin-top: 25px;">
    						<tr>
    							<td class="td_left">
    								<label for="username">用户名</label>
    							</td>
    							<td class="td_right">
    								<input type="text" id="username" name="username" placeholder="请输入账号">
    							</td>
    						</tr>
    						<tr>
    							<td class="td_left">
    								<label for="password">密码</label>
    							</td>
    							<td class="td_right">
    								<input type="text" id="password" name="password" placeholder="请输入密码">
    							</td>
    						</tr>
    						<tr>
    							<td class="td_left">
    								<label for="email">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>

现在去访问注册页面,先在注册页面填写一些数据

然后点击注册就会发送一个请求到registUserServlet页面

先在去看数据库内部有没有插上这条数据

 很明显就是数据插入也没有问题。

上面在处理数据的时候,没有处理数据编码问题,是因为我们已经通过filter进行过滤了,直接在filter包里面放了如下文件

CharchaterFilter.java

package web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 解决全站乱码问题,处理所有的请求
 */
@WebFilter("/*")
public class CharchaterFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse rep, FilterChain filterChain) throws IOException, ServletException {
        //将父接口转为子接口
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) rep;
        //获取请求方法
        String method = request.getMethod();
        //解决post请求中文数据乱码问题
        if(method.equalsIgnoreCase("post")){
            request.setCharacterEncoding("utf-8");
        }
        //处理响应乱码
        response.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

 下面我们要去做如下部分

 在register.html页面处理一下服务器响应过来的数据

这里很明显servlet会给我们响应一个对象的信息的json数据的格式

 

 

在前端页面这个位置增加提示信息

 好了,来说一下注册成功的情况,如果注册成功,就跳转到一个一个注册成功页面,这里我们也已经做好了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>

如果注册失败了,就给刚刚那个div,就是需要我们添加错误信息的div提示一些错误信息 

现在把服务器关掉重新启动一下

我刻意把验证码写错或者把用户名写成数据库当中已经存在的用户名,并没有给我提示错误,于是去看一下控制台

发现好像给我们response的json数据也没有写错,于是再去检查一下

 发现这个M应该是小写的m

然后刻意把验证码写错

如果把用户名写错,程序就会走这个地方

 

简单说就是用户名已经存在,就会提示注册失败这条路

刚刚我改变了一下输入验证码正确,然后用户名输入与数据库里插入的名字相同

但是发现数据有,但是回写到html页面,缺提示undefined

插入一个测试代码 

 

 

 看一下网页中的数据传输

发现数据是存在的,那么为什么会提示undefined呢 ?

原因就在于回写json数据的时候,没有假如如下语句

 然后重新启动服务器,提示注册失败,运行成功

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值