【JAVA EE#4】【传智书城·源码阅读】首页逻辑:页面头部登陆前后不同状态+分类显示图书+搜索查询图书+轮播图+本周热卖推荐+公告展示

主要逻辑:
在这里插入图片描述

页面头部登陆前后不同状态
登陆前后主要区别体现在首页的头部:
登录前,右上角最后一个为新用户注册,下面并无登陆者信息:
在这里插入图片描述
登陆后,右上角最后一个为退出登录,下面同时显示登陆者信息:
在这里插入图片描述
jsp中实现原理:

<% 
User user = (User) request.getSession().getAttribute("user");
if(null == user){
%>
| <a href="${pageContext.request.contextPath}/client/register.jsp">新用户注册</a>							
<% 	
}else{
%>
| <a href="${pageContext.request.contextPath}/logout" onclick="javascript:return confirm_logout()">用户退出</a>
<br><br><br>欢迎您: ${user.username}
<% 	
}
%>		

可见骚气的if语句分开显示不同情况下的页面内容,登陆前显示新用户注册登陆后变为退出登录,onclick属性指向一个自定义函数,弹出一个确认退出的提示,在接受到确定之后才调用LogoutServlet后直接销毁Session。值得注意在Session获取User之前,要导包,不然js中不能识别该类。

<%@ page import="cn.itcast.itcaststore.entity.User"%>

除此之外,视有无登录情况,头部我的账户会有变化,没有登录就会跳转登录界面,已经登陆就会重定向到账户信息页面,除此之外,根据角色的不同,登陆后我的账户也会有不同的目标页面,普通用户跳转至home.jsp,超级用户跳转至myAccount.jsp后台管理页面,这一套逻辑由web.xml映射的MyAccountServlet完成。

<a href="${pageContext.request.contextPath}/myAccount">我的帐户</a>

MyAccountServlet:

//在session中查找名为“user”的会话
		User user = (User) request.getSession().getAttribute("user");
		//如果找到没有名为“user”的会话,说明用户没有登录,此时跳转到登录页面
		if (user == null) {
			response.sendRedirect(request.getContextPath() + "/client/login.jsp");
			return;
		}
		//如果是超级用户,进入到网上书城后台管理系统;否则进入到普通用户的账户信息页面
		if ("超级用户".equals(user.getRole())) {
			response.sendRedirect(request.getContextPath() + "/admin/login/home.jsp");
//			return;
		}else{
			response.sendRedirect(request.getContextPath() + "/client/myAccount.jsp");
//			return;
		}

分类显示图书
menu_search.jsp文件中分类栏:

<div id="divmenu">
		<a href="${pageContext.request.contextPath}/showProductByPage?category=文学">文学</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=生活">生活</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=计算机">计算机</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=外语">外语</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=经营">经管</a>
		<a href="${pageContext.request.contextPath}/showProductByPage?category=励志">励志</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=社科">社科</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=学术">学术</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=少儿">少儿</a>
		<a href="${pageContext.request.contextPath}/showProductByPage?category=艺术">艺术</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=原版">原版</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=科技">科技</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage?category=考试">考试</a>
		<a href="${pageContext.request.contextPath}/showProductByPage?category=生活百科">生活百科</a> 
		<a href="${pageContext.request.contextPath}/showProductByPage" style="color:#b4d76d">全部商品目录</a>		
</div>

在这个模块里,主要是调用了ShowProductByPageServlet,内容逻辑如下:

// 1.定义当前页码,默认为1
		int currentPage = 1;
		String _currentPage = request.getParameter("currentPage");
		if (_currentPage != null) {
			currentPage = Integer.parseInt(_currentPage);
		}
		// 2.定义每页显示条数,默认为4
		int currentCount = 4;
		String _currentCount = request.getParameter("currentCount");
		if (_currentCount != null) {
			currentCount = Integer.parseInt(_currentCount);
		}
		// 3.获取查找的分类
		String category = "全部商品";
		String _category = request.getParameter("category");
		if (_category != null) {
			category = _category;
		}
		// 4.调用service,完成获取当前页分页Bean数据.
		ProductService service = new ProductService();
		PageBean bean = service.findProductByPage(currentPage, currentCount,
				category);
		// 将数据存储到request范围,跳转到product_list.jsp页面展示
		request.setAttribute("bean", bean);
		request.getRequestDispatcher("/client/product_list.jsp").forward(request, response);
		return;

主要指定三个参数categorycurrentPagecurrentCount来控制ProductService的查询结果并封装到PageBean中,然后在回到product_list.jsp页面读取出来。

搜索查询图书
MenuSearchServlet处理类在点击提交搜索框时调用,该类主要是判断搜索框是否为默认值,空的话直接跳转至显示全部分类图书和上一个分类显示模块全部分类重叠。若不为空,就会直接调用ProductService查询结果封装到PageBean中,product_list.jsp再调用,其实实质上这两个搜索和分类用的是同一套底层调用类ProductDao。一个是按分类查找,一个是按名字查找,返回结果都放在PageBean
MenuSearchServlet中:

// 1.定义当前页码,默认为1
		int currentPage = 1;
		String _currentPage = req.getParameter("currentPage");
		if (_currentPage != null) {
			currentPage = Integer.parseInt(_currentPage);
		}
		// 2.定义每页显示条数,默认为4
		int currentCount = 4;	
		//获取前台页面搜索框输入的值
		String searchfield = req.getParameter("textfield");
		//如果搜索框中没有输入值,则表单传递的为默认值,此时默认查询全部商品目录
		if("请输入书名".equals(searchfield)){ 
			req.getRequestDispatcher("/showProductByPage").forward(req, resp);
			return;
		}
		//调用service层的方法,通过书名模糊查询,查找相应的图书
		ProductService service = new ProductService();
		PageBean bean = service.findBookByName(currentPage,currentCount,searchfield);
		// 将数据存储到request范围,跳转到product_search_list.jsp页面展示
		req.setAttribute("bean", bean);
		req.getRequestDispatcher("/client/product_search_list.jsp").forward(req, resp);

轮播图
轮播图的实现需要CSS以及JS的双层支持,在<head>标签内需要引入轮播图的实现js以及css代码。在<body>标签内引用并添加展示图片,前端知识也挺多的暂时放着,怕扎进去出不来了。

<head>
	<title>传智书城</title>
	<%-- 导入css --%>
	<link rel="stylesheet" href="${pageContext.request.contextPath}/client/css/main.css" type="text/css" />
	<!-- 导入首页轮播图css和js脚本 -->
	<link type="text/css" href="${pageContext.request.contextPath }/client/css/autoplay.css" rel="stylesheet" />
	<script type="text/javascript" src="${pageContext.request.contextPath }/client/js/autoplay.js"></script>
</head>
<!-- 图书商场首页轮播图  start -->
	<div id="box_autoplay">
    	<div class="list">
        	<ul>
            	<li><img src="${pageContext.request.contextPath }/client/ad/index_ad1.jpg" width="900" height="335" /></li>
            	<li><img src="${pageContext.request.contextPath }/client/ad/index_ad2.jpg" width="900" height="335" /></li>
            	<li><img src="${pageContext.request.contextPath }/client/ad/index_ad3.jpg" width="900" height="335" /></li>
            	<li><img src="${pageContext.request.contextPath }/client/ad/index_ad4.jpg" width="900" height="335" /></li>
            	<li><img src="${pageContext.request.contextPath }/client/ad/index_ad5.jpg" width="900" height="335" /></li>
        	</ul>
    	</div>
	</div>

公告展示

<body>
	<jsp:forward page="ShowIndexServlet"></jsp:forward>
</body>

WebContent根目录下的index.jsp文件中,只是调用一个ShowIndexServlet其他什么都没做,他是怎么初始化公告内容和订单内容的呢?

//查询最近一条公告,传递到index.jsp页面进行展示
		NoticeService nService = new NoticeService();
		Notice notice = nService.getRecentNotice();
		req.setAttribute("n", notice);
//请求转发
		req.getRequestDispatcher("/client/index.jsp").forward(req, resp);

可以看到,ShowIndexServlet里面getRecentNotice()获得一个最近公告的方法,返回的Notice被命名为n放进了请求中,所以在WebContent/client/index.jsp中可以直接通过EL表达式获得该对象。

<td width="485" height="100%">${n.details }</td>

本周热卖推荐
首页界面关于这部分一直是空白,不知出了什么bug。

//查询本周热销的两条商品,传递到index.jsp页面进行展示
		ProductService pService = new ProductService();
		List<Object[]> pList =  pService.getWeekHotProduct();
		for(Object[] os:pList){
			for(Object o:os){
				System.out.println(o);
			}
			System.out.println("---------------------");
		}
		req.setAttribute("pList", pList);
		
		//请求转发
		req.getRequestDispatcher("/client/index.jsp").forward(req, resp);

ShowIndexServlet里面,关于初始化热卖商品是这样描述,我们到ProductServicegetWeekHotProduct()里面看看,ProductService里面只是调用了ProductDao的一个getWeekHotProduct()方法,我们再进去看看:

//前台,获取本周热销商品
	public List<Object[]> getWeekHotProduct() throws SQLException {
		String sql = "SELECT products.id,products.name, "+
                             " products.imgurl,SUM(orderitem.buynum) totalsalnum "+
                     " FROM orderitem,orders,products "+
                     " WHERE orderitem.order_id = orders.id "+
                             " AND products.id = orderitem.product_id "+
                             " AND orders.paystate=1 "+
                             " AND orders.ordertime > DATE_SUB(NOW(), INTERVAL 7 DAY) "+
                     " GROUP BY products.id,products.name,products.imgurl "+
                     " ORDER BY totalsalnum DESC "+
                     " LIMIT 0,2 ";
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		return runner.query(sql, new ArrayListHandler());
	}

考验SQL功底的时候了,这条语句的意思是说:orderitem,orders,products三表关联查询,在订单子项从属的订单id和订单的id同一、商品id和订单子项的商品id同一、订单的支付状态为1、订单提交的时间为7天之内的条件下,以商品id、商品name、商品imgurl分组显示查询结果,以销量降序排列,只显示前3条。
可能是因为数据库内未存在已支付状态的订单,符合不了条件才没有结果。

limit是mysql的语法:
select * from table limit m,n
其中m是指记录开始的index,从0开始,表示第一条记录
n是指从第m+1条开始,取n条。
select * from tablename limit 2,4
即取出第3条至第6条,4条记录

DATE_SUB(d,INTERVAL expr type)函数返回起始日期d减去一个时间段后的日期。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章