黑马旅游网案例
##模块一 用户注册与登录页面
## 1. 前端html页面 ##
(1)判断输入数据类型是否合理
如限制用户名的长度,email的格式等
因此这里要使用js配合正则表达式来进行判断;
function checkUsername(){
//1.获取用户名
var username=$("#username").val();
//2.定义正则
var reg_username=/^\w{8,20}$/;
//3.完成判断,给出提示信息
var flag=reg_username.test(username);
if(flag){
//校验通过
$("#username").css("border","");
}else {
$("#username").css("border","1px solid red");
}
return flag;
}
当对应的组件失去焦点时执行对应的check方法;
当表单提交时,执行所有的check方法;
(2)使用ajax完成异步转发
为注册按钮添加submit事件
在转发前首先要进行判断,如果数据类型不合理,则不提交数据,还是返回该页面;如果数据类型合理,则提交表单数据;
if(checkUsername()&&checkPassword()&&checkEmail())
(3)表单数据提交后的跳转
提交表单数据里面的特殊方法$("form").serialize()方法
如果注册成功,即用户名不存在且合理的话,跳转到register_ok页面
location.href="register_ok.html";
如果注册失败,即用户名已经存在,在form表单的上方打印错误信息
<div id="errorMsg" style="color: red;text-align: center"></div>
$("#errorMsg").html(data.errorMsg);
----------
## 2.Servlet页面 ##
(1)CheckCodeServlet——验证码的Servlet
package cn.itcast.travel.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个随机验证码,12Ey
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);
}
}
----------
(2)RegistUserServlet
----------
在进行表单数据的校验之前,先进行验证码的校验;伪代码即:if(校验码通过){则进行数据表单的校验}else{返回html页面,info存入false和msg,序列化为json并写入客户端}。
String check = request.getParameter("check");
//从session中获取验证码
HttpSession session = request.getSession();
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
//为了避免复用,session使用过之后立马移出——保证验证码只使用一次.
session.removeAttribute("CHECKCODE_SERVER");
//比较
//如果校验通过,直接执行下面的逻辑
if (checkcode_server==null||!checkcode_server.equalsIgnoreCase(check)){
//如果校验失败,返回html页面
ResultInfo info=new ResultInfo();
info.setFlag(false);
info.setErrorMsg("验证码错误!");
//响应回客户端
ObjectMapper mapper=new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return;
}
注意:1.序列化与write重复书写,可以编写方法优化;
2.为了避免空指针异常,判断条件除了不相等之外还需要
checkcode_server==null
----------
后续操作:
1. 获取提交的表单数据;
2. 封装user对象;
3. 调用service方法进行操作;
4. 根据service的返回值进行判断。
----------
1.将参数封装成map集合
`Map<String, String[]> map = request.getParameterMap();`
2.封装对象
BeanUtils.populate(user,map);
这个方法会将map集合对应的数据封装到user对应的属性中去。
3.调用service方法,获得返回值,根据返回值进行判断
UserService service=new UserServiceImpl();
boolean flag=service.regist(user);
4.创建resultInfo实体类,封装后端返回前端的数据对象
package cn.itcast.travel.domain;
import java.io.Serializable;
import java.util.Objects;
/**
* 用于封装后端返回前端数据对象
*/
public class ResultInfo implements Serializable {
private boolean flag;//后端返回结果正常为true,发生异常返回false
private Object data;//后端返回结果数据对象
private String errorMsg;//发生异常的错误消息
//无参构造方法
public ResultInfo() {
}
public ResultInfo(boolean flag) {
this.flag = flag;
}
/**
* 有参构造方法
* @param flag
* @param errorMsg
*/
public ResultInfo(boolean flag, String errorMsg) {
this.flag = flag;
this.errorMsg = errorMsg;
}
/**
* 有参构造方法
* @param flag
* @param data
* @param errorMsg
*/
public ResultInfo(boolean flag, Object data, String errorMsg) {
this.flag = flag;
this.data = data;
this.errorMsg = errorMsg;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}
包含三个成员变量 flag(判断返回结果是否正常)、data(后端返回结果数据对象)、errorMsg(异常的错误信息)。
ResultInfo info=new ResultInfo();
if(flag){
//响应数据
info.setFlag(true);
}else {
info.setFlag(false);
info.setErrorMsg("用户名存在,注册失败!");
}
info对象序列化为json,并写回客户端。
ObjectMapper mapper=new ObjectMapper();
String json = mapper.writeValueAsString(info);
//设置content type
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
----------
## 3.service页面 ##
service要实现注册用户的判断方法:
调用dao层进行操作:
如果用户名不存在,return true,需要保存信息——此方法在dao层实现,if判断调用即可;如果用户名存在,返回false即可。
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;
public class UserServiceImpl implements UserService {
private UserDao dao=new UserDaoImpl();
/**
* 注册用户的方法
* @param user
* @return
*/
@Override
public boolean regist(User user) {
//调用dao
User byUsername = dao.findByUsername(user.getUsername());
if (byUsername!=null){
return false;
}
//用户名不存在,保存信息
dao.save(user);
return true;
}
}
## 4.dao层 ##
先定义jdbctemplate对象
dao层需要实现两个功能:
(1)对request传入的username在数据库进行查找;
(2)对于数据库不存在的用户信息进行储存
(2)的实现:
@Override
public void save(User user) {
String sql="insert into tab_user(username,password,name,birthday,sex,telephone,email)"+
"values(?,?,?,?,?,?,?)";
template.update(sql,user.getUsername(),user.getPassword(),user.getName(),user.getBirthday(),
user.getSex(),user.getTelephone(),user.getEmail());
}
对于(1)的实现:
@Override
public User findByUsername(String username) {
//定义sql
User user = null;
try {
String sql="select*from tab_user where username=?";
//如果没有查询到,会直接null,不能封装成对象而报错
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class),username);
} catch (Exception e) {
}
return user;
}
这里有一个细节:
`String sql="select*from tab_user where username=?"`
如果没有查询到,会直接null,不能封装成对象而报错。