javaee之黑马旅游网1

news2024/11/16 18:41:01

这是一个用来锻炼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数据的时候,没有假如如下语句

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

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/61113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计小型银行管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

JavaWeb_第6章_FilterListenerAjax

JavaWeb_第6章_Filter&Listener&Ajax 文章目录JavaWeb_第6章_Filter&Listener&Ajax1&#xff0c;Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问…

最新版本zookeeper+dubbo-admin

zookeeper 下载地址 :https://archive.apache.org/dist/zookeeper/ 修改conf下zoo_sample.cfg - >zoo.cfgbin下启动zkServer.cmd启动成功 :binding to port 0.0.0.0/0.0.0.0:2181 问题1&#xff1a;zookeper安装 1.去官网下载apache-zookeeper-3.6.2-bin.tar.gz名字中带有…

通用的改进遗传算法求解带约束的优化问题(MATLAB代码)

目录 1 概述 2 遗传算法 2.1 遗传算法的基本概念 2.2 遗传算法的特点 2.3 程序框图 3 运行结果 4 通用的改进遗传算法求解带约束的优化问题&#xff08;MATLAB代码&#xff09; 1 概述 遗传算法(Genetic Algorithm,GA)是模拟生物在自然环境中的遗传和进化过程而形成的自…

Spark中宽依赖、窄依赖、Job执行流程

一、宽依赖和窄依赖的定义 【宽依赖&#xff1a;】 宽依赖表示同一个父&#xff08;上游&#xff09;RDD 的 Partition 被多个子&#xff08;下游&#xff09;RDD 的 Partition 依赖&#xff0c;会引起 Shuffle&#xff0c;总结&#xff1a;宽依赖我们形象的比喻为多生。有shu…

DPD(Digital Pre-Distortion,数字预失真)

什么是DPD 下图中图A是一个理想PA的输入输出关系&#xff0c;它具有线性特性&#xff0c;也就是说输出信号的功率与输入信号功率具有线性关系。但是&#xff0c;现实中使用的PA却不具备理想PA的线性特性。如图C所示&#xff0c;现实PA的输出与输入是非线性关系。为了让非理想P…

HCIA 笔记(1)

一、什么是计算机网络&#xff1a; 二、什么是云技术&#xff1f; 云技术 包含 云存储&#xff08;百度网盘&#xff09; 、云计算&#xff08;分布式计算&#xff09; 三、计算机技术是怎么实现的&#xff1f; 答&#xff1a;抽象语言&#xff08;高级语言、汇编语言等&…

数据库、计算机网络,操作系统刷题笔记7

数据库、计算机网络&#xff0c;操作系统刷题笔记7 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&…

用代码实现全自动化批量下单官网的 iPhone-14-Pro 集成智能下单购物系统,附源码可直接运行

用代码实现全自动化批量下单官网的 iPhone-14-Pro 集成智能下单购物系统,附源码可直接运行。 环境搭建: 1、首先打开谷歌浏览器 输入:chrome://version/ 查看浏览器的版本; 2、打开这个链接: http://chromedriver.storage.googleapis.com/index.html 找到和自己浏览器…

uni-app入门:HBuilderX安装与项目创建

1.HBuilderX下载与安装 2.新建 uni-app 项目并运行到微信开发者工具 1.HBuilderX下载与安装uni-app 官方推荐使用 HBuilderX 来开发 uni-app 类型的项目。 主要好处&#xff1a; 模板丰富 完善的智能提示 一键运行 当然&#xff0c;依然可以根据自己的喜好&#xff0c;选…

(附源码)php小型网络舆情平台设计 毕业设计 252324

小型网络舆情平台设计 摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用php技术建设…

作业11:优化算法比较

目录1. 编程实现图6-1&#xff0c;并观察特征2. 观察梯度方向3. 编写代码实现算法&#xff0c;并可视化轨迹4. 分析上图&#xff0c;说明原理&#xff08;选做&#xff09;1&#xff09; 为什么SGD会走“之字形”&#xff1f;其它算法为什么会比较平滑&#xff1f;2&#xff09…

C#获取子文件夹及其中所有的文件

首先用FolderBrowserDialog获取目标文件夹&#xff0c;如果不要求可视化也可以直接在文本框中输入&#xff0c;从其的SelectedPath属性中就可以获取目标路径。 FolderBrowserDialog folder new FolderBrowserDialog(); folder.ShowDialog(); string Root folder.SelectedPat…

三台机器搭建redis集群过程及问题记录

文章目录1. 前言2. 搭建集群3. 遇到的问题4. 相关文章1. 前言 Redis版本 5.0.4 服务器版本 Linux CentOS 6&#xff1b;CentOS 7&#xff1b;CentOS 9&#xff1b; redis集群需要至少要三个master节点&#xff0c;我们这里搭建三个master节点&#xff0c;并且给每个master再搭…

Spring boot 启动流程及外部化配置

平时我们开发Spring boot 项目的时候&#xff0c;一个SpringBootApplication注解加一个main方法就可以启动服务器运行起来&#xff0c;那它到底是怎么运行起来的呢&#xff1f; Main 入口 我们首先从main方法来看源码&#xff0c;逐步深入&#xff1a; SpringBootApplicatio…

Python实现Stacking回归模型(随机森林回归、极端随机树回归、AdaBoost回归、GBDT回归、决策树回归)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 Stacking通常考虑的是异质弱学习器&#xff08;不同的学习算法被组合在一起&#xff09;&#xff0c;st…

(附源码)SSM宠物领养系统 毕业设计 031654

SSM宠物领养系统 摘 要 如今&#xff0c;随着人们生活水平不断提高&#xff0c;人们的生活在物质满足的基础上&#xff0c;更多的人将生活的重点放在追求精神享受的过程中。于此同时&#xff0c;Internet铺天盖地的普及&#xff0c;使得这样的人纷纷通过Internet的方式去寻找精…

(十一) 共享模型之无锁【CAS 与 volatile】

一、问题引出&#xff08;P158&#xff09; 1. 取款案例 interface Account {// 获取余额Integer getBalance();// 取款void withdraw(Integer amount);/*** 方法内会启动 1000 个线程&#xff0c;每个线程做 -10 元 的操作* 如果初始余额为 10000 那么正确的结果应当是 0*/st…

Seata概述基础

分布式事务原因&#xff1a; 单体架构的spring事务不能跨机器&#xff0c;不能跨数据源 分布式事务的概念&#xff1a; 一个业务流程&#xff0c;在分布式系统&#xff08;微服务&#xff09;中&#xff0c;每个业务模块都是一个分支&#xff0c;保证每个业务分支一起成功&am…

ROS1 LTS版本安装教程

Abstract: "ROS is primarily targeted at the Ubuntu , though other Linux systems as well as Mac OS X, Android, and Windows are supported to varying degrees. " 一、系统要求 ROS版本系统版本长期支持ROS Kinetic KameWily: amd64、i386 Xenial: amd64、i…