因为要报账,赶着做出来一个用来展示的网站,用来申请软件著作权然后拿到发票赶紧报销去。所以用了几个小时的时间弄出来一个丑不拉几的网站,还好之前web作业做过一部分。现在的话是这样弄得:
整体架构如下用了IDEA开发,基于Java EE,tomcat和MySQL(大雾:算是用了dao模式?
其中用户的注册登录等都是直接按照别人的仿写的,具体可参考http://www.cnblogs.com/tzhz/archive/2013/05/18/3085432.html,尤其是里面的一个选取功能非常有用我会在后面详细说明一下。
统一说一下里面的两个大坑,第一是mac上我用navicat导入mdb格式的数据库到MySQL的时候有问题,所以我用那台win本当数据库了,用的是这么一条命令,grant all privileges on recipe.* to ‘root’@’192.168.31.203’identified by’root’。在win本上root用户输入上述命令就可给予权限,允许192.168.31.203以用户名root密码root访问recipe数据库,并给与全部权限。
第二个是tomcat会找不到你引入的外部jar包,要把用到的jar包拷一份到tomcat/lib目录下
直接上重点,推荐引擎的设计还是跟(二)里面的一样,只用了原料列,这部分后面再完善,这次只讲别的部分。
UserVo类里设计一个私有属性private static ArrayList like=new ArrayList();//存放用户喜欢的菜谱的id,然后在rec_sys.jsp里面是这样写的(我在jsp里面写Java了,好孩子不要学哦
<%@ page import="com.sun.dao.DisDAO" %>
<%@ page import="com.sun.vo.RecipeVo" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: sunyang
Date: 2016/12/8
Time: 下午1:42
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>推荐系统</title>
</head>
<body>
<% String id =(String) (request.getAttribute("id"));%>
<% DisDAO dd=new DisDAO();
ArrayList<RecipeVo> list=dd.display(70);
%>
<html>
<head>
<style type = "text/css">
td{
width:60px;
}
</style>
<script type="text/javascript">
function chickAll(){
// 全选方法
var chickobj = document.getElementsByName("num");
for(var i = 0 ; i<chickobj.length ; i++){
chickobj[i].checked = "checked";
}
}
function Nochick(){
// 反选方法
var chickobj = document.getElementsByName("num");
for(var i = 0 ; i<chickobj.length ; i++){
chickobj[i].checked = !chickobj[i].checked ;
}
}
</script>
</head>
<body>
<div id = "main">
<form name="form1" action ="/countSim" method = "post">
<table width="1000" border ="1" align = "center" style="border-collapse:collapse;">
<tr align="center">
<td colspan="8">
食谱大全
</td>
</tr>
<tr align="center">
<td></td>
<td>菜谱ID</td>
<td>菜谱名称</td>
<td width="400">做法</td>
<td>特性</td>
<td>提示</td>
<td>调料</td>
<td>原料</td>
</tr>
<%for(int i = 0 ; i<list.size();i++) {
RecipeVo re = list.get(i);%>
<tr align="center" >
<td><input type = "checkbox" value ='<%=re.getId() %>' name="num"/></td>
<td><%=re.getId() %></td>
<td><%=re.getName() %></td>
<td width="400"><%=re.getZuofa() %></td>
<td><%=re.getTexing() %></td>
<td><%=re.getTishi() %></td>
<td><%=re.getTiaoliao() %></td>
<td><%=re.getYuanliao() %></td>
</tr>
<%
}
%>
</table>
<table align = "center" >
<tr>
<td><input type="button" value="上一页" name="pre" id="pre" onclick="pre"></td>
<td><input type="text" name="页数" id="pageNum"></td>
<td><input type="button" value="跳转" name="skip" id="skip" onclick="skip"></td>
<td><input type="button" value="下一页" name="next" id="next" onclick="next"></td>
</tr>
</table>
<table align="center">
<tr>
<td></td>
<td><input type="button" value ="全选" name="checkall" id = "checkall" onclick="chickAll()"/></td>
<td><input type ="button" value ="反选" name="nocheck" id= "nocheck" onclick="Nochick()"/></td>
<td><input type ="submit" value ="提交" /></td>
</tr>
</table>
<input type="hidden" name="userid" value="<%=id%>">
</form>
</div>
</body>
</html>
</body>
</html>
你会发现table里的第一列我们这个单选框给的value就是菜谱的id,我们这个form表单传过去的就是这个东西,存入到上面我说的那个用户类的属性中去。
对应的servlet里面的countSim代码如下:
package com.sun.servlet;
import com.sun.dao.DisDAO;
import com.sun.dao.SimDao;
import com.sun.rec_engin.similarity;
import com.sun.vo.RecipeVo;
import com.sun.vo.UserListVector;
import com.sun.vo.UserVo;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.*;
/**
* Created by sunyang on 2016/12/8.
* 这个类得到用户选择的菜谱之后,计算相似度给出推荐
*/
public class countSim extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime=System.currentTimeMillis(); //获取开始时间
UserListVector ul=new UserListVector();
DisDAO disdao=new DisDAO();
SimDao simdao=new SimDao();
similarity sim=new similarity();
ArrayList<UserVo> ulist=ul.getList();
String likeId[] = request.getParameterValues("num");//表单传来的已选择的菜谱的ID
ArrayList<Integer> likeList=new ArrayList<Integer>();//转换成动态数据int型
for (int i = 0; i < likeId.length; i++) {
likeList.add(Integer.parseInt(likeId[i]));
}
int userid=Integer.parseInt(request.getParameter("userid"));//表单传来的选择菜谱的用户的id
UserVo user=null;
for (int i = 0; i < ulist.size(); i++) {//找到id为这个的用户,并为他添加喜欢的菜谱id
user=ulist.get(i);
if(user.getUserId()==userid){
user.setLike(likeList);
}
}
ArrayList<String> str1=new ArrayList<String>();//这个作为用户的向量空间.
str1=simdao.getUserVector(userid);//得到这个用户的向量空间
Map<Integer,Double> simList = new HashMap<Integer,Double>();//存放计算的相似值
for (int i = 0; i < 1000; i++) {//在这里修改总共对比的条数
double res=sim.getSimilarDegree(str1,simdao.getRecipeVector(i));
if(!Double.isNaN(res)) {
simList.put((Integer) disdao.idlist.get(i), res);
}
System.out.println(res);
}
/*
对map进行排序取前十
*/
List<Map.Entry<Integer,Double>> infoIds = new ArrayList<Map.Entry<Integer,Double>>(simList.entrySet());
//对value进行排序
Collections.sort(infoIds, new Comparator<Map.Entry<Integer,Double>>() {
@Override
public int compare(Map.Entry<Integer, Double> o1, Map.Entry<Integer, Double> o2) {
return (o2.getValue()).toString().compareTo(o1.getValue().toString());
}
});
// 对HashMap中的 value 进行排序后 显示排序结果
long endTime=System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
request.setAttribute("list", infoIds);
request.getRequestDispatcher("/Rec_list.jsp").forward(request, response);
}
}
初了这些就没什么好记录的了,当整个推荐系统完成的时候我传一份代码工程吧。
目前的效果就是当你选择了你喜爱的菜谱然后提交之后计算完相似度会给你生成推荐列表。
至于推荐效果,只能后面慢慢优化了。