系统大致流程:
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 方法用于进入下一个页面
- }
- }
- busServlet
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;
- }
- }
- busService
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;
- }
- }
- Bus
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];
- }
- }
- }
- // 依次保存前驱
- for(int i=0;i<9&&prenode[vf]!=vs;i++) {
- list.add(getNamebyid(vf));
- vf=prenode[vf];
- }
- list.add(getNamebyid(vs));
- list.add(path[vf]+"");//+"" 作用是将 int 转化为 String 型
- 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;
- }
- }
- Dao
- 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>
index.jsp
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=r equest.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>
list.jsp
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=r equest.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>
succeed.jsp
项目布局:(与连接数据库操作基本相同, 只不过本人做的时候没有另建类似连接数据库的 excelutil 包, 而是直接在 dao 层连接; 小伙伴们可以尝试建立 excelutil 包, 会方便很多)
运行截图:
主页: index.jsp
点击 "出示站点信息":list.jsp
输入起点, 终点:
检查输入站点名称:
输出最短路径: succeed.jsp
来源: http://www.bubuko.com/infodetail-3117028.html