关于项目的配置:
P343 01-项目导入
P344 02-项目启动
P345 03-技术选型
一、注册功能
1.注册页面
2.功能分析
3.前台的表单校验
register.html
<script>
/*
表单校验:
1.用户名:单词字符,长度8到20位
2.密码:单词字符,长度8到20位
3.email:邮件格式
4.姓名:非空
5.手机号:手机号格式
6.出生日期:非空
7.验证码:非空
*/
//校验用户名()
function checkUsername() {
var username = $("#username").val(); //获取用户名值
var reg_username = /^\w{8,20}$/;//定义正则(单词字符,长度8到20位)
//3.判断,给出提示信息
var flag = reg_username.test(username);
if(flag){
$("#username").css("border","");//用户名合法,默认的边框
}else{
$("#username").css("border","1px solid red");//用户名非法,边框变为红色
}
return flag;//返回校验结果
}
//校验密码
function checkPassword() {
var password = $("#password").val();//获取密码值
var reg_password = /^\w{8,20}$/;//定义正则
//3.判断,给出提示信息
var flag = reg_password.test(password);
if(flag){
$("#password").css("border","");//用户名合法,默认的边框
}else{
$("#password").css("border","1px solid red");//密码非法,加一个红色边框
}
return flag;//返回校验结果
}
//校验邮箱
function checkEmail(){
var email = $("#email").val();//获取邮箱
var reg_email = /^\w+@\w+\.\w+$/;//定义正则(itcast@163.com)
//3.判断
var flag = reg_email.test(email);
if(flag){
$("#email").css("border","");
}else{
$("#email").css("border","1px solid red");
}
return flag;//返回校验结果
}
//异步提交表单
$(function () {
$("#registerForm").submit(function(){//当点击了表单的提交时
//==注意因为这里是表单对象$("#registerForm")调用的submit方法所以在这个函数里${this}就是$("#registerForm")==
if(checkUsername() && checkPassword() && checkEmail()){//校验用户名、密码、Email都通过后
//前端校验通过,发送ajax请求,提交表单的数据
$.post("registUserServlet",$(this).serialize(),function(data){
// ==你提交的表单数据应该是“username=zhangsan&password=123”这样式的,所以一个form对象调用serialize()方法就可以把数据转换成那种形式==
//处理服务器响应的数据,data 的格式是{flag:true,errorMsg:"注册失败"}
if(data.flag){
location.href="register_ok.html";//注册成功,跳转成功页面
}else{
$("#errorMsg").html(data.errorMsg);//注册失败,给errorMsg添加提示信息
}
});
}
//前端校验不通过,不让页面跳转
return false;//如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交
});
//当某一个组件失去焦点是,调用对应的校验方法(异步)
$("#username").blur(checkUsername);
$("#password").blur(checkPassword);
$("#email").blur(checkEmail);
});
</script>
4.后台servlet的实现
user类
public class User implements Serializable {
private int uid;//用户id
private String username;//用户名,账号
private String password;//密码
private String name;//真实姓名
private String birthday;//出生日期
private String sex;//男或女
private String telephone;//手机号
private String email;//邮箱
private String status;//激活状态,Y代表激活,N代表未激活
private String code;//激活码(要求唯一)
public User() {
}
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;
}
}
ResultInfo.class
service层完成注册、查询等有可能是成功的也可能是失败的,要是失败了servlet就要告诉前端flag=false和发生错误的信息,为此我们建了ResultInfo类来封装这些东西
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;
}
public ResultInfo(boolean flag, String errorMsg) {
this.flag = flag;
this.errorMsg = 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;
}
}
RegistUserServlet
@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取数据
Map<String, String[]> map = request.getParameterMap();
//2.封装对象
User user = new User();
try {
BeanUtils.populate(user,map);//把map集合对应的数据封装到User对应的属性里
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//3.调用service完成注册
UserService service = new UserServiceImpl();
boolean flag = service.regist(user);
ResultInfo info = new ResultInfo();
if(flag){
info.setFlag(true);
}else{
info.setFlag(false);
info.setErrorMsg("注册失败!");
}
//将info对象序列化为json
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);
}
}
Dao层
public interface UserDao {
public User findByUsername(String username);
public void save(User user);
}
public class UserDaoImpl implements UserDao {
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
@Override //根据用户名查询用户数据
public User findByUsername(String username) {
User user = null;
try {
String sql = "select * from tab_user where username = ?";
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username);
} catch (Exception e) {
}
return user;
}
@Override //存储用户信息
public void save(User user) {
String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email) values(?,?,?,?,?,?,?)";
template.update(sql,user.getUsername(),
user.getPassword(),
user.getName(),
user.getBirthday(),
user.getSex(),
user.getTelephone(),
user.getEmail());
}
}
service层
public interface UserService {
boolean regist(User user);
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public boolean regist(User user) {
//根据用户名查询用户对象
User u = userDao.findByUsername(user.getUsername());
//判断u是否为null
if(u != null){
//u不为null,说明用户名存在,注册失败
return false;
}
//u为null,则保存用户信息
userDao.save(user);
return true;
}
}
5.后台servlet添加验证码校验
@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//验证校验
String check = request.getParameter("check");//从前台获取到验证码框中用户输入的内容
HttpSession session = request.getSession();
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");//从CheckCodeServle中获取动态生成的验证码
session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
//比较(==要防止用户不填写验证码导致的验证码空指针异常==)
if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
//验证码错误
ResultInfo info = new ResultInfo();
info.setFlag(false);
info.setErrorMsg("验证码错误");
//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return;
}
//1.获取数据
Map<String, String[]> map = request.getParameterMap();
//2.封装对象
User user = new User();
try {
BeanUtils.populate(user,map);//把map集合对应的数据封装到User对应的属性里
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//3.调用service完成注册
UserService service = new UserServiceImpl();
boolean flag = service.regist(user);
ResultInfo info = new ResultInfo();
if(flag){
info.setFlag(true);
}else{
info.setFlag(false);
info.setErrorMsg("注册失败!");
}
//将info对象序列化为json
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);
}
}
6.运行结果
二、邮件激活功能
1.分析
2.后台代码的编写
新建一个activeUserServlet
active就是动词“激活”
@WebServlet("/activeUserServlet")
public class ActiveUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String code = request.getParameter("code");//获取激活码
//==上述代码你可能不理解,你需要看一下service层的发送邮件的邮件内容==
if(code != null){
//调用service完成激活
UserService service = new UserServiceImpl();
boolean flag = service.active(code);
//判断标记
String msg = null;
if(flag){
//激活成功
msg = "激活成功,请<a href='login.html'>登录</a>";
}else{
//激活失败
msg = "激活失败,请联系管理员!";//激活失败一般就是用户网络造成的
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(msg);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
修改service层
public interface UserService {
boolean regist(User user);
boolean active(String code);
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override //修改注册用户,添加一个发送邮件的功能
public boolean regist(User user) {
//根据用户名查询用户对象
User u = userDao.findByUsername(user.getUsername());
//判断u是否为null
if(u != null){
//u不为null,说明用户名存在,注册失败
return false;
}
//u为null,说明用户名不存在,那么保存用户信息并且给用户发送邮件让他激活:
user.setCode(UuidUtil.getUuid());//给用户设置激活码(有一个UuidUtil工具类通过调用getUuid()方法就可以获得全球唯一的一个字符串,用它作为激活码)
user.setStatus("N");//设置激活状态为N表示用户还未激活
userDao.save(user);
//用MaileUtils工具类给完成注册的用户发送邮件让他激活
//==有一个MaileUtils工具类,通过调用sendMai方法就可以给该用户发送一封邮件(sendMai方法的参数为用户邮箱、邮件内容、邮件的title)==
String content="<a href='http://localhost/travel/activeUserServlet?code="+user.getCode()+"'>点击激活【黑马旅游网】</a>";
//如上代码所示,邮件内容就是一个超链接,用户点击然后就能激活
MailUtils.sendMail(user.getEmail(),content,"激活邮件");
return true;
}
@Override
public boolean active(String code) {
//根据激活码查询用户对象
User user = userDao.findByCode(code);
if(user != null){ //根据激活码能查到用户
//调用dao的修改激活状态的方法
userDao.updateStatus(user);
return true;
}else{ //根据激活码查不到用户
return false;
}
}
修改Dao层
public interface UserDao {
public User findByUsername(String username);
public void save(User user);
User findByCode(String code);
void updateStatus(User user);
}
public class UserDaoImpl implements UserDao {
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
@Override //根据用户名查询用户数据
public User findByUsername(String username) {
User user = null;
try {
String sql = "select * from tab_user where username = ?";
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username);
} catch (Exception e) {
}
return user;
}
@Override //存储用户信息
public void save(User user) {
String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email,status,code) values(?,?,?,?,?,?,?,?,?)";
template.update(sql,user.getUsername(),
user.getPassword(),
user.getName(),
user.getBirthday(),
user.getSex(),
user.getTelephone(),
user.getEmail(),
user.getStatus(), //新加的
user.getCode() //新加的
);
}
@Override //根据激活码查询用户对象
public User findByCode(String code) {
User user = null;
try {
String sql = "select * from tab_user where code = ?";
user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),code);
} catch (DataAccessException e) {
e.printStackTrace();
}
return user;
}
@Override //修改指定用户激活状态
public void updateStatus(User user) {
String sql = " update tab_user set status = 'Y' where uid=?";
template.update(sql,user.getUid());
}
}
3.运行结果
三、登录功能
1.分析
2.后台编写
LoginServlet
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String[]> map = request.getParameterMap();//获取用户名和密码数据
//封装User对象
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//调用Service查询
UserService service = new UserServiceImpl();
User u = service.login(user);
ResultInfo info = new ResultInfo();
//判断用户对象是否为null
if(u == null){
//用户名密码或错误
info.setFlag(false);
info.setErrorMsg("用户名密码或错误");
}
//判断用户是否激活
if(u != null && !"Y".equals(u.getStatus())){
//用户名不为null而且激活码不为Y,说明用户尚未激活
info.setFlag(false);
info.setErrorMsg("您尚未激活,请激活");
}
//判断登录成功
if(u != null && "Y".equals(u.getStatus())){
request.getSession().setAttribute("user",u);//登录成功后将用户存入session,在findUserServlet中用到了user信息
info.setFlag(true);//登录成功
}
//响应数据
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),info);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
service层添加如下代码
UserService在原有代码的基础上添加
User login(User user);
UserServiceImpl在原有代码的基础上添加
@Override
public User login(User user) {
return userDao.findByUsernameAndPassword(user.getUsername(),user.getPassword());
}
Dao层添加如下代码
UserDao在原有代码的基础上添加
User findByUsernameAndPassword(String username, String password);
UserDaoImpl在原有代码的基础上添加
@Override
public User findByUsernameAndPassword(String username, String password) {
User user = null;
try {
String sql = "select * from tab_user where username = ? and password = ?";
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username,password);
} catch (Exception e) {
}
return user;
}
3.前台代码的编写
login.html
<script>
$(function () {
//给登录按钮绑定单击事件
$("#btn_sub").click(function () {
//发送ajax请求,提交表单数据
$.post("loginServlet",$("#loginForm").serialize(),function (data) {
//data的格式flag:false,errorMsg:''}
if(data.flag){
//登录成功
location.href="index.html";
}else{
//登录失败
$("#errorMsg").html(data.errorMsg);
}
});
});
});
</script>
4.运行结果
5.添加姓名提示
header.html
<script>
$(function () {
$.get("findUserServlet",{},function (data) {
//返回的数据格式为{uid:1,name:'李四'}
var msg = "欢迎回来,"+data.name;
$("#span_username").html(msg);
});
});
</script>
findUserServlet
@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object user = request.getSession().getAttribute("user");//从session中获取登录用户(见loginServlet)
//将user写回客户端
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
6.退出功能
什么叫做登录了?session中有user对象。
什么叫退出?销毁session中user对象。
实现步骤:
1.访问servlet,将session销毁
2.跳转到登录页面
header.html
<a href="javascript:location.href='exitServlet';">退出</a>
//点击退出就会跳转到exitServlet
exitServlet
@WebServlet("/exitServlet")
public class ExitServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//销毁session
request.getSession().invalidate();
//跳转登录页面
response.sendRedirect(request.getContextPath()+"/login.html");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
感谢浏览和收藏