javaweb项目之(书城项目)的功能实现(最全没有之一)

2022年05月10日 阅读数:11
这篇文章主要向大家介绍javaweb项目之(书城项目)的功能实现(最全没有之一),主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。
用户的登录注册
-bean:实体类的建立(要和数据库字段一一对应);
-dao|daoimpl:
-1.根据用户和密码查找用户是否存在(登录)
-2.查找是否用户名被占用(注册)
-3.保存用户信息(注册)
-service|serviceImpl:
-1.登录的功能
-2.查找用户名是否存在
-3.注册的功能
-servlet:
-1.登录的功能:
-步骤: 1.)首先是获取前台输入的帐号和密码
2.)调用service中的根据用户和密码查找用户的方法
3.)若是有返回成功页面,若是没有该用户返回登录页面,并回显错误信息
4.)登录成功时将用户信息保存到session的域对象中
-2.注册的功能:
-步骤: 1.)获取前台的数据信息并封装到bean中
2.)首先获取输入的验证码,和谷歌的验证码进行对比,若是一致说明正确。不一致,则错误并回显信息
3.)若是验证码一致,则进行用户名的查新和判断。若是用户名已存在,则注册失败,回显信息。若是成功则注册成功。
-3.注销的功能:
-步骤: 1.)首先获取session的对象的user的对象
2.)调用session 的remove的方法进行移除
3.)转发到起始页
经常使用知识点:
1.把用户存到session域中(为了过滤器的使用,过滤没有登陆就不能查看的页面)
2.谷歌验证码:
1.)添加类库kaptcha

2.)配置web.xml(若是是中文的话要说明格式,图片的格式要修改)
<servlet>
<servlet-name>kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<init-param>
<!-- 记住,kaptcha默认是英文验证码,不须要配置,若是改为中文验证码的时候,必定要加上中文字体配置。不然会有乱码  -->
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>楷体</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>kaptcha</servlet-name>
<url-pattern>/kaptcha.png</url-pattern>
</servlet-mapping>

3.)servlet的编写:
// 获取以前生成的验证码
String code = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
// 移除生成的验证码
request.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);


4.)在页面中使用<img>标签的src属性引入访问路径。(验证码前端验证须要结合Ajax使用。)
<!--  使用img标签引入验证码。也可使用width和height属性控制验证码的大小  -->
<img alt="验证码找不到" src="kaptcha.png" width="80" height="25" />


3.登录表单验证:
<script type="text/javascript">
// 页面加载完成以后
$(function(){

// 给注册按钮添加事件
$("#sub_btn").click(function(){

// 获取用户名
var usernameValue = $("#username").val();
// 验证用户名是否合法,规则以下:必须由字母,数字,下划线组成,而且长度为5到15位。
var usernameReg = /^\w{5,15}$/;
// 验证用户信息
if (!usernameReg.test(usernameValue)) {
// 提示用户
alert("用户名不合法!");
return false;
}

// 获取密码
var passwordValue = $("#password").val();
// 验证密码是否合法,规则以下:必须由字母,数字,下划线组成,而且长度为5到15位。
var passwordReg = /^\w{5,15}$/;
// 验证用户信息
if (!passwordReg.test(passwordValue)) {
// 提示用户
alert("密码不合法!");
return false;
}

// 阻止表单提交
return true;
});

});
</script>

4.注册表单验证:

-1)获取姓名输入框:servlet的验证
public void checkUsername(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.先获取用户名参数。
String username = request.getParameter("username");
// 2.调用UserService.existUsername验证用户名是否存在。
boolean existUsername = userService.existUsername(username);
// 3.把结果输出给客户端
// 若是返回值为真,说明用户名已存在

Gson gson = new Gson();
Map<String, String> result = new HashMap<String, String>();
if (existUsername) {
//表示用户名已存在
result.put("result", "1");
} else {
//用户名不存在的状况
result.put("result", "0");
}
String mapJson = gson.toJson(result);
response.getWriter().write(mapJson);
}
2.)JQuery 的验证以及用Ajax对用户名是否存在的验证的编写
<script type="text/javascript">
// 页面加载完成以后
$(function(){
//1.先给用户名输入框绑定失去焦点事件
$("#username").blur(function(){
//2.获取用户名输入框中的文本内容
//alert( this.value );
// 3.发起一个Ajax请求到服务器去验证
$.getJSON(
"userServlet",
"action=checkUsername&username=" + this.value + "&d=" + new Date(),
function(data){
// 4.收到响应后,提示用户响应的结果
// 若是result == 1.说明用户名已存在
if (data.result == "1") {
$("span.errorMsg").html("用户名已存在!");
} else if (data.result == "0") {
// 用户名不存在,可用。
$("span.errorMsg").html("");
}
}
);
});

//刷新页面,验证码更新
$("#imgCode").click(function(){
this.src = "kaptcha.png?d="+new Date();
});

// 给注册按钮添加事件
$("#sub_btn").click(function(){
// 获取用户名
var usernameValue = $("#username").val();
// 验证用户名是否合法,规则以下:必须由字母,数字,下划线组成,而且长度为5到15位。
var usernameReg = /^\w{5,15}$/;
// 验证用户信息
if (!usernameReg.test(usernameValue)) {
// 提示用户
alert("用户名不合法!");
return false;
}

// 获取密码
var passwordValue = $("#password").val();
// 验证密码是否合法,规则以下:必须由字母,数字,下划线组成,而且长度为5到15位。
var passwordReg = /^\w{5,15}$/;
// 验证用户信息
if (!passwordReg.test(passwordValue)) {
// 提示用户
alert("密码不合法!");
return false;
}

// 获取确认密码
var repwdValue = $("#repwd").val();
// 验证确认密码和密码一致
if (passwordValue != repwdValue) {
// 提示用户
alert("确认密码和密码不一致!");
return false;
}

// 获取用户名
var emailValue = $("#email").val();
// 验证邮件输入是否合法。
var emailReg = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;

if (!emailReg.test(emailValue)) {
// 提示用户
alert("邮件输入不合法!");
return false;
}
// 获取验证码信息
var codeValue = $("#code").val();
// 验证验证码不为空!
if (codeValue == "") {
alert("验证码不能为空!");
}
return true;
});
});
</script>

图书的增删查改以及分页
-bean:实体类book和page的建立(要和数据库字段一一对应);
-dao|daoimpl:
-1.保存图书
-2.修改图书
-3.删除图书
-4.根据id查找图书
-5.查询全部的图书
-6.分页后的数据展示
-7.图书总记录数
-8.按照价格分页
-9.分页以后的记录数
-service|serviceImpl:
-1.保存图书
-2.修改图书
-3.删除图书
-4.根据id查找图书
-5.查询全部的图书
-6.分页
-7.按照价格分页
-servlet:
-1.图书展示的功能:
-步骤: 1.)首先调用service的方法查找全部的数据
2.)将查找的全部的数据保存到request的中去
3.)用转发的方式进行数据的传输
4.)在展台的页面的时候进行数据的遍历
-2.图书分页后的展示的功能:
-步骤: 1.)首先获取前台传过来的页码和每页的数据条数
2.)首先调用service的方法查找全部的数据
3.)将查找的全部的数据保存到request的中去
4.)用转发的方式进行数据的传输
5.)在展台的页面的时候进行数据的遍历
-3.图书的删除功能:
-步骤: 1.)首先获取前台传过来的id
2.)根据id,调用service的方法进行删除操做
3.)并返回当前页面
-4.图书的添加功能:
-步骤: 1.)首先获取前台传来的图书的信息
2.)调用service的方法进行保存
3.)保存完以后返回到当前页面
-5.图书的修改功能+获取图书的功能:(因为修改图书须要将信息回显到修改的页面)
-步骤:
获取图书的功能:
1.)首先获取到前台要修改的id
2.)根据id,调用service的方法查找图书信息
3.)将图书信息保存到rquest域中并将转发当前页面
修改图书的功能:
1.)首先获取前台修改后的数据,并封装到bean
2.)调用service的修改的方法,并将修改后的数据保存到request 的域中
3.)转发到当前页面
前台展现页面:
经常使用知识点:
1.)隐藏域的使用,用于存放方法名,经过baseServlet 的反射进行servlet的方法的调用
2.)JTEL的使用判断是否
<form action="manager/bookServlet" method="post">
<input type="hidden" name="pageNo" value="${ param.pageNo }" />
<c:choose>
<c:when test="${ empty requestScope.book }">
<input type="hidden" name="action" value="addBook"/>
</c:when>
<c:otherwise>
<input type="hidden" name="action" value="updateBook"/>
<input type="hidden" name="id" value="${ book.id }"/>
</c:otherwise>
</c:choose>
3.)是否肯定删除
<script type="text/javascript">
$(function(){
$("a.deleteBook").click(function(){
var name = $(this).parent().parent().find("td:first").text();
var result = confirm("你肯定删除【"+name+"】记录吗?");
if(result){
return true;
}
return false;
});
})
</script>
4.)分页的页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>


<div id="page_nav">
<a href="${ page.url }&pageNo=1">首页</a>
<c:if test="${ page.pageNo > 1 }">
<a href="${ page.url }&pageNo=${ page.pageNo - 1 }">上一页</a>
</c:if>
<c:choose>
<%-- 这是总页码小于等于5的状况 --%>
<c:when test="${ page.pageTotal <= 5 }">
<c:set value="1" var="begin" scope="page"></c:set>
<c:set value="${ page.pageTotal }" var="end" scope="page"></c:set>
</c:when>
<%-- 总页码大于5的状况 --%>
<c:otherwise>
<%-- 若是总页码大于5,又分三种状况 --%>
<c:choose>
<%-- 当前页码是小于等于3的状况 --%>
<c:when test="${ page.pageNo <= 3 }">
<c:set value="1" var="begin" scope="page"></c:set>
<c:set value="5" var="end" scope="page"></c:set>
</c:when>
<%-- 当前页码是最后的三位的时候 --%>
<c:when test="${ page.pageNo >= page.pageTotal - 2 }">
<c:set value="${ page.pageTotal - 4 }" var="begin" scope="page"></c:set>
<c:set value="${ page.pageTotal }" var="end" scope="page"></c:set>
</c:when>
<%-- 其余状况 --%>
<c:otherwise>
<c:set value="${ page.pageNo - 2 }" var="begin" scope="page"></c:set>
<c:set value="${ page.pageNo +2 }" var="end" scope="page"></c:set>
</c:otherwise>
</c:choose>
</c:otherwise>
</c:choose>


<c:forEach begin="${ pageScope.begin }" end="${ pageScope.end }" var="i">
<c:if test="${ i == page.pageNo }">
【${ i }】
</c:if>
<c:if test="${ i != page.pageNo }">
<a href="${ page.url }&pageNo=${ i }">${ i }</a>
</c:if>
</c:forEach>



<c:if test="${ page.pageNo < page.pageTotal }">
<a href="${ page.url }&pageNo=${ page.pageNo + 1 }">下一页</a>
</c:if>
<a href="${ page.url }&pageNo=${ page.pageTotal }">末页</a>
共${ page.pageTotal }页,${ page.pageTotalCount }条记录 到第<input value="${ page.pageNo }" name="pn" id="pn_input"/>页
<input id="search_page_btn" type="button" value="肯定">
</div>

<script type="text/javascript">
//页面加载完成以后
$(function(){
// 给搜索页面的按钮添加单击事件
$("#search_page_btn").click(function(){
// 1.当点击按钮后要获取输入框中输入指定页码----添加单击事件
var cur_pageNo = $("#pn_input").val();
// alert(cur_pageNo);
// 2.而后发起请求http://localhost:8080/book/manager/bookServlet?action=page&pageNo=获得的页码
// 在js中有一个location对象,它有一个属性。叫href。这个属性是可读可写的。href属性表示浏览器地址栏中的信息。
// alert(location.href);
location.href = "${ page.url }&pageNo=" + cur_pageNo;
// 3.在页码框中回显当前页码
});
});
</script>
购物车的模块:(利用session域的形式来进行购物车模块的编写)
-bean: 实体类cartItem的建立(id,name,count,price,totalMoney)
实体类cart的建立;(注意:金钱的属性用BigDecimal,值不能为double类型,能够在后边+""的形式)
-1.)Map(Integer,Object)商品的信息
-2.)总的数量(建立初始值为零,并进行商品的遍历,进行数量的累加,返回累加的值)
-3.)总的价格(建立总价格的初始值BigDecimal为零,进行遍历,并将单类总价格累加,返回全部商品总的价格)
-4.)添加商品(形参为CartItem ,根据形参的id,来用map的key判断是否存在该商品,若是不存在就直接保存到map集合,若是存在就修改数量和总价格)
-5.)修改商品(id,count)根据id判断是否存在该商品,若是存在就直接修改数量和总价格,并返回总的价格。
-6.)删除商品(id)根据id直接在map中移除商品
-7.)清空购物车 直接调用clear()方法
-servlet:
调用bookService的方法
1.添加功能:
-1.)首先获取id,根据id 查找图书
-2.)在session域中查找cart,若是没有就建立并添加到session域中,若是有直接添加,并将图书名传到session域中
-3.)使用ajax的方法 Gson,并建立map对象,将总的数量和最后添加的图书名传进去,
-4.)response.getWriter().write(gson.toJson(result));

2.修改功能:
-1.)获取id和数量
-2.)在session域中查找cart,若是没有就建立并添加到session域中,若是有直接调用修改的方法
-3.)使用ajax的方法 Gson,并建立map对象,将商品的总价和购物车总的数量和购物车总的价格传进去,
-4.)输出到客户端response.getWriter().write(gson.toJson(result));

3.删除商品:
-1.)获取商品的id
-2.)在session域中查找cart,存在时就调用删除的方法
-3.)返回到当前页面response.sendRedirect(request.getHeader("referer"));
4.清空购物车
-1.)在session域中查找cart,存在时就调用清空的方法
-2.)返回到当前页面response.sendRedirect(request.getHeader("referer"));
前台页面:
经常使用知识点:
1.)进行购物车的清空和删除提示,商品数量的修改
<script type="text/javascript">
//页面加载完成以后
$(function(){
// 清空购物车的提示
$("#clearCart").click(function(){
return confirm("你肯定清空购物车吗?");
});
// 删除商品的提示
$("a.deleteItem").click(function(){
// 提示用户肯定 删除
return confirm("你肯定删除商品吗?");
// return 能够阻止元素的默认操做。
// return false;
});

$(".updateClass").change(function(){
//1.提示用户是否修改商品数量
if ( confirm("你肯定修改商品数量为:" + this.value) ){
//2.若是用户赞成修改,发起请求到服务器修改商品数量
var id = $(this).attr("oid");
// location.href="cartServlet?action=updateCount&id=" + id+"&count="+this.value;
// 一、只须要使用Ajax请求来代替原来 location.href 的请求
$.getJSON(
"cartServlet",
"action=updateCountAjax&id=" + id+"&count="+this.value + "&d=" + new Date(),
function(data) {
// 二、从服务器返回单个商品的总价,以及购物总的商品数量和购物总金额 ,而后局部更新购物车内容
console.log(data);
$(".b_count").html(data.cart_totalCount);
$(".b_price").html(data.cart_totalMoney);
$("#item_totalMoney_" + id).html(data.item_totalMoney);
}
);
} else {
//3.若是用户不一样意,就恢复原来的数量
// 有两个方案。一个方案是再添加一个属性,保存原来的数量
// this.value = $(this).attr("ov");
// 第二种方案。经过文本输入框的dom对象的一个属性,叫作defaultValue
this.value = this.defaultValue;
}
});
});
</script>

2.)在主页面中进行商品添加的事务操做
<script type="text/javascript">
$(function(){
// i.先给添加商品,添加单击事件
$("a.addItem").click(function(){
// ii.想办法获取到你当前添加的商品的id编号
var id = $(this).attr("oid");
$.getJSON(
"cartServlet",
"action=addItemAjax&d=" + new Date() + "&id=" + id,
function(data){
// iv.返回购物车中总的商品数量和,最后一次购物商品名称。更新。
// alert(data);
$("#cart_totalCount").html("您的购物车中有 " + data.cart_totalCount +"件商品");
// 最后一次添加的商品名称
$("#cart_last_product").html("您刚刚将<span style='color: red'>" + data.last_product  + "</span>加入到了购物车中");
}
);
// return false 阻止原来a标签的请求
return false;
});
});
</script>


订单管理模块:

-bean:实体类orderItem和order的建立(要和数据库字段一一对应);
-dao|daoimpl:
orderDao|orderDaoImpl:
-1.保存订单
-2.根据userid查找个人订单
-3.查询全部的订单
-4.修改订单状态
orderItemDao|orderItemDaoImpl:
-1.保存订单项
-2.查询订单项
-service|serviceImpl:
orderService|orderServiceImpl:
-1.生成订单
-2.根据userid查找个人订单
-3.订单详情(根据订单id)
-4.查询全部的订单(管理员)
-5.发货
-6.收货
-servlet:
一、订单的生成
二、个人订单列表  
三、订单详情
四、管理员--查看全部订单
五、确认发货
六、用户确认收货
七、最后优化批量SQL

经常使用知识点:
优化批量的sql:
咱们先在BaseDaoImpl中添加方法:


/**
* 执行批量操做

* @param sql
*            要执行的sql语句
* @param params
*            参数
* @return 返回每一个语句修改的数量
*/
public int[] batch(String sql, Object[][] params) {
Connection connection = null;


try {
// 获取数据库链接
connection = JDBCUtils.getConnection();
// 执行查询语句
return queryRunner.batch(connection, sql, params);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.closeConnection(connection);
}


return null;
}






在OrderItemDao中添加接口方法:
/**
* 保存订单项

* @param item
*            保存的订单项
*/
public void batchSaveOrderItem(Collection<OrderItem> items);

在OrderItemDaoImpl方法中添加实现:
@Override
public void batchSaveOrderItem(Collection<OrderItem> items) {
// 插入sql语句
String sql = "insert into t_order_item(`name`,`price`,`total_money`,`count`,`order_id`) values(?,?,?,?,?)";
// 建立一个二组数组
Object[][] params = new Object[items.size()][5];
int i = 0;
// 遍历每个订单项,建立参数
for (OrderItem item : items) {
Object[] oneParams = params[i];
oneParams[0] = item.getName();
oneParams[1] = item.getPrice();
oneParams[2] = item.getTotalMoney();
oneParams[3] = item.getCount();
oneParams[4] = item.getOrderId();
i++;
}
// 执行sql
batch(sql, params);
}



订单的建立:
public String createOrder(Cart cart, int userId) {
// 生成订单号,使用用户id+当前时间
String orderId = userId + "" + System.currentTimeMillis();
// 生成一个订单对象
Order order = new Order(orderId, new Date(), cart.getTotalMoney(), 0, userId);
// 把订单保存到数据库
orderDao.saveOrder(order);
//我在保存订单以后 ,生成一个错误。
// int i = 12 / 0;

// 保存订单项
List<OrderItem> orderItems = new ArrayList<OrderItem>();
// 遍历购物车中的每个购物项,生成订单项OrderItem
for (CartItem cartItem : cart.getItems().values()) {
// 把购物车中的每个商品项转化成为订单项
OrderItem orderItem = new OrderItem(0, cartItem.getName(), cartItem.getCount(),
cartItem.getMoney(), cartItem.getTotalMoney(), orderId);
orderItems.add(orderItem);
// 保存到数据库
// orderItemDao.saveOrderItem(orderItem);
// 从购物项的id中获取商品的编号
Book book = bookDao.queryBook(cartItem.getId());
// 把原来的销量加上购物车中的数量 ,获得新的销量
book.setSales( book.getSales() + cartItem.getCount() );
// 把原来 的库存量,减去,购物车中的数量,获得新的库存量
book.setStock( book.getStock() - cartItem.getCount() );
bookDao.updateBook(book);
}