黑马旅游网(简单实现)
- 前言
- 项目功能介绍
- 一、创建一个web项目
- 二、浏览器页面部署
- 1.设置首页
- 1、游客首页
- 2.用户首页
- 2.登录页面
- 3.注册页面
- 三、Servlet编写
- 注册Servlet
- 登录Servlet
- 验证码Servlet
- 四、Java操作MySQL
- 1、用户的实体类
- 2、JDBC工具类 使用Durids连接池
- 3、操作数据库中User表的类
- 4、配置文件
- 五、其他
- 1、需要导入的jar包
- 2、IDEA整体项目布局
- 3、注册或登录时,首先判断验证码是否正确
- 结尾
- 1、未实现的功能
- 2、存在的Bug
- 3、项目总结
前言
刚学习了一个Session案例,即服务器端会话技术案例,做完案例之后,
突然想将之前学习前端技术的案例和这个结合起来,于是就有了这个项目。
项目功能介绍
将tomcat集成到IDEA中,创建JavaEE项目,部署web项目,结合了Servlet、MySQL、JSP和Bootstrap技术,
简单实现以下功能:
1、未注册过的用户以游客身份浏览首页,
2、注册账号后,以用户身份跳转到首页,
- 如果用户名或密码均无输入,跳转注册页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转注册页面,提示:验证码错误
3、登录账号后,以用户身份跳转到首页,
- 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
4、退出登录,回到游客身份跳转到首页。
一、创建一个web项目
1、先建立一个工程,创建web项目
2、修改虚拟目录名称,我一般设为web项目名称
二、浏览器页面部署
1.设置首页
1、游客首页
1、首页效果图
2、首页整体代码,结合Bootstrap编写在index.jsp里
3、页眉部分
4、主体部分
5、页脚部分
2.用户首页
1、首页展示效果图,只有以下这里发生了改变
2、代码实现,点击退出登录后,回到游客首页
2.登录页面
1、登录页面效果图,弄的比较随意
2、用户名或密码错误效果
①数据库用户数据
②用户名或密码输入错误
③登录结果
3、代码实现,结合了Servlet和MySQL技术实现,将代码写到login.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
<script>
window.onload = function () {
document.getElementById("img").onclick = function () {
this.src="/yanshi/checkCodeServlet?time="+new Date().getTime();
}
}
</script>
<style>
.error{
color: red;
}
</style>
</head>
<body>
<form action="/yanshi/loginServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td>
<input type="text" name="username">
</td>
</tr>
<tr>
<td>密码</td>
<td class="error">
<input type="text" name="password">
<%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%>
</td>
</tr>
<tr>
<td>验证码</td>
<td class="error">
<input type="text" name="checkCode">
<%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%>
</td>
</tr>
<tr>
<td colspan="2"><img id="img" src="/yanshi/checkCodeServlet"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
3.注册页面
1、注册页面效果图
①数据库用户数据
②注册时,用户名或密码无输入,或用户名与数据库的用户名重复
③注册结果
2、代码实现,本处只对用户名和密码进行数据库存储,其余数据没有存储,将代码编写到register.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
<script>
window.onload = function () {
document.getElementById("img_check").onclick = function () {
this.src="/yanshi/checkCodeServlet?time="+new Date().getTime();
};
};
</script>
<style>
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
body{
background: url("img/register_bg.png") no-repeat center;
padding-top: 150px;
background-size:cover;
}
.rg_layout{
width: 900px;
height: 500px;
border: 8px solid #eeeeee;
background-color: white;
/*让div水平居中显示*/
margin: auto;
margin-bottom: 100px;
box-sizing: border-box;
}
.rg_left{
/*border: 1px solid red;*/
float: left;
margin: 15px;
}
.rg_left > p:first-child{
color: #ffd026;
font-size: 20px;
}
.rg_left > p:last-child{
color: #a6a6a6;
font-size: 20px;
}
.rg_center{
/*border: 1px solid red;*/
float: left;
margin: 30px;
}
.rg_right{
/*border: 1px solid red;*/
float: right;
margin: 25px;
}
.rg_right > p{
font-size: 15px;
}
.rg_right p a{
color: pink;
}
.td_left{
width: 150px;
height: 45px;
text-align: right;
}
.td_right{
padding-left: 20px;
}
#username,#password,#checkCode,#name,#birthday,#tel,#email{
width: 175px;
height: 32px;
border: 1px solid #a6a6a6;
/*设置边框圆角*/
border-radius: 5px;
padding-left: 10px;
}
#checkCode{
width: 105px;
}
#img_check{
height: 32px;
vertical-align: middle;
}
#btn_sub{
width: 150px;
height: 40px;
background-color: #ffd026;
border: 1px solid #ffd026;
}
.error{
color:red;
}
#td_sub{
padding-left: 170px;
}
</style>
</head>
<body>
<div class="rg_layout">
<div class="rg_left">
<p>新用户注册</p>
<p>USER REGISTER</p>
</div>
<div class="rg_center">
<div class="rg_form">
<!--定义表单 form-->
<form action="/yanshi/registerServlet" method="post">
<table>
<tr>
<td class="td_left"><label for="username">用户名</label></td>
<td class="td_right error">
<input type="text" name="username" id="username" placeholder="请输入用户名">
<span id="s_username" class="error"></span>
<%=request.getAttribute("username_error") == null ? "" : request.getAttribute("username_error")%>
</td>
</tr>
<tr>
<td class="td_left"><label for="password">密码</label></td>
<td class="td_right error">
<input type="password" name="password" id="password" placeholder="请输入密码">
<span id="s_password" class="error"></span>
<%=request.getAttribute("password_error") == null ? "" : request.getAttribute("password_error")%>
</td>
</tr>
<tr>
<td class="td_left"><label for="email">Email</label></td>
<td class="td_right"><input type="email" name="email" id="email" placeholder="请输入邮箱"></td>
</tr>
<tr>
<td class="td_left"><label for="name">姓名</label></td>
<td class="td_right"><input type="text" name="name" id="name" placeholder="请输入姓名"></td>
</tr>
<tr>
<td class="td_left"><label for="tel">手机号</label></td>
<td class="td_right"><input type="text" name="tel" id="tel" placeholder="请输入手机号"></td>
</tr>
<tr>
<td class="td_left"><label>性别</label></td>
<td class="td_right">
<input type="radio" name="gender" value="male"> 男
<input type="radio" name="gender" value="female"> 女
</td>
</tr>
<tr>
<td class="td_left"><label for="birthday">出生日期</label></td>
<td class="td_right"><input type="date" name="birthday" id="birthday" placeholder="请输入出生日期"></td>
</tr>
<tr>
<td class="td_left"><label for="checkCode" >验证码</label></td>
<td class="td_right error"><input type="text" name="checkCode" id="checkCode" placeholder="请输入验证码">
<img id="img_check" src="/yanshi/checkCodeServlet">
<%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%>
</td>
</tr>
<tr>
<td colspan="2" id="td_sub"><input type="submit" id="btn_sub" value="注册"></td>
</tr>
</table>
</form>
</div>
</div>
<div class="rg_right">
<p>已有账户?<a href="/yanshi/login.jsp">立即登录</a></p>
</div>
</div>
</body>
</html>
三、Servlet编写
注册Servlet
package servlet;
import org.apache.commons.beanutils.BeanUtils;
import servlet.sql.dao.UserDao;
import servlet.sql.domain.User;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/registerServlet")
public class registerServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置request编码
request.setCharacterEncoding("utf-8");
//2.1获取所有请求参数
Map<String, String[]> map = request.getParameterMap();
String checkCode = request.getParameter("checkCode");
//2.2创建User对象
User registerUser = new User();
//2.3使用BeanUtils封装
try {
BeanUtils.populate(registerUser,map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//3.1先获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session = (String)session.getAttribute("checkCode_session");
//删除session中存储的验证码
session.removeAttribute("checkCode_session");
//3.2先判断验证码是否正确
if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)){
//忽略大小写,验证码正确
//判断用户名或密码是否有输入
if ((registerUser.getUsername().length() & registerUser.getPassword().length()) != 0){
//2.4创建UserDao对象
UserDao dao = new UserDao();
//2.4调用UserDao的login方法
User login = dao.login(registerUser);
//判断用户名是否存在
if (registerUser.getUsername().equals(login.getUsername()) != true){
//注册成功
User user = dao.register(registerUser);
//存储信息,用户信息
session.setAttribute("user",user.getUsername());
//重定向到success.jsp
response.sendRedirect(request.getContextPath()+"/user_homepage.jsp");
}else {
//注册失败
//存储提示信息到request
request.setAttribute("username_error", "用户名重复");
//转发到登录页面
request.getRequestDispatcher("/register.jsp").forward(request,response);
}
} else {
//注册失败
if (registerUser.getUsername().length() == 0){
//存储提示信息到request
request.setAttribute("username_error","用户名错误");
}
if (registerUser.getPassword().length() == 0){
//存储提示信息到request
request.setAttribute("password_error","密码错误");
}
//转发到登录页面
request.getRequestDispatcher("/register.jsp").forward(request,response);
}
}else {
//验证码不一致
//存储提示信息到request
request.setAttribute("cc_error","验证码错误");
//转发到登录页面
request.getRequestDispatcher("/register.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
登录Servlet
package servlet;
import org.apache.commons.beanutils.BeanUtils;
import servlet.sql.dao.UserDao;
import servlet.sql.domain.User;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置request编码
request.setCharacterEncoding("utf-8");
//2.获取参数
/*String username = request.getParameter("username");
String password = request.getParameter("password");*/
//2.1获取所有请求参数
Map<String, String[]> map = request.getParameterMap();
String checkCode = request.getParameter("checkCode");
//2.2创建User对象
User loginUser= new User();
//2.3使用BeanUtils封装
try {
BeanUtils.populate(loginUser,map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//2.4调用UserDao的login方法
UserDao dao = new UserDao();
User user = dao.login(loginUser);
//3.1先获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session = (String)session.getAttribute("checkCode_session");
//删除session中存储的验证码
session.removeAttribute("checkCode_session");
//3.2先判断验证码是否正确
if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)){
//忽略大小写,验证码正确
//判断用户名和密码是否一致
if (user != null){ //需要调用UserDao查询数据库
//登录成功
//存储信息,用户信息
session.setAttribute("user",user.getUsername());
//重定向到success.jsp
response.sendRedirect(request.getContextPath()+"/user_homepage.jsp");
}else {
//登录失败
//存储提示信息到request
request.setAttribute("login_error","用户名或密码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}else {
//验证码不一致
//存储提示信息到request
request.setAttribute("cc_error","验证码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
验证码Servlet
package 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("/checkCodeServlet")
public class checkCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//简单形式,设置编码
//response.setContentType("text/html;charset=utf-8");
int width = 100;
int height = 50;
//1.创建一对象,在内存中代表图片(验证码对象)
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.PINK);//设置背景颜色
g.fillRect(0,0,width,height);
Font font = new Font("Helvetica",Font.ITALIC,18);
g.setFont(font);
//2.2画边框
g.setColor(Color.blue);
g.drawRect(0,0,width-1,height-1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
sb.append(ch);
//2.3写验证码
g.drawString(ch + "",width/6*i,30);// y:height/2
}
String checkCode_session = sb.toString();
//将验证码存入session
request.getSession().setAttribute("checkCode_session", checkCode_session);
//2.4画干扰线
g.setColor(Color.green);
//随机生成坐标点
for (int i = 0; i < 5; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面中展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
四、Java操作MySQL
1、用户的实体类
package servlet.sql.domain;
/**
* 用户的实体类
*/
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
2、JDBC工具类 使用Durids连接池
package servlet.sql.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具类 使用Durids连接池
*/
public class JDBCUtils {
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
//使用ClassLoader加载配置文件,获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接池对象
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 获取连接Connection对象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
3、操作数据库中User表的类
package servlet.sql.dao;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import servlet.sql.domain.User;
import servlet.sql.util.JDBCUtils;
/**
* 操作数据库中User表的类
*/
public class UserDao {
//声明JDBCTemplate对象共用
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 登录方法,查询功能
* @param loginUser 只有用户名和密码
* @return user包含用户全部数据,没有查询到,返回null
*/
public User login(User loginUser){
try {
//1.编写sql
String sql = "select * from user where username = ? and password = ?";
//2.调用query方法
User user = template.queryForObject(
sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(),
loginUser.getPassword()
);
return user;
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
/**
* 注册方法
* @param registerUser 只有用户名和密码
* @return user包含用户全部数据,没有查询到,返回null
*/
public User register(User registerUser){
//1.定义sql语句
String sql1 = "insert into user(username,password) values(?,?)";
//2.调用方法实现
Object[] args = {registerUser.getUsername(), registerUser.getPassword()};
//3.执行sql
template.update(sql1,args);
return login(registerUser);
}
}
4、配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
五、其他
1、需要导入的jar包
2、IDEA整体项目布局
3、注册或登录时,首先判断验证码是否正确
①数据库用户数据
②验证码有误
③结果
登录同样,不再演示。
结尾
1、未实现的功能
在注册页面中,输入用户名和密码时,想进行一个表单的校验,
即输入用户名或密码时,鼠标移出输入框,点击鼠标时,会通过正则表达式来校验其用户名或密码的格式是否正确,若是则出现√,否则提示错误。
然后功能并未实现,没想明白
/*
分析:
1.给表单绑定onsubmit事件。监听器中判断每一个方法校验的结果。
如果都为true,则监听器方法返回true
如果有一个为false,则监听器方法返回false
2.定义一些方法分别校验各个表单项。
3.给各个表单项绑定onblur事件。
*/
window.onload = function(){
//1.给表单绑定onsubmit事件
document.getElementById("form").onsubmit = function(){
//调用用户校验方法 chekUsername();
//调用密码校验方法 chekPassword();
//return checkUsername() && checkPassword();
return checkUsername() && checkPassword();
};
//给用户名和密码框分别绑定离焦事件
document.getElementById("username").onblur = checkUsername;
document.getElementById("password").onblur = checkPassword;
};
//校验用户名
function checkUsername(){
//1.获取用户名的值
var username = document.getElementById("username").value;
//2.定义正则表达式
var reg_username = /^\w{6,12}$/;
//3.判断值是否符合正则的规则
var flag = reg_username.test(username);
//4.提示信息
var s_username = document.getElementById("s_username");
if(flag){
//提示绿色对勾
s_username.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
}else{
//提示红色用户名有误
s_username.innerHTML = "用户名格式有误";
}
return flag;
}
//校验密码
function checkPassword(){
//1.获取用户名的值
var password = document.getElementById("password").value;
//2.定义正则表达式
var reg_password = /^\w{6,12}$/;
//3.判断值是否符合正则的规则
var flag = reg_password.test(password);
//4.提示信息
var s_password = document.getElementById("s_password");
if(flag){
//提示绿色对勾
s_password.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
}else{
//提示红色用户名有误
s_password.innerHTML = "密码格式有误";
}
return flag;
}
2、存在的Bug
思路:登录时,若用户名或密码输入错误,则对用户名或密码单独提醒。
结果:无法完成,若用户名或密码输入错误,只能对它们同时提醒。
思考:因为调用以下的查询数据库函数进行封装成User对象时,若从数据库中查询没有结果,则通过调用这个函数返回的结果是null,此时无法再通过调用User对象的getUsername方法或getPassword方法得到数据库中的值。
public User login(User loginUser){
try {
//1.编写sql
String sql = "select * from user where username = ? and password = ?";
//2.调用query方法
User user = template.queryForObject(
sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(),
loginUser.getPassword()
);
return user;
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
3、项目总结
通过Java操作数据库还是很不熟练,对表单校验得操作也有点迷,还有首页很多功能未实现,还是得多学习一下吧。