1.按照Jsp/html-servlet-service-dao框架进行开发。
2.中文乱码-编码过滤器
重写doFilter方法:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
response.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
}
3. 查看商家所有菜品
3.1.jstl标签和el表达式
Jsp页面不可避免需要写java代码,<%java代码%><%=表达式%>
简单易懂的话,用el表达式+jstl标签来写
先导入两个jar包:standard.jar和jstl.jar
jsp页面声明:<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
El表达式:<%=food.getFoodName() %> 等价于 ${food.foodName}
${name }---查找范围是从page,request,session,application,从小到大获取数据
最常用的循环标签:
<c:forEach items="${requestScope.pv.datas}" var="food">
<tr><td>${food.id}</td><td>${food.foodName }</td>
<td>${food.foodPrice}</td>
<td> <a class="buy" >订购</a><input type="hidden" value="${food.id}">
<a href="/mt/addContent?foodName=${food.foodName }">查看评论</a>
<a href="/mt/addContentTo?foodName=${food.foodName }">添加评论</a>
</td></tr>
</c:forEach>
3.2 菜品显示在jsp页面上
1.request.setAttribute(“food”,food)将数据带到页面
2.request.getAttribute(“food”)在页面显示
3.用List把food封装起来,显示的时候一起显示简单
4.订购菜品,将菜品放入购物车,商品加入购物车,并提示加入成功,但不跳转页面(ajax效果)
<td><a class="buy">订购</a><input type="hidden" value="${food.id}">
Jsp:在页面加载完毕后,给订购设置点击事件,一点击订购,通过food.id获取id的值,然后ajax将值作为参数送到servlet,以ajax方式传递到servlet
$(function(){
//给用户名文本框注册事件
$(".buy").click(function(){
//获取文本框的值
var id=$(this).next().val();
$.ajax({
url:"/mt/addtocart",
type:"get",
dataType:"text",
data:{"id":id},
success:function(data){
if(data=='0'){
alert("该商品已添加购物车");
}
else{
alert("该商品可以添加购物车");
}
}
});
});
})
Servlet:将菜品放入购物车,返回food,如果该菜品是第一次加入购物车,则需要先创建购物车,然后再加入,如果不是第一次加入,则直接加入
//判断当前是否有购物车
String b="1";
HttpSession session = request.getSession();
if(session.getAttribute("cart")==null){
//第一个菜品
List<Food> cart = new ArrayList<Food>();
cart.add(foods);
session.setAttribute("cart", cart);
}else{
List<Food> cart =(List<Food>) session.getAttribute("cart");
for (Food f: cart) {
if(f.getId()==foods.getId()){
f.setSalenum(f.getSalenum()+1);
b="0";
}
}
if(b=="1")
cart.add( foods);
}
5.订购完毕之后,查看购物车
Jsp是动态页面,在浏览器无法直接打开,需要借助servlet跳转
1. request.getPequestDisPatcher(“/jsp页面”).forward(request,response);
2. Response.sendRedirect(“jsp页面”);
3.
<tr><td>菜品名称</td><td>价格</td><td>操作</td></tr>
<%
List<Food> foods= ( List<Food> )session.getAttribute("cart");
for(Food food:foods){
%>
<tr><td><%=food.getFoodName() %></td><td><%=food.getFoodPrice() %></td>
<td>
<input class="add" type="button" value="+" class="btn">
<input value="1" class="numtxt" name="saleNum">
<input class="reduce" type="button" value="-" class="btn"></td></tr>
<%} %>
<% %>可以用el表达式替换
可在购物车页面直接对数量进行加减
$(".add").click(function(){
var curval=$(this).next().val();
$(this).next().val(parseInt(curval)+1);
calc()//计算总价
})
$(".reduce").click(function(){
var curval=$(this).prev().val();
$(this).prev().val(parseInt(curval)-1);
calc()
})
$(".numtxt").change(function(){
calc()
})
每当数量加减,相对应的总价也应该变化
function calc(){
var total=0;
//循环计算总价
trs=$("tr:gt(0)")//过滤第一个tr
trs.each(function(){
//当前tr
var price= $(this).children("td").eq(1).html()
var num=$(this).children("td").eq(2).children("input").eq(1).val()
total+=parseFloat(price)*parseInt(num);
//显示总价
$("#totalPrice").val(total)
})
6. 给菜品评论
评论的时候时间是一直都在变化的,获得最新的时间
//设置当前时间
Date dte = new Date();
Timestamp timestamp = new Timestamp(dte.getTime());
在评论页面上有一个下拉框,里面有我们数据库里面所有的菜品,选择其中一道菜对其评论,传到数据库,可以评论好几条,查看某一菜品评论时会显示对这个菜品的所有评论
<select class="form-control" id="foodname" name="foodname">
<%
FoodService fs = new FoodService();
List<Food> foods = fs.find();
for(Food food:foods){
%>
<option value="<%=food.getFoodName() %>"><%=food.getFoodName() %></option>
<%} %>
</select>
El表达式替换:
<select class="form-control" id="foodname" name="foodname">
<c:forEach items="${foods}" var="foods">
<option value="${foods.foodName}">${foods.foodName}</option>
</c:forEach>
</select>
菜品评价时用富文本编辑器
1)首先我们项目中引入一个ckeditor,拷贝到webcontent目录下
2)页面引入<script type="text/javascript" src="ckeditor/ckeditor.js"></script>
3)在textarea标签上定义ckeditor样式 ,class="ckeditor"
<textarea rows="10" cols="30" id="content" name="content" class="ckeditor form-control"></textarea>
7. 注册功能,注册功能判断用户是否存在,密码与确认密码是否一致的效果
这个效果也是ajax实现
<form action="/mt/register" method="post"><!-- /表示tomacat的根路径。 -->
用户名:<input type="text" name="username" id="username"/><span id="info"></span><br>
密码:<input type="password" name="password" id="password"/><br>
确认密码:<input type="password" name="password" id="passwordd"/><span id="info1"></span><br>
<input type="submit" value="注册"/>
</form>
1. 先判断数据库是否已经存在该用户名,有的话,离开文本框时会显示该用户名已经注册
$(function(){
//给用户名文本框注册事件
$("#username").blur(function(){
//获取文本框的值
var username=$(this).val();
//alert(username)
//将值作为参数送到servlet,以ajax方式传递到servlet
$.ajax({
url:"/mt/isExistsUser",
type:"get",
dataType:"text",
data:{"username":username},
success:function(data){
if(data=='0'){
$("#info").html("用户名已被注册");
}else{
$("#info").html("用户名可用");
}
}
})
})
AjaxServlet:
PrintWriter out = response.getWriter();
//获取用户名
String username = request.getParameter("username");
//判断用户名是否存在
boolean b=rs.isExistsUser(username);
if(b){
out.print("0");
}else{
out.print("1");
}
out.close();
}
两次输入密码是否一致
//判断第二次输入的密码与第一次是否一致
$("#passwordd").blur(function(){
//获取密码文本框的值
var password=$("#password").val();
//获取确认密码文本框的值
var passwordd=$("#passwordd").val();
//若两次输入的密码不同,提示用户重新输入
if(!(password==passwordd)){
$("#passwordd").val("");//将确认密码输入框中的内容清空
$("#info1").html("两次密码不一致,请重新输入");
//alert("11111")
}else{
$("#info1").html("两次密码一致");
}
})
8. 查看某一个菜品的评论
想要的效果是所有的评论都显示出来,然后按时间递增排序
select * from food_content where foodname=? order by time DESC
9. 下订单
需要两张表:e_order,e_order_item
10. 百度地图集成
页面引入:
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3"></script>
<script type="text/javascript" src="http://developer.baidu.com/map/jsdemo/demo/convertor.js"></script>
在html页面上:页面加载完毕后
$(function(){
//在mapdiv中加载地图
var map=new BMap.Map("map");//参数div的id
var point=new BMap.Point(121.453449,37.492814);
map.centerAndZoom(point,18);//zoom有1-20的级别
//标注甲骨文餐厅的位置point
var marker=new BMap.Marker(point);
map.addOverlay(marker);//给地图加上覆盖物
marker.setLabel(new BMap.Label("<a href='http://localhost:8080/mt/findFoods'>欢迎进入学校餐厅!!</a>",{"offset":new BMap.Size(20,-10)}));
})
11. 送餐人员活动轨迹
思路:
1. 从当天的订单表中找出所有的送餐地址,构成一个数组
2. 将这些地址转为经纬度点坐标,形成一个point数组
3. 将这些点在地图上marker一下
4. 让他们产生动画跳动效果
5. 交通图层覆盖
6. 连线(从当前商家位置到每一个送餐地址的连线),用一个动态效果,注意顺序
var pointArr=[];//点数组
var map;
$(function(){
//在mapdiv中加载地图
map=new BMap.Map("map");//参数div的id
var point=new BMap.Point(121.453449,37.492814);//创建一个点
map.centerAndZoom(point,15);//zoom有1-20级别
//标注甲骨文餐厅的位置point
var marker=new BMap.Marker(point);
map.addOverlay(marker);//在地图上加上覆盖物
map.enableScrollWheelZoom()//鼠标滚轮缩放地图大小
//获取后台传过来的一个送餐地址的字符串
var addStr='${address}';
var arr=addStr.split(",");//地址数组
//将地址解析为point
for(var i=0;i<arr.length;i++){
search(arr[i]);
}
//地图上绘制点pointArr
window.setTimeout(function(){
//百度解析完地址后,开始绘制
for(var i=0;i<pointArr.length;i++){
var marker=new BMap.Marker(pointArr[i]);
map.addOverlay(marker);//在地图上加上覆盖
marker.setAnimation(BMAP_ANIMATION_BOUNCE);
}
},3000);
//连线
var count=0;
var inter=window.setInterval(function(){
//连接当前点到送餐地址点
var polyline = new BMap.Polyline([
point,
pointArr[count]
], {strokeColor:"blue", strokeWeight:3, strokeOpacity:0.5});
count++;
map.addOverlay(polyline);
if(count==pointArr.length){
//当count等于所有点的总和时候,清除定时器
window.clearInterval(inter)
}
},1000);
})
//解析地址函数
function search(keyword){
var localSearch = new BMap.LocalSearch(map);
localSearch.enableAutoViewport(); //允许自动调节窗体大小
localSearch.setSearchCompleteCallback(function (searchResult) {
var poi = searchResult.getPoi(0);
console.log(poi.point)
pointArr.push(poi.point);
});
localSearch.search(keyword);
}
活动轨迹主要是根据送餐地址来决定的
每次订餐时不同的是时间,根据时间来查询送餐地址
Select * from e_order where DATE_FORMAT(order_time,'%Y-%m-%d')=DATE_FORMAT(SYSDATE(),'%Y-%m-%d')
12. 分页功能
创建一个实体类pageVO
private int page;//当前第几页
private int pageSize=5;//默认一页存几条
private List<Food> datas=new ArrayList<>();//数据
private int totalPages;//总共多少页
在servlet中,将数据显示到页面时因为pageVO里存了food集合,所以
Request.setAttribute(“pv”,pv);
int page=1;
//获取查询第几页参数
String pageStr = request.getParameter("page");
//判断page为null就是第一页
if(pageStr==null){
page=1;
}else{
page=Integer.parseInt(pageStr);
}
Service:
/**
* 根据分页查询数据
* @param pv
* @return
*/
public PageVO findFoodByPage(PageVO pv) {
//
List<Food> foods=this.dao.find();
int totalCount=foods.size();//总共有多少条
int totalPages=(totalCount%pv.getPageSize()==0)?totalCount/pv.getPageSize():(totalCount/pv.getPageSize()+1);
pv.setTotalPages(totalPages);
return this.dao.findFoodByPage(pv);
}
Dao:
//求出当前查的从第几条开始
int page = pv.getPage();
int start=(page-1)*pv.getPageSize();
pstmt = con.prepareStatement("select * from food_menu limit "+start+","+pv.getPageSize());
rs = pstmt.executeQuery();
while(rs.next()){
//将rs数据放入list
Food food=new Food();
food.setId(rs.getInt("id"));
food.setFoodName(rs.getString("foodname"));
food.setFoodPrice(rs.getDouble("price"));
foods.add(food);
13. 表单重复提交
//限制用户的第二次点击
$(this).attr("disabled","disabled");
$(this).disabled();