目录
- 介绍
- 修改成jsp页面并且导入JSTL标签库
- 对公共部分进行抽取
- head部分
- 底部声明部分
- 登录成功后的菜单部分
- 后台的菜单部分
- 数据库用户表的创建
- 对用户提交的表单进行验证
- 导入jQuery
- js验证
- 编写pojo、dao、service、servlet
- 编写pojo
- 编写dao
- 编写servic
- 测试数据库操作
- 编写Servlet
- 页面的处理
- 登陆页面
- 注册页面
- 注销
- 测试
介绍
本套笔记是为了记录Java的学习过程,项目来源;尚硅谷书城项目。该项目的主要功能有:用户注册及登陆、购物车操作、结算及生成订单号、管理员管理图书、管理员管理订单。
修改成jsp页面并且导入JSTL标签库
将所有的html页面全都转换成jsp页面,只需要简单的将后缀名改成jsp,然后加上下述代码即可。修改完成了以后可能有些引入的网址后缀名不会变化,这里不用担心,因为页面比较少,发现一处改一处即可。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
对公共部分进行抽取
拿到页面以后我们发现有很多公共的部分,我们可以将这些这些公共的部分抽取出来,这样修改的时候只需要修改一份就可以了
head部分
每个页面的head部分都需要引入css文件、jQuery文件以及需要设置标签,我们可以抽成一个jsp然后进行引入就可以
抽取出来的内容:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+ request.getContextPath()+"/";
%>
<base href="<%=basePath%>">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>
在其他页面引入:
<%@ include file="/pages/common/head.jsp"%>
底部声明部分
每个页面底部都有声明部分,为了便于管理也可以都抽取出来
抽取部分代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div id="bottom">
<span>
尚硅谷书城.Copyright ©2015
</span>
</div>
引入代码:
<%@ include file="/pages/common/foot.jsp"%>
登录成功后的菜单部分
登录成功以后会有“欢迎xxx光临尚硅谷书城”这部分信息,我们进行抽取
抽取代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
<span>欢迎<span class="um_span">韩总</span>光临尚硅谷书城</span>
<a href="pages/order/order.jsp">我的订单</a>
<a href="index.jsp">注销</a>
<a href="index.jsp">返回</a>
</div>
引入代码:
<%@ include file="/pages/common/login_sucess_menu.jsp"%>
后台的菜单部分
后台管理有“ 图书管理 订单管理 返回商城”这个菜单栏,我们进行抽取
抽取代码:
在这里插入代码片
引入代码:
<%@ include file="/pages/common/manager_menu.jsp"%>
数据库用户表的创建
想要永久化用户数据,必然是需要用到数据库,在本模块中创建一个b_user表,用来存放用户的id、账号、密码和邮箱信息。
首先创建book_stu数据库及b_user表,创建的sql语句如下:
CREATE DATABASE book_stu;
USE book_stu;
CREATE TABLE b_user(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(20) NOT NULL UNIQUE,
`password` VARCHAR(20) NOT NULL,
`email` VARCHAR(200)
);
然后我们插入几条数据,然后查询出来,确保数据库能够能正常工作:
INSERT INTO b_user(`username`,`password`,`email`) VALUE('admin','admin','admin@163.com');
INSERT INTO b_user(`username`,`password`,`email`) VALUE('lxy','lxy','lxy@163.com');
SELECT * FROM b_user
对用户提交的表单进行验证
我们拿到本网站的静态页面,打开注册和登录部分,会看到注册的时候需要填写用户名称、用户密码、确认密码、电子邮件、验证码以及登录的时候需要填写用户名称和用户密码。为了更好的用户体验没我们要在前端使用js进行验证,保证确认密码和用户密码要相同,并且其他项不为空。
导入jQuery
首先在web目录下的static目录创建一个script目录,用来存放jQuery,然后将jQuery复制进去。然后我们在login.html和regist.html中引入jQuery。
<script src="../../static/script/jquery-1.7.2.js" type="text/javascript"></script>
js验证
判断确认密码和用户密码是否相同,并且其他项是否不为空,代码如下:
regist中:
$(function () {
$("#sub_btn").click(function () {
//验证用户名
var usernameText = $("#username").val();
var usernamePatt = /^\w{5,12}$/;
if(!(usernamePatt.test(usernameText)))
{
$(".errorMsg").text("用户名输入不合法")
return false;
}
//验证密码
var passwordText = $("#password").val();
var passwordPatt = /^\w{5,12}$/;
if(!(passwordPatt.test(passwordText))){
$(".errorMsg").text("密码输入不合法");
return false;
}
//验证确认密码
var repwd = $("#repwd").val();
if(repwd != passwordText)
{
$(".errorMsg").text("确认密码和密码不一致");
return false;
}
//验证邮箱
var emailText = $("#email").val();
var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
if (!emailPatt.test(emailText)) {
$("span.errorMsg").text("邮箱格式不合法!");
return false;
}
//验证验证码
var code = $("#code").val();
//验证码去前后空格
code = $.trim(code);
if(code == null || code=="")
{
$("span.errorMsg").text("验证码不能为空!");
return false;
}
//都正确的话清空错误提示信息
$("span.errorMsg").text("");
});
});
login中:
$(function () {
$("#sub_btn").click(function () {
//验证用户名
var usernameText = $("#username").val();
var usernamePatt = /^\w{5,12}$/;
if(!(usernamePatt.test(usernameText)))
{
$(".errorMsg").text("用户名输入不合法")
return false;
}
//验证密码
var passwordText = $("#password").val();
var passwordPatt = /^\w{5,12}$/;
if(!(passwordPatt.test(passwordText))){
$(".errorMsg").text("密码输入不合法");
return false;
}
});
});
编写pojo、dao、service、servlet
编写pojo
将用户抽象成User类、有id,username、password、email四个属性。再提供空参构造器、无参构造器、get和set方法、tostring方法。
private Integer id;
private String username;
private String password;
private String email;
编写dao
首先导入duutils和druid两个jar包,然后创建一个BaseDao类,在这个类中实现通用的增删改查功能。
1.首先创建jdbc.properties配置文件,在文件中填写好数据库账号密码等相关关信息。
username=root
password=root
url=jdbc:mysql://localhost:3306/book
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
2.编写JdbcUtil类,主要用来获取数据库连接和关闭数据库连接。
public class JdbcUtils {
private static DruidDataSource dataSource;
static {
try {
Properties properties = new Properties();
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(is);
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @return
* @Author glq
* @Description 使用德鲁伊获取数据库链接
* @Date 14:04 2020/4/18
* @Param
**/
public static Connection getConnection() {
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* @Author glq
* @Description //TODO 关闭数据库链接
* @Date 14:08 2020/4/18
* @Param [conn]
* @return void
**/
public static void close(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.编写BaseDao类,主要用来实现通用的增删改、查询获取一个JavaBean对象、查询获取JavaBean集合、查询一些特殊的(一行一列)。
public class BaseDao {
private QueryRunner queryRunner = new QueryRunner();
/**
* @Author glq
* @Description 通用的增删改操作
* @Date 13:07 2020/4/18
* @Param [sql, arg]
* @return 成功返回影响的行数,失败返回-1
**/
public int update(String sql,Object... arg){
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.update(connection,sql,arg);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(connection);
}
return -1;
}
/**
* @Author glq
* @Description //TODO 查询一个bean
* @Date 14:16 2020/4/18
* @Param [clazz, sql, arg]
* @return
**/
public <T> T queryForOne(Class<T> clazz,String sql,Object... arg){
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanHandler<T>(clazz),arg);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return null;
}
/**
* @Author glq
* @Description //TODO 查询获取多个JavaBean
* @Date 14:20 2020/4/18
* @Param [clazz, sql, args]
* @return java.util.List<T>
**/
public <T> List<T> queryForList(Class<T> clazz,String sql,Object ... args){
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanListHandler<T>(clazz),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return null;
}
/**
* @Author glq
* @Description //TODO 查询返回一行一列
* @Date 14:22 2020/4/18
* @Param [sql, args]
* @return java.lang.Object
**/
public Object queryForSingleValue(String sql,Object ... args){
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new ScalarHandler(),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return null;
}
}
4.编写UserDao接口和UserDaoImpl实现类, 主要实现根据用户名查询用户、根据用户名和密码查询用户、保存用户三个功能。
public class UserDaoImpl extends BaseDao implements UserDao {
/**
* @Author glq
* @Description //TODO 根据用户名查询用户
* @Date 15:33 2020/4/18
* @Param [username]
* @return com.glq.pojo.User
**/
@Override
public User queryUserByUsername(String username) {
String sql = "select * from b_user where username = ?";
User user = queryForOne(User.class, sql, username);
return user;
}
/**
* @Author glq
* @Description //TODO 根据用户名和密码查询用户
* @Date 15:33 2020/4/18
* @Param [username, password]
* @return com.glq.pojo.User
**/
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql = "select * from b_user where username = ? and password = ?";
User user = queryForOne(User.class, sql, username, password);
return user;
}
/**
* @Author glq
* @Description //TODO 保存用户
* @Date 15:33 2020/4/18
* @Param [user]
* @return int
**/
@Override
public int saveUser(User user) {
String sql = "insert into b_user(username,password,email) values(?,?,?)";
int update = update(sql, user.getUsername(), user.getPassword(), user.getEmail());
return update;
}
}
编写servic
编写UserService接口和EserServiceImpl实现类,主要实现用户登录、用户注册、查询用户名是否存在三个功能。
public class UserServiceImpl implements UserService {
private UserDaoImpl userDao = new UserDaoImpl();
/**
* @Author glq
* @Description //TODO 用户注册
* @Date 15:45 2020/4/18
* @Param [user]
* @return void
**/
@Override
public void registUser(User user) {
userDao.saveUser(user);
}
/**
* @Author glq
* @Description //TODO 用户登录
* @Date 15:45 2020/4/18
* @Param [user]
* @return com.glq.pojo.User
**/
@Override
public User login(User user) {
User result_user = userDao.queryUserByUsernameAndPassword(user.getUsername(), user.getPassword());
return result_user;
}
/**
* @Author glq
* @Description //TODO 查询用户名是否存在
* @Date 15:46 2020/4/18
* @Param [username]
* @return boolean
**/
@Override
public boolean exitsUsername(String username) {
User user = userDao.queryUserByUsername(username);
if(user == null){
return false;
}
return true;
}
}
测试数据库操作
测试Service中的登录、注册、验证用户名是否正确。若正确则dao中一般也不会出问题。
public class UserServiceImplTest {
@Test
public void registUser() {
UserServiceImpl userService = new UserServiceImpl();
userService.registUser(new User(null,"test","test","test@163.com"));
}
@Test
public void login() {
UserServiceImpl userService = new UserServiceImpl();
User login = userService.login(new User(null, "lxy", "lxy", "sdfsdf"));
System.out.println(login);
}
@Test
public void exitsUsername() {
UserServiceImpl userService = new UserServiceImpl();
boolean lxy = userService.exitsUsername("lxy1");
System.out.println(lxy);
}
}
编写Servlet
1.首先编写一个BaseServlet类,让其他的类来继承这个类,然后在这个类中获取action参数,根据这个参数名使用反射的方式获取到同名方法,然后调用通用名方法。这样可以减少大量的if判断。
public class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
System.out.println("BaseServlet被调用,action:"+action);
try {
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.编写UserServlet类,主要实现用户登录、用户注册、判断用户名是否存在、注销用户这四个功能。其中,用户注册的时候要注意判断输入的验证码是否正确,这里借助于谷歌验证码来生成。
public class UserServlet extends BaseServlet {
private UserServiceImpl userService = new UserServiceImpl();
/**
* @Author glq
* @Description //TODO 登录
* @Date 17:17 2020/4/18
* @Param [req, resp]
* @return void
**/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
User login = userService.login(new User(null, username, password, null));
if(login == null){
req.setAttribute("msg","用户名或者密码错误!");
req.setAttribute("username",username);
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
}else{
req.getSession().setAttribute("user",login);
resp.sendRedirect("/pages/user/login_success.jsp");
}
}
/**
* @Author glq
* @Description //TODO 注册
* @Date 17:25 2020/4/18
* @Param [req, resp]
* @return void
**/
protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
User user = WebUtils.copyParamToBain(req.getParameterMap(), new User());
if(token!=null && token.equals(code)){
if(userService.exitsUsername(username)){
req.setAttribute("msg","用户名已存在!");
req.setAttribute("username",username);
req.setAttribute("email",email);
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
}else {
userService.registUser(new User(null,username,password,email));
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);
}
}else{
// 把回显信息,保存到Request域中
req.setAttribute("msg", "验证码错误!!");
req.setAttribute("username", username);
req.setAttribute("email", email);
System.out.println("验证码[" + code + "]错误");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
}
}
/**
* @Author glq
* @Description //TODO 判断用户名是否存在
* @Date 18:21 2020/4/18
* @Param [req, resp]
* @return void
**/
protected void ExitsUsername(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
boolean isExits = userService.exitsUsername(username);
HashMap<String, Object> resultMap = new HashMap<>();
resultMap.put("existsUsername",isExits);
Gson gson = new Gson();
String json = gson.toJson(resultMap);
resp.getWriter().write(json);
}
/**
* @Author glq
* @Description //TODO 注销用户
* @Date 16:44 2020/4/19
* @Param [req, resp]
* @return void
**/
protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("logout被调用");
req.getSession().invalidate();
resp.sendRedirect("index.jsp");
}
}
页面的处理
登陆页面
1.首先要修改form表单的提交信息,修改为:
<form action="userServlet?action=login" method="post">
2.如果登录失败,我们希望页面回显已经输入的用户名信息和错误标签信息。修改后的代码为:
<span class="errorMsg">${empty requestScope.msg ? "请输入用户名和密码":requestScope.msg}</span>
</div>
<div class="form">
<form action="userServlet?action=login" method="post">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1" name="username" id="username" value="${requestScope.username}"/>
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password" id="password"/>
<br />
<br />
<input type="submit" value="登录" id="sub_btn" />
</form>
</div>
注册页面
1.当输入用户名的内容发生改变的时候发送一个AJAX请求,来判断用户名是否存在,并且在错误标签输出相应的提示信息。
$("#username").blur(function () {
var username = this.value;
$.getJSON("userServlet","action=ExitsUsername&username="+username,function (data) {
if(data.existsUsername){
$(".errorMsg").text("用户名已经存在!");
}else
{
$(".errorMsg").text("用户名可以使用!");
}
})
});
2.在点击验证码图片的时候刷新验证码图片的地址
$("#code_img").click(function () {
this.src="${basePath}kaptcha.jpg?d="+new Date();
});
3.修改form表单的提交信息和用户名邮箱的回显
<form action="userServlet?action=regist" method="post">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1" name="username" id="username" value="${requestScope.username}"/>
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password" id="password" />
<br />
<br />
<label>确认密码:</label>
<input class="itxt" type="password" placeholder="确认密码" autocomplete="off" tabindex="1" name="repwd" id="repwd" />
<br />
<br />
<label>电子邮件:</label>
<input class="itxt" type="text" placeholder="请输入邮箱地址" autocomplete="off" tabindex="1" name="email" id="email" value="${requestScope.email}"/>
<br />
<br />
<label>验 证 码:</label>
<input class="itxt" type="text" name="code" style="width: 120px;" id="code" value=""/>
<img id="code_img" alt="" src="kaptcha.jpg" style="float: right; margin-right: 40px; width: 100px; height: 40px;">
<br />
<br />
<input type="submit" value="注册" id="sub_btn" />
</form>
注销
修改注销的地址,这里主要有两处,一处是抽取出来的公共部分中的,另一处是index.jsp中的。
<a href="userServlet?action=logout">注销</a>
测试
至此,用户部分的功能都已经完成了,测试一下是否能够正常注册、登录、注销。修改成jsp页面导致的链接错误只需要该一下即可。