黑马旅游网-学习笔记Part04
黑马旅游网-学习笔记Part04
今日目标
- 项目介绍🍐
- 导入并启动项目 ✏️
- 技术选型🍐
- 创建数据库
- 用户注册功能 ✏️ ❤️
知识准备
- 完成JDK、Idea、Maven、Mysql、Navicat等软件的安装
- 能理解据库的库、表、字段的关系以及表和表的关系
- 完成sql基本curd语句和mybatis入门案例的代码编写
1. 项目介绍
前言

黑马旅游网主要是用来查看并选择旅游路线的网站,网站功能有网站账号注册,网站登录,查看旅游路线及收藏旅游路线等。
需要具备基础
- Java面向对象,html,css,javascript,jquery,mysql,jdbc,DButils,Druid ,servlet,jsp, javamail,ajax,http
实训目标
- 熟悉并掌握软件开发的基本方法及流程;
- 熟悉并掌握Java面向对象特性及在项目中的使用;
- 熟悉并掌握JavaEE开发技术并整合到项目中的应用;
- 熟悉并掌握web应用程序中的分层体系架构;
- 参与不同阶段的工作任务,体验真实软件项目开发过程,积累一定的实际项目开发经验;
软件环境:
- mysql数据库服务器(5.7+)
- SQLyog或者Navicat
- JDK1.8以上
- Intellij idea
首页

分类页

登录页
注册页
详情页
2. 导入并启动项目
导入并启动项目
项目采用前后端分离开发,前端项目运行在nginx中,后端代码运行在tomcat中,如下图:

- 需求分析:首先我们需要阅读需求文档,分析需求,理解需求。
- 定制接口:查询接口文档中关于需求的接口的定义,包括地址,参数,响应数据类型等等
- 前后台并行开发:各自按照接口文档进行开发,实现需求。然后各自按照接口文档进行测试
- 前后段联调测试:前段工程请求后端工程,测试功能
前后端运行流程: 👇 👇

- 已经准备了黑马旅游网的初始代码企业中一般不会等你创建,工程已经存在!,直接导入即可开启开发
- 后端代码20kb
- 安装MavenHelper插件,检查pom.xml文件中的tomcat插件配置,启动项目
3. 技术选型
技术选型

1). 用户层前端工程师
本项目中在构建门户前端页面,我们会用到Ajax、Html、css、js、jQuery等技术。

2). 网关层
Nginx是一个服务器,主要用来作为Http服务器,部署静态资源,访问性能高。在Nginx中还有两个比较重要的作用: 反向代理和负载均衡, 在进行项目部署时,要实现Tomcat的负载均衡,就可以通过Nginx来实现。


3). 应用层
HttpServlet: 接受请求和响应数据
javaMail: 发送邮件的工具类。
JWT 安全性高: 用于对应用程序上的用户进行身份验证的标记。
阿里云OSS: 对象存储服务,在项目中主要存储文件,如图片等。
Filter: 用来拦截请求进行校验
4). 数据层
MySQL企业实用: 关系型数据库, 本项目的核心业务数据都会采用MySQL进行存储。
Redis提高访问性能: 基于key-value格式存储的内存数据库, 访问速度快, 经常使用它做缓存。

Mybatis企业实用: 本项目持久层将会使用Mybatis开发。

pagehelper: 分页插件。
Jedis: 简化java代码操作Redis的API。
5). 工具
git企业实用: 版本控制工具, 在团队协作中, 使用该工具对项目中的代码进行管理。

maven企业实用: 项目构建工具。

junit:单元测试工具,开发人员功能实现完毕后,需要通过junit对功能进行单元测试。
postman/Apifox: 接口测工具,模拟用户发起的各类HTTP请求,获取对应的响应结果。

4. 创建数据库
数据库环境搭建
- 从资料中找到travel.sql

创建数据库travel

- 执行travel.sql文件

- 执行完成后,共创建出6张表

5. 用户注册功能
用户注册功能

- 请求方式:POST
- 请求路径:
/travel/registUserServlet
- 请求参数:如下图

返回结果:
- 成功:
{"flag":true,"data":null,"errorMsg":null}
- 失败:
{"flag":false,"data":null,"errorMsg":"注册失败!!"}
- 成功:
其他接口: 获得验证码接口:
http://localhost:端口/travel/checkCode?1686239356355

代码操作
步骤
- 1.书写RegistUserServlet类,继承HttpServlet,配置路径,接受请求
- 2.注册表单提交,先进行验证码判断;
- 3.获取表单的数据,封装表单数据到User对象,调用业务层UserService代码添加用户,根据返回结果,返回给前端Json;
- 4.在业务层实现类中
UserServiceImpl
查询用户名是否存在,如果存在插入失败,如果不存在插入成功 - 5.存入数据库 - 此时还未邮箱激活,所以状态码status为N;
- 6.为邮箱发送激活验证码 - 登录邮箱进行验证;
- 7.验证成功修改当前注册用户的状态为 Y;
1.书写RegistUserServlet类,继承HttpServlet,配置路径,接受请求
RegistUserServlet类
@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
// 覆写doPost方法
}
并且准备MybatisUtils工具类
/**
* Mybatis工具类,方便获得SQLSession对象,用来操作数据库
*/
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
// 初始化SqlSessionFactory对象
static {
try {
// 使用MyBatis提供的Resources类加载mybatis的配置文件
Reader reader =
Resources.getResourceAsReader("mybatis-config.xml");
// 构建sqlSession的工厂
sqlSessionFactory =
new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
// 获取SqlSession对象的静态方法
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
2.注册表单提交,先进行验证码判断;
RegistUserServlet类
//获取表单提交过来的 验证码,以及获取session 域中的code
String check = req.getParameter("check");
//从域中拿到对应的验证码
String checkcode_server = (String) req.getSession().getAttribute
("CHECKCODE_SERVER");
//创建一个封装结果集
ResultInfo resultInfo = new ResultInfo();
//判断验证码是否正确
if (check == null || !check.equalsIgnoreCase(checkcode_server)) {
//判断验证码错误 则设置为错误
resultInfo.setFlag(false);
resultInfo.setErrorMsg("验证码错误!!");
//将实体类转化为 json数据串
String jsonString = JSON.toJSONString(resultInfo);
//设置响应头信息
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(jsonString);
return;
}
3.获取表单的数据,封装表单数据到User对象,调用业务层UserService代码添加用户,根据返回结果,返回给前端Json
RegistUserServlet类
//第二步获取前端传递过来的数据
Map<String, String[]> userMap = req.getParameterMap();
//创建user对象
User user = new User();
//java 有api 可以将map的数据和实体类进行直接绑定 第一个参数传实体类, 第二个参数放map
try {
BeanUtils.populate(user, userMap);
System.out.println(user.toString());
} catch (Exception e) {
e.printStackTrace();
}
//调用 UserService接口做逻辑处理
UserService userService = new UserServiceImpl();
// alt +回车创建方法
boolean flag = userService.add(user);
if(flag){
//返回为true
resultInfo.setFlag(true);
}else {
resultInfo.setFlag(false);
resultInfo.setErrorMsg("注册失败!!");
}
// 将resultInfo 转为json并且响应给前端
//将实体类转化为 json数据串
String jsonString = JSON.toJSONString(resultInfo);
//设置响应头信息
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(jsonString);
return;
4.在业务层实现类中UserServiceImpl
查询用户名是否存在,如果存在插入失败,如果不存在插入成功
.travel.service.impl.UserServiceImpl类
注:阴影部分是发送邮件的逻辑👈
public class UserServiceImpl implements UserService {
//User 用户相关逻辑层 用来处理 相关user业务
@Override
public boolean add(User user) {
//定义标识符(用来判断 新增是否成功)444
boolean flag = true;
//做注册需要查询用户名是否存在问题
//获取mybatis的sqlSession,并且自动提交事务
SqlSession sqlSession = MybatisUtils.getSqlSessionFactory().openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//通过username查询数据库 user是否存在问题
User dbuser = mapper.checkUser(user.getUsername());
//对通过帐号查询出来user1对象进行判断
if (dbuser == null) {
//进行user数据添加
//设置用户状态码 默认为 'N'
user.setStatus("N");
//创建用户激活码code
String uuid = UuidUtil.getUuid();
user.setCode(uuid);
//进行密码加密
try {
String password1 = Md5Util.encodeByMd5(user.getPassword());
user.setPassword(password1);
} catch (Exception e) {
e.printStackTrace();
}
//进行数据库的新增插入操作
int i = mapper.addUser(user);
if (i == 0) {
//假设添加失败 那么设置响应为错误
flag = false;
return flag;
}
//创建一个邮件主题内容文本 href ="localhoset:xxxxx"
String text = "<a href='http://你的ip:端口/travel/activeUserServlet?code=" + user.getCode() +
"'>点击激活【黑马旅游网】</a>";
//通过邮件系统发送 激活邮件 ,需要携带code
MailUtils.sendMail(user.getEmail(), text, "激活测试");
} else {
flag = false;
}
return flag;
}
}
UserMapper.java
public interface UserMapper {
//查询用户是否存在
User checkUser(String username);
//将用户注册的信息添加到数据库
int addUser(User user);
//修改用户的激活状态
int updateUserStatus(String code);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.itcast.travel.mapper.UserMapper">
<select id="checkUser" resultType="user">
select * from tab_user where username= #{username}
</select>
<insert id="addUser">
insert into tab_user (username,password,name,birthday,sex,telephone,email,status,code)
VALUES (#{username},#{password},#{name},#{birthday},#{sex},#{telephone},#{email},#{status},#{code})
</insert>
<update id="updateUserStatus">
update tab_user set status ='Y' where code= #{code}
</update>
</mapper>
5.存入数据库 - 此时还未邮箱激活,所以状态码status为N;代码在第四步中
6.为邮箱发送激活验证码 - 登录邮箱进行验证;代码在第四步中
点击查看qq邮箱的授权码教程点这里!!
上图中的网址:
https://service.mail.qq.com/detail/0/75
发送邮件的工具类 👇
/**
* 发邮件工具类
*/
public final class MailUtils {
private static final String USER = "填写邮箱号!!"; // 发件人称号,同邮箱地址
private static final String PASSWORD = "填写密码或者授权码"; // 如果是qq邮箱可以使户端授权码,或者登录密码
/**
*
* @param to 收件人邮箱
* @param text 邮件正文
* @param title 标题
*/
/* 发送验证信息的邮件 */
public static boolean sendMail(String to, String text, String title){
try {
final Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", "smtp.qq.com");
// 发件人的账号
props.put("mail.user", USER);
//发件人的密码
props.put("mail.password", PASSWORD);
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用环境属性和授权信息,创建邮件会话
Session mailSession = Session.getInstance(props, authenticator);
// 创建邮件消息
MimeMessage message = new MimeMessage(mailSession);
// 设置发件人
String username = props.getProperty("mail.user");
System.out.println(username);
InternetAddress form = new InternetAddress(username);
message.setFrom(form);
// 设置收件人
InternetAddress toAddress = new InternetAddress(to);
message.setRecipient(Message.RecipientType.TO, toAddress);
// 设置邮件标题
message.setSubject(title);
// 设置邮件的内容体
message.setContent(text, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
public static void main(String[] args) throws Exception { // 做测试用
MailUtils.sendMail("","你好,这是一封测试邮件,无需回复。","测试邮件");
System.out.println("发送成功");
}
}
7.验证成功修改当前注册用户的状态为 Y
;
需求:👇
ActiveUserServlet类
/**
* 用户邮箱激活,激活码验证
*/
@WebServlet("/activeUserServlet")
public class ActiveUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取 url地址传递过来code
String code = req.getParameter("code");
//调用UserService 进行修改操作
UserService userService = new UserServiceImpl();
boolean flag = userService.updateStatusByCode (code);
String msg ="";
if (flag){
//激活成功,并且显示登录 链接
msg ="激活成功,请点击<a href='login.html'>登录</a>";
}else {
//激活有误
msg = "激活失败,请联系管理员";
}
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write(msg);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
业务层实现类:UserServiceImpl 👇
public class UserServiceImpl implements UserService {
@Override
public boolean updateStatusByCode(String code) {
// 1. 获得Mybatis的工具类,通过工具类获得Mapper代理对象
UserMapper mapper = MybatisUtils.getSqlSessionFactory().openSession(true).getMapper(UserMapper.class);
// 2. 通过代理对象操作数据库
int i=mapper.updateStatusByCode(code);
return i!=0;
}
}
UserMapper.java
public interface UserMapper {
//修改用户的激活状态
int updateStatusByCode(String code);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.itcast.travel.mapper.UserMapper">
<update id="updateStatusByCode">
update tab_user set status ='Y' where code= #{code}
</update>
</mapper>