数据结构---公交线路提示系统(Java后台+excel表格+web前端)
系统大致流程:
index.jsp输入站名(点击“出示站点信息”,跳转list.jsp读取表格);
后台通过站名获得id;getIdbyname(String name)
将id反馈至dijkstra(int vs,int vf),求得最短路径以及路径上的顶点(读取文档获得图Graph);
dijkstra运行结果仍是数字,所以还要getNamebyid(int id);运用List<String>返回最短路径上的站点名称
最后反馈至succeed.jsp
源代码:
servlet层:
import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import entity.Bus; import service.busService; /** * Servlet implementation class busServlet */ @WebServlet("/busServlet") public class busServlet extends HttpServlet { private static final long serialVersionUID = 1L; busService bus=new busService(); protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub req.setCharacterEncoding("utf-8"); String method = req.getParameter("method"); if(method.equals("dijkstra")) { dijkstra(req,resp); }else if(method.equals("list")) { list(req,resp); }else if(method.equals("getIdbyname")) { getIdbyname(req,resp); } } private void getIdbyname(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /** * 通过name获得id * 用来判断输入站名在表格中是否有库存 */ req.setCharacterEncoding("utf-8"); String s = req.getParameter("start"); String f = req.getParameter("final"); int k1=bus.getIdbyname(s); int k2=bus.getIdbyname(f); if(k1!=-1&&k2!=-1) {//与运算,两边同时成立为真 req.setAttribute("message", "查询成功");//setAttribute方法用于将内容保存在对象中,传到jsp中 req.getRequestDispatcher("busServlet?method=dijkstra").forward(req,resp);//getRequestDispatcher方法用于进入下一个页面 }else if(k1==-1||k2==-1){//或运算,两边一个成立为真 req.setAttribute("message", "站名错误,请保证正确输入"); req.getRequestDispatcher("index.jsp").forward(req,resp); } } private void list(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException { req.setCharacterEncoding("utf-8"); List<Bus> buses = bus.readExcelList(); req.setAttribute("buses", buses); req.getRequestDispatcher("list.jsp").forward(req,resp); } private void dijkstra(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException { req.setCharacterEncoding("utf-8"); String s = req.getParameter("start"); String f = req.getParameter("final"); int vs=bus.getIdbyname(s); int vf=bus.getIdbyname(f); List<String> stations=bus.dijkstra(vs, vf); req.setAttribute("stations",stations);//setAttribute方法用于将内容保存在对象中,传到jsp中 req.getRequestDispatcher("succeed.jsp").forward(req,resp);//getRequestDispatcher方法用于进入下一个页面 } }
service层:
import java.io.IOException; import java.util.List; import busRoute.Dao; import entity.Bus; public class busService { Dao dao=new Dao(); public List<String> dijkstra(int vs,int vf) throws IOException { // TODO 自动生成的方法存根 return Dao.dijkstra(vs,vf); } public List<Bus> readExcelList() throws IOException { // TODO 自动生成的方法存根 return dao.readExcelList(); } public int getIdbyname(String str) throws IOException { int t=dao.getIdbyname(str); return t; } }
entity层:
public class Bus { private String name; private int id; public void setName(String name) { this.name=name; } public String getName() { return name; } public void setId(int id) { this.id=id; } public int getId() { return id; } public Bus() { } public Bus(int b,String a) { name=a; id=b; } }
dao层:
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import entity.Bus; public class Dao{ public List<Bus> readExcelList() throws IOException { /** * 读取表格 * 输出至前端 */ List<Bus> list = new ArrayList<>(); String filePath="D://dns.xls"; InputStream input = new FileInputStream(filePath); Workbook wb = null; wb = new HSSFWorkbook(input); //得到一个工作表对象; Sheet sheet = wb.getSheetAt(0); int rsRows = sheet.getLastRowNum();// 获取sheet表中的总行数 // 遍历行 //每一行成一个bus对象 Bus bus=null; for (int i=0;i<=rsRows;i++) { Row row = sheet.getRow(i); int id=0; String name=null; //遍历行单元格,已知有两列;第一列int型id,第二列String型name Cell cell1 = row.getCell(0); Cell cell2 = row.getCell(1); //一定要检验是否为空 if(cell1==null||cell1.equals(null)||cell1.getCellType()==CellType.BLANK){ break; }else { //数值型 id=(int) cell1.getNumericCellValue(); } if(cell2==null||cell2.equals(null)||cell2.getCellType()==CellType.BLANK){ break; }else { //字符串型 name= cell2.getStringCellValue(); } bus=new Bus(id,name); list.add(bus); } wb.close();//关闭 return list; } public static List<String> readTxtFile(String filePath) { /** * 读取文档 * @param filePath * @return */ List<String> list = new ArrayList<String>(); try { String encoding = "UTF-8"; File file = new File(filePath); if (file.isFile() && file.exists()) { InputStreamReader read = new InputStreamReader( new FileInputStream(file), encoding); BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null; while ((lineTxt = bufferedReader.readLine()) != null) { if (!lineTxt.startsWith("#")) list.add(lineTxt); } read.close(); } else { System.out.println("找不到文件"); } } catch (Exception e) { System.out.println("出错了"); e.printStackTrace(); } return list; } public static String[][] createArray(String filePath){ /** * 读取文档生成二维数组 * @param filePath * @return */ List<String> list = readTxtFile(filePath); System.out.println("读取成功"); String[][] array = new String[list.size()][]; for(int i=0;i<list.size();i++){ array[i] = new String[list.size()]; String linetxt=list.get(i); String[] myArray = linetxt.replaceAll("\\s+", "@").split("@"); for(int j=0;j<myArray.length;j++){ array[i][j]=myArray[j]; } } return array; } public static int[][] str2int(String[][] str){//String型转为int型 int a,b; a = str.length; b = str[0].length; int result[][] = new int[a][b]; for(int i = 0 ; i < a ; ++ i) for(int j = 0 ; j < b ; ++ j) { result[i][j] = Integer.parseInt(str[i][j]); } return result; } public static List<String> dijkstra(int vs,int vf) throws IOException { /** * Dijkstra最短路径。 * 即图中"节点vs"到其它各个节点的最短路径。 * @param vs 起始节点 * @param Graph 图 * 将最短路径上的顶点,距离存入泛型集合list,返回 * 注意整型用Integer不能用int */ List<String> list= new ArrayList<String>();//将最短路径上的顶点,距离存入list,返回 String[][] str= createArray("D:\\text.txt"); //将读取的String型二维数组转化为int型 int[][]Graph =str2int(str); int NUM = Graph[0].length; int[] prenode = new int[NUM];//前驱节点数组 int[] path = new int[NUM];//最短距离数组 boolean[] flag = new boolean[NUM];// 该节点是否已经找到最短路径 int vnear = 0;//距离vs最近的节点 //初始化 for (int i = 0; i <path.length; i++) { prenode[i] = i; path[i] = Graph[vs][i];//顶点i的最短路径为顶点vs到i的权 flag[i] = false; } flag[vs] = true;//vs自身初始化 //遍历 Graph.length-1次,找出每个顶点的最短路径 for (int v = 1; v < Graph.length; v++) { // 每次循环求得当前距离vs最近的顶点vnear和最短距离min int min = 100000;//100000表示无穷 for (int j = 0; j < Graph.length; j++) { if (!flag[j] && path[j] < min) { min = path[j]; vnear = j; } } //标记顶点vnear为已经获取到最短路径 flag[vnear] = true; // 根据vnear更新vs到其他所有节点的前驱节点和最短路径 for (int k = 0; k < Graph.length; k++) { if (!flag[k] && (min + Graph[vnear][k]) < path[k]) { prenode[k] = vnear; path[k] = min + Graph[vnear][k]; } } } list.add(path[vf]+"");//+""作用是将int转化为String型 //依次保存前驱 for(int i=0;i<4&&prenode[vf]!=vs;i++) {//i范围根据自己表的情况 list.add(getNamebyid(vf)); vf=prenode[vf]; } list.add(getNamebyid(vs)); return list; } public int getIdbyname(String name)throws IOException { //通过name获得id int x=-1; String filePath="D://dns.xls"; InputStream input = new FileInputStream(filePath); Workbook wb = null; wb = new HSSFWorkbook(input); //得到一个工作表对象; Sheet sheet = wb.getSheetAt(0); int rsRows = sheet.getLastRowNum();// 获取sheet表中的总行数 // 遍历行 for (int i=0;i<=rsRows;i++) { Row row = sheet.getRow(i); int id=0; String flag=null; //遍历行单元格,已知有两列;第一列int型id,第二列String型name Cell cell1 = row.getCell(0); Cell cell2 = row.getCell(1); if(cell1==null||cell1.equals(null)||cell1.getCellType()==CellType.BLANK){ break; }else { //数值型 id=(int) cell1.getNumericCellValue(); }; if(cell2==null||cell2.equals(null)||cell2.getCellType()==CellType.BLANK){ break; }else { //字符串型 flag= cell2.getStringCellValue(); }; String a=new String(flag); String b=new String(name); if(a.equals(b)){ x=id; }; } wb.close();//记得关闭 return x; } public static String getNamebyid(int id) throws IOException { //通过id获得name String str=null; String filePath="D://dns.xls"; InputStream input = new FileInputStream(filePath); Workbook wb = null; wb = new HSSFWorkbook(input); //得到一个工作表对象; Sheet sheet = wb.getSheetAt(0); int rsRows = sheet.getLastRowNum();// 获取sheet表中的总行数 // 遍历行 for (int i=0;i<=rsRows;i++) { int flag=0; String name=null; Row row = sheet.getRow(i); //遍历行单元格 Cell cell1= row.getCell(0); Cell cell2 = row.getCell(1); if(cell1==null||cell1.equals(null)||cell1.getCellType()==CellType.BLANK){ break; }else { //数值型 flag=(int) cell1.getNumericCellValue(); } if(cell2==null||cell2.equals(null)||cell2.getCellType()==CellType.BLANK){ break; }else { //字符串型 name= cell2.getStringCellValue(); } if(flag==id){ str=name; } } wb.close();//记得关闭 return str; } }
index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>首页</title> <style > .a{ font-size: 26px; margin-top: 20px; } </style> </head> <body> <% Object message = request.getAttribute("message"); if(message!=null && !"".equals(message)){ %> <script type="text/javascript"> alert("<%=request.getAttribute("message")%>"); </script> <%} %> <div align="center"> <h1 style="color: red;">公交线路</h1> <a href="busServlet?method=list">出示站点信息</a> <form action="busServlet?method=getIdbyname" method="post" onsubmit="return check()"> <div > 起点<input type="text" id="start" name="start"/> </div> <div > 终点<input type="text" id="final" name="final" /> </div> <div > <button type="submit" >确定</button> </div> </form> </div> <script type="text/javascript"> function check() { var a = document.getElementById("start"); var b= document.getElementById("final"); //非空 if(a.value == '') { alert('起点为空'); a.focus(); return false; } if(b.value == '') { alert('终点为空'); b.focus(); return false; } } </script> </body> </html>
list.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>列出表格内容</title> <style> .a{ margin-top: 20px; } .b{ font-size: 20px; width: 160px; color: white; background-color: greenyellow; } .tb, td { border: 1px solid black; font-size: 22px; } </style> </head> <body> <% Object message = request.getAttribute("message"); if(message!=null && !"".equals(message)){ %> <script type="text/javascript"> alert("<%=request.getAttribute("message")%>"); </script> <%} %> <div align="center"> <h1 style="color: red;">站点列表</h1> <a href="index.jsp">返回主页</a> <table class="tb"> <tr> <td>站点id</td> <td>站点名称</td> </tr> <c:forEach items="${buses}" var="item"> <tr> <td>${item.id}</td> <td>${item.name}</td> </tr> </c:forEach> </table> </div> </body> </html>
succeed.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>最短路径</title> <style> .a{ margin-top: 20px; } .b{ font-size: 20px; width: 160px; color: white; background-color: greenyellow; } .tb, td { border: 1px solid black; font-size: 22px; } </style> </head> <body> <% Object message = request.getAttribute("message"); if(message!=null && !"".equals(message)){ %> <script type="text/javascript"> alert("<%=request.getAttribute("message")%>"); </script> <%} %> <div align="center"> <h1 style="color: red;">最短路径</h1> <a href="index.jsp">返回主页</a> <table class="tb"> <tr> <td>站点倒序</td> </tr> <c:forEach items="${stations}" var="item"> <tr> <td>${item}</td> </tr> </c:forEach> </table> </div> </body> </html>
项目布局:(与连接数据库操作基本相同,只不过本人做的时候没有另建类似连接数据库的excelutil包,而是直接在dao层连接;小伙伴们可以尝试建立excelutil包,会方便很多)
运行截图:
主页:index.jsp
点击“出示站点信息”:list.jsp
输入起点,终点:
检查输入站点名称:
输出最短路径:succeed.jsp