商品展示
一、验证码
验证码展示
<img id="pagecode" src="/user?action=valid">
//在UserController中验证码展示
public void valid(HttpServletRequest request,HttpServletResponse response) throws IOException {
ValidateCode vc = new ValidateCode(120, 50, 1, 5);
System.out.println("验证码:"+vc.getCode());
request.getSession().setAttribute("imgCode",vc.getCode());
vc.write(response.getOutputStream());
}
验证码校验
//3.验证输入的验证码 是否正确
$("#vcode").change(function(){
$.get("/user","action=checkCode&code="+this.value,function(data){
if(data==0){
$("#checkMsg").html("<font color='green'>OK</font>");
$("#btn").removeAttr("disabled");
}else{
$("#checkMsg").html("<font color='red'>ERROR</font>");
$("#btn").prop("disabled",true); //设置disable属性
}
})
});
//验证码校验
public String checkCode(HttpServletRequest request,HttpServletResponse response){
String code = request.getParameter("code"); //获取表单子控件验证码值
//获取验证码图片的内容
String imgCode = (String) request.getSession().getAttribute("imgCode");
if(code.equalsIgnoreCase(imgCode)){
return "0"; //0代表验证成功
}else{
return "1"; //1代表验证失败
}
}
刷新验证码
//2.点击验证码 跟新验证码
$("#pagecode").click(function(){
$("#pagecode").attr("src","/user?action=valid&c=?"+Math.random());
});
二、记录账户
在登录成功后,如果勾选了"记录登录账户",则存储Cookie;在展示首页时,获取cookie,根据存储的cookie,取出后进行登录测试,如果登录成功,则设置凭证。
设置Cookie
//记录登录账户:
String auto = request.getParameter("auto");
Cookie cookie = new Cookie(ConstUtils.UPASS,username+"-"+password);
if(auto!=null){ //不为null,则说明勾选了;为null则去掉勾选
cookie.setMaxAge(60*60*24*14); //单位秒 14天
}else{
cookie.setMaxAge(0); //清除cookie
}
response.addCookie(cookie);
获取Cookie
在首页中获取Cookie:
<%
//获取Cookie
Cookie[] cookies = request.getCookies();
String username = null; //接收用户名和密码
String password = null;
if(cookies!=null){
for(Cookie c:cookies){ //循环变量,并判断登录cookie
if(c.getName().equals(ConstUtils.UPASS)){
username = c.getValue().split("-")[0];
password = c.getValue().split("-")[1];
break;
}
}
}
//判断是否取到登录cookie值
if(username!=null&&password!=null){
UserService userService = new UserServiceImpl();
User user = userService.login(username,password); //交给业务层登录
//对应的设置凭证
request.getSession().setAttribute(ConstUtils.LOGIN,user);
}
%>
清除cookie
点击首页”注销“,可以清除cookie及登录凭证
//在header.jsp中触发注销功能
<a href="user?action=logOut" id="a_top">注销</a>
//注销session与cookie
public String logOut(HttpServletRequest request,HttpServletResponse response){
//移除session
request.getSession().removeAttribute(ConstUtils.LOGIN);
//清除cookie
Cookie cookie = new Cookie(ConstUtils.UPASS,"xxx");
cookie.setMaxAge(0); //立马失效
response.addCookie(cookie);
return ConstUtils.RED+"/index.jsp";
}
三、商品类别
访问首页时,会报错误,原因是访问商品类别失败;需要创建商品类别模块
创建类别模块
在控制层和service和DAO层分别创建商品类别模块;并修改类别实体
展示类别信息
在header.jsp中发送ajax请求,在类别controller中处理
$.ajax({
url:"${pageContext.request.contextPath}/type?action=show",
type:"GET",
//dataType:"json", //返回json字符串后,进行json解析成对象
success:function(data){
data= JSON.parse(data); //解析成对象
for(var i in data){
var a = $("<a href='${pageContext.request.contextPath}/getGoodsListByTypeId?typeid="+data[i].t_id+"'>"+data[i].t_name+"</a>");
$("#goodsType").append(a);
}
},
error:function(){
alert("失败");
}
})
在控制层接收请求,并交给业务层处理
@WebServlet("/type")
public class TypeController extends BaseServlet {
private TypeService typeService = new TypeServiceImpl();
public String show(HttpServletRequest request, HttpServletResponse response){
List<Type> list = typeService.showAll(); //查询类别
//将对象解析成json数据,回传出去
return new Gson().toJson(list);
}
}
四、商品管理
商品展示
点击商品类别,匹配类别ID,将所有商品展示出来;在后台需要创建商品的控制层,service层,DAO层。
//header.jsp中发请求
var a = $("<a href='${pageContext.request.contextPath}/goods?action=show&tid="+data[i].t_id+"'>"+data[i].t_name+"</a>");
@WebServlet("/goods")
public class ProductController extends BaseServlet {
private GoodsService goodsService = new GoodsServiceImpl();
public String show(HttpServletRequest request,HttpServletResponse response){
System.out.println("产品展示");
//获取tid参数
int tid = Integer.parseInt(request.getParameter("tid"));
//再调用业务层,返回集合
List<Product> list = goodsService.showByTid(tid);
//产品展示完成,进行转发
request.setAttribute("glist",list);
return ConstUtils.FOR +"/goodsList.jsp";
}
}
//返回到goodsList.jsp中
<c:forEach items="${glist}" var="g" varStatus="i">
<div class="col-sm-3">
<div class="thumbnail">
<img src="${pageContext.request.contextPath}/${g.p_image}" width="180" height="180" alt="小米6" />
<div class="caption">
<h4>商品名称<a href="${pageContext.request.contextPath}/getGoodsById?id=${g.p_id}">${g.p_name}</a></h4>
<p>热销指数
<c:forEach begin="1" end="${g.p_state}">
<img src="image/star_red.gif" alt="star"/>
</c:forEach>
</p>
<p>上架日期:${g.p_time}</p>
<p style="color:orange">价格:${g.p_price}</p>
</div>
</div>
</div>
</c:forEach>
商品分页
将分页功能的DAO层进行测试
@Override //分页具体实现
public List<Product> selectByPage(int startIndex, int pageSize,int tid) throws SQLException {
String sql = "select * from product where t_id=? limit ?,?";
return runner.query(sql,new BeanListHandler<>(Product.class),tid,startIndex,pageSize);
}
封装Page,创建Page实体,并在业务层封装
public Page<Product> getPage(int tid, String current) {
int currentPage = 1;
int pageSize = 4;
if(current!=null){
currentPage = Integer.parseInt(current); //当前页赋值
}
Page<Product> page = new Page<>(currentPage,pageSize);
try {
long totalCount = goodsDao.getTotalCount(tid); //dao层获取总条数
page.setTotalCount(totalCount); //设置总条数
long pageCount = (totalCount%pageSize==0)?totalCount/pageSize:totalCount/pageSize+1;
page.setPageCount(pageCount); //设置总页数
int startIndex = (currentPage-1)*pageSize; //求起始行
//设置内容
page.setList(goodsDao.selectByPage(startIndex,pageSize,tid));
}catch (Exception e){
e.printStackTrace();
}
return page;
}
//在控制层,返回分页信息
public String show(HttpServletRequest request,HttpServletResponse response){
System.out.println("产品展示");
//获取tid参数
int tid = Integer.parseInt(request.getParameter("tid"));
String current = request.getParameter("currentPage");
Page<Product> page = goodsService.getPage(tid, current);
//存储分页信息
request.setAttribute("p",page);
return ConstUtils.FOR +"/goodsList.jsp";
}
测试链接:http://localhost:8080/goods?action=show&tid=1¤tPage=1
展示页面: <c:forEach items="${p.list}" var="g" varStatus="i">
前端展示分页效果,使用显示页数的方式(使用bootstrap中的分页标签)
<ul class="pagination"><%--分页效果:class="pagination"--%>
<c:if test="${p.currentPage!=1}"><%--不是第一页则可显示上一页 --%>
<li> <%--${param.tid}:从参数中获取tid的值--%>
<a href="/goods?action=show&tid=${param.tid}¤tPage=${p.currentPage-1}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
</c:if>
<%-- 循环从起始1到到页数量的范围 begin:起始值 end:结束值
varStatus:取值状态 --%>
<c:forEach begin="1" end="${p.pageCount}" varStatus="vs">
<%-- vs.index:从begin开始取值 --%>
<c:choose>
<c:when test="${p.currentPage==vs.index}">
<li class="active"><a href="/goods?action=show&tid=${param.tid}¤tPage=${vs.index}">${vs.index}</a></li>
</c:when>
<c:otherwise><li><a href="/goods?action=show&tid=${param.tid}¤tPage=${vs.index}">${vs.index}</a></li></c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${p.currentPage!=p.pageCount}"><%--不是尾页,则显示下一页--%>
<li>
<a href="/goods?action=show&tid=${param.tid}¤tPage=${p.currentPage+1}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</c:if>
</ul>
五、单品展示
点击单个商品信息,进入到单个商品的详情介绍
//在goodsList.jsp中点击单品展示
<h4>商品名称<a href="${pageContext.request.contextPath}/goods?action=goodsDetail&pid=${g.p_id}">${g.p_name}</a></h4>
//展示单个商品详情
public String goodsDetail(HttpServletRequest request,HttpServletResponse response){
//获取参数信息
int pid = Integer.parseInt(request.getParameter("pid"));
Product product = goodsService.showByPid(pid); //根据pid,获取唯一信息
request.setAttribute("goods",product);
return ConstUtils.FOR+"/goodsDetail.jsp";
}
//goodsDetail.jsp页面展示详情信息
<h3>产品名称:<small>${goods.p_name}</small></h3>
<div style="margin-left: 10px;">
<p>市场价格: <span class="text-danger" style="font-size: 15px;">${goods.p_price}</span> <span class="glyphicon glyphicon-yen"></span></p>
<p>上市时间: ${goods.p_time}</p>
<p>热销指数:
<c:forEach begin="1" end="${goods.p_state}">
<img src="image/star_red.gif" alt="star"/>
</c:forEach>
</p>
...
六、加入购物车
购物车模块
准备购物车的实体类,控制层,service层及DAO层
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Cart {
private int c_id; //购物车ID
private int u_id; //用户ID
private int p_id; //商品ID
private BigDecimal c_count; //商品小计
private int c_num; //商品数量
}
思考添加购物车
点击单品展示中“添加购物车”按钮,传入pid,price,uid(登录凭证中获取-购物车控制层操作);在控制层中如果没有登录凭证,则需要重新登录,如果有,则获取到uid。
注意:如果之前添加过购物车,则修改数量和小计;如果没有添加过购物车,则添加,数量为1,小计=价格
七、总结与作业
总结
1.验证码
用户模块-验证码的展示,校验,刷新
2.记录账户(重点)
用户模块-设置cookie(登录成功且勾选记录),获取cookie(首页),清除cookie
3.商品类别管理
创建类别模块-实体类,控制层,业务层,DAO层
在首页展示类别信息
4.商品管理(重点)
商品展示-根据类别id展示商品
商品分页-分页DAO测试,封装Page,分页展示
5.单品展示
点击单个商品,根据pid获取单个商品参数
作业
1.独立完成今天的所有模块功能
2.添加购物车,不考虑修改数量情况(数量为1)
晨考
手写商品的Page在业务层封装(仅仅写业务层代码即可-封装5个属性的设置)
import java.util.List;
public class ProductPage {
private int currentPage; // 当前页码
private int pageSize; // 每页显示的记录数
private int totalRecords; // 总记录数
private int totalPages; // 总页数
private List<Product> productList; // 当前页的商品列表
// 构造函数
public ProductPage(int currentPage, int pageSize, int totalRecords, List<Product> productList) {
this.currentPage = currentPage;
this.pageSize = pageSize;
this.totalRecords = totalRecords;
this.productList = productList;
// 计算总页数
this.totalPages = (int) Math.ceil((double) totalRecords / pageSize);
}
// Getter 和 Setter 方法
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalRecords() {
return totalRecords;
}
public void setTotalRecords(int totalRecords) {
this.totalRecords = totalRecords;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public List<Product> getProductList() {
return productList;
}
public void setProductList(List<Product> productList) {
this.productList = productList;
}
}