商城项目的导航条的分类管理其实上也是属于一个表;
所以我们需要先在商城这个所在的数据库中创建一张分类表categroy
CREATE TABLE categroy(
cid VARCHAR(50),
cname VARCHAR(200)
);
INSERT INTO categroy VALUES('1','手机数码'),('172934bd636d485c98fd2d3d9cccd409','运动户外'),
('2','电脑办公'),('3','家具家居'),('4','鞋靴箱包'),('5','图书音像'),
('59f56ba6ccb84cb591c66298766b83b5','aaaa'),('6','母婴孕婴'),
('afdba41a139b4320a74904485bdb7719','汽车用品');
因为我们在商城中的每一个页面都应该看到这个菜单栏和导航条,所以我们可以直接把这一块的html代码独立独立出来成为一个head.jsp,然后用jsp的include指令(静态包含)或者是用jsp的include标签(动态包含),把这个页面包含进需要这个页面的jsp中即可;因为这其中有用到<c:if>标签,所以还得在head.jsp页面导入c标签,这样别的页面在包含进这个页面的时候就不需要再添加c标签了;
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!--
时间:2015-12-30
描述:菜单栏
-->
<div class="col-md-3" style="padding-top:20px">
<ol class="list-inline">
<c:if test="${empty user }">
<li><a href="${pageContext.request.contextPath }/user?method=loginUI">登录</a></li>
<li><a href="${pageContext.request.contextPath }/user?method=registUI">注册</a></li>
<li><a href="cart.htm">购物车</a></li>
</c:if>
<c:if test="${not empty user }">
${user.username }:您好
<li><a href="${pageContext.request.contextPath }/user?method=logout">退出</a></li>
<li><a href="${pageContext.request.contextPath }/user?method=registUI">我的订单</a></li>
<li><a href="cart.htm">购物车</a></li>
</c:if>
</ol>
</div>
<!--
时间:2015-12-30
描述:导航条
-->
<a class="navbar-brand" href="#">首页</a>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav" id="menuId"> </ul>
而这个导航条是在我们一打开商城页面就会看到的,所以就是页面加载完后就会自动加载的,所以我们就要用到ajax技术;在页面加载后自动发送ajax请求,从缓存中得到导航条所需要的信息.记得导入jquery的jar包和在jsp页面引用jquery文件
<script type="text/javascript" src="${pageContext.request.contextPath}jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(function(){
$.get("${pageContext.request.contextPath}/categroy?method=categ",function(data){
//获取id为menuId的ul标签
var $ul=$("#menuId");
//遍历数组,并向ul标签内部追加子标签
$(data).each(function(){
$ul.append($("<li><a href='${pageContext.request.contextPath}/product?
method=findByPage&cid="+this.cid+"&currPage=1'>"+this.cname+"</a></li>"));
});
},"json");//因为是json格式,所以这里可以用this.cname,相当于map集合的键值对
});
</script>
然后在index.jsp / login.jsp / register.jsp等需要看到这个导航条和菜单栏的所有页面上的,在页面应该放导航条和菜单栏的地方加上包含语句;
静态包含:
<%@include file="/jsp/head.jsp" %>
动态包含:
<jsp:include page="/jsp/head.jsp"> </jsp:include>
以上任选一;
-------------------------------------------------------------------------------------------------------------
静态包含和动态包含的区别是:
1) 原理不同, 静态是先把页面合并,再翻译成java源文件; 动态是先各自翻译成java源文件,运行的时候再合并
2) 语法不同, 静态 <%@include file="/jsp/head.jsp" %>
动态<jsp:include page="/jsp/head.jsp"> </jsp:include>
(都不需要导入标签库的)
3) 参数传递不同, 静态不可以向被包含页面传参;
动态可以通过<jsp:param value="tom" name="username" />传参
---------------------------------------------------------------------------------------------------------------
然后就是做后台处理的路径为/categroy的CoteproyServlet中的方法categ();
public class CategroyServlet extends BaseServlet {
public String categ(HttpServletRequest request, HttpServletResponse response) throws Exception {
//设置编码
response.setContentType("text/html;charset=utf-8");
//调用CategroyService处理业务逻辑
CategroyService cs=new CategroyServlceImpl();
//即从数据库的Cotegroy表中查出分类数据,返回list集合
List<Categroy> clist=cs.findAll();
//把list集合转为json格式. 用这个工具类的时候需先导入json的多个jar包,
JSONArray json = JSONArray.fromObject(clist);
//固定步骤,只要是用到json的,最后都必须写回去. 而不是用setAttribute();
response.getWriter().println(json);
return null;//即告诉BaseServlet 我不用转发也不用重定向
}
}
中间省略Categroy实体类 / CategroyService / CategroyDao的代码
直接上CategroyServiceImpl的代码,因为在这个类中比平时多用到一个缓存技术 ehcache
问题:为什么要用缓存呢?
缓存是为了来存一些不常变化的数据,比如导航栏的分类. 用的时候可以直接在缓存中获取,如果
缓存中没有的话,再从数据库里获取数据,然后放入缓存中.这样就可以减少和数据库的频繁交互;
但是对于一些经常变化的则直接从数据库获取即可,无须用缓存多此一举;
ehcache的使用步骤
1) 先导入5个jar包(1个核心包+4个日志包)
2)然后编写配置文件(放在src下)
3)使用api
ehcache的配置文件如下:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="C:/ehcache"/>
<cache
name="categoryCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<!--
默认缓存配置,
以下属性是必须的:
name :cache的标识符,在一个CacheManager中必须唯一。
maxElementsInMemory : 在内存中缓存的element的最大数目。
maxElementsOnDisk : 在磁盘上缓存的element的最大数目。
eternal : 设定缓存的elements是否有有效期。如果为true,timeouts属性被忽略。
overflowToDisk : 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上。
以下属性是可选的:
timeToIdleSeconds : 缓存element在过期前的空闲时间。
timeToLiveSeconds : 缓存element的有效生命期。
diskPersistent : 在VM重启的时候是否持久化磁盘缓存,默认是false。
diskExpiryThreadIntervalSeconds : 磁盘缓存的清理线程运行间隔,默认是120秒.
memoryStoreEvictionPolicy : 当内存缓存达到最大,有新的element加入的时候,
移除缓存中element的策略。默认是LRU,可选的有LFU和FIFO
-->
</ehcache>
这是CategroyServiceImpl的代码: 注意看清楚ehcache的api导入的包
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
public class CategroyServlceImpl implements CategroyService {
@Override
public List<Categroy> findAll() throws Exception {
// 1.创建缓存管理器
CacheManager cm = CacheManager
.create(CategroyServlceImpl.class.getClassLoader().getResourceAsStream("ehcache.xml"));
//当前类名.class.getClassLoader().getResourceAsStream("文件名");
// 2.获取指定的缓存(这个是在ehcache.xml中的name)
Cache cache = cm.getCache("categoryCache");
// 3.通过缓存获取数据 将cache看成一个map即可
Element element = cache.get("clist"); //这个 c l i s t 必须与下面的一样
List<Categroy> list = null;
// 4.判断数据
if (element == null) {
// 从数据库中获取
CategroyDao cd = new CategroyDaoImpl();
list = cd.findAll();
// 将list放入缓存
cache.put(new Element("clist", list));//这个 c l i s t 必须与上面的一样
System.out.println("缓存中没有数据,已去数据库中获取");
} else {
// 直接返回
list = (List<Categroy>) element.getObjectValue();
System.out.println("缓存中有数据");
}
return list;
}
}
最后是CategroyDaoImpl查库语句
public class CategroyDaoImpl implements CategroyDao {
public List<Categroy> findAll() throws Exception {
QueryRunner qr=new QueryRunner(C3P0Utils.getDatasource());
String sql="select * from categroy";
return qr.query(sql, new BeanListHandler<>(Categroy.class));
}
}