数据库结构:
项目结构:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> /* 设置外层wrapper宽高、背景验证、水平居中、相对定位 */ .wrapper { position: relative; width: 550px; height: 250px; background-color: #669999; margin: 0 auto; } /* 设置内层div相对于父级绝对定位,默认隐藏 */ .wrapper div { display: none; position: absolute; top: 50px; } /* 设置label宽高、行内块、文本居中、行高、字体大小、字体颜色 */ label { width: 175px; height: 50px; display: inline-block; text-align: center; line-height: 50px; font-size: 14px; color: white; } /* 默认所有radio隐藏 */ input[type="radio"] { display: none; } /* 被选中的radio下的label下的div显示 */ input[type="radio"]:checked+label+div { display: block; } /* 被选中的radio下的label背景颜色改为红色 */ input[type="radio"]:checked+label { background-color: #666699; } </style> </head> <body> <div class="wrapper"> <form action="Servlet" post="method"> <input type="radio" name="gender" id="bro1" /> <label for="bro1">站点查询</label> <div> <h4>站点名称:<input type="text" name="station1"></h4> <button type="submit" name="kind" value="1">查询</button> </div> <input type="radio" name="gender" id="bro2" checked /> <label for="bro2">线路查询</label> <div> <h4>线路名称:<input type="text" name="line"></h4> <button type="submit" name="kind" value="2">查询</button> </div> <input type="radio" name="gender" id="bro3" /> <label for="bro3">换乘查询</label> <div> <h4>站点1:<input type="text" name="station1"></h4> <h4>站点2:<input type="text" name="station2"></h4> <button type="submit" name="kind" value="3">查询</button> </div> </form> </div> </body> </html>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>查询结果</title> </head> <script type="text/javascript"> String data=request.getAttribuete("get"); </script> <style type="text/css"> /* 设置外层wrapper宽高、背景验证、水平居中、相对定位 */ .wrapper { position: relative; width: 550px; height: 250px; background-color: #669999; margin: 0 auto; } /* 设置内层div相对于父级绝对定位,默认隐藏 */ .wrapper div { display: none; position: absolute; top: 50px; } /* 设置label宽高、行内块、文本居中、行高、字体大小、字体颜色 */ label { width: 175px; height: 50px; display: inline-block; text-align: center; line-height: 50px; font-size: 14px; color: white; } /* 默认所有radio隐藏 */ input[type="radio"] { display: none; } /* 被选中的radio下的label下的div显示 */ input[type="radio"]:checked+label+div { display: block; } /* 被选中的radio下的label背景颜色改为红色 */ input[type="radio"]:checked+label { background-color: #666699; } </style> <body> <div class="wrapper"> <input type="radio" name="gender" id="bro1" checked/> <label for="bro1">查询结果</label> <div> <h4><span>${get}</span><h4> </div> <input type="radio" name="gender" id="bro2" /> <label for="bro2">查询结果</label> <div> <span>${get}</span> </div> <input type="radio" name="gender" id="bro3" /> <label for="bro3">查询结果</label> <div> <span>${get}</span> </div> </div> </body> </html>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>查询结果</title> </head> <script type="text/javascript"> String data=request.getAttribuete("get"); </script> <style type="text/css"> /* 设置外层wrapper宽高、背景验证、水平居中、相对定位 */ .wrapper { position: relative; width: 550px; height: 250px; background-color: #669999; margin: 0 auto; } /* 设置内层div相对于父级绝对定位,默认隐藏 */ .wrapper div { display: none; position: absolute; top: 50px; } /* 设置label宽高、行内块、文本居中、行高、字体大小、字体颜色 */ label { width: 175px; height: 50px; display: inline-block; text-align: center; line-height: 50px; font-size: 14px; color: white; } /* 默认所有radio隐藏 */ input[type="radio"] { display: none; } /* 被选中的radio下的label下的div显示 */ input[type="radio"]:checked+label+div { display: block; } /* 被选中的radio下的label背景颜色改为红色 */ input[type="radio"]:checked+label { background-color: #666699; } </style> <body> <div class="wrapper"> <input type="radio" name="gender" id="bro1" checked/> <label for="bro1">查询结果</label> <div> <h4><span>${get}</span><h4> </div> <input type="radio" name="gender" id="bro2" /> <label for="bro2">查询结果</label> <div> <span>${get}</span> </div> <input type="radio" name="gender" id="bro3" /> <label for="bro3">查询结果</label> <div> <span>${get}</span> </div> </div> </body> </html>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>查询结果</title> </head> <script type="text/javascript"> String data=request.getAttribuete("get"); </script> <style type="text/css"> /* 设置外层wrapper宽高、背景验证、水平居中、相对定位 */ .wrapper { position: relative; width: 550px; height: 250px; background-color: #669999; margin: 0 auto; } /* 设置内层div相对于父级绝对定位,默认隐藏 */ .wrapper div { display: none; position: absolute; top: 50px; } /* 设置label宽高、行内块、文本居中、行高、字体大小、字体颜色 */ label { width: 175px; height: 50px; display: inline-block; text-align: center; line-height: 50px; font-size: 14px; color: white; } /* 默认所有radio隐藏 */ input[type="radio"] { display: none; } /* 被选中的radio下的label下的div显示 */ input[type="radio"]:checked+label+div { display: block; } /* 被选中的radio下的label背景颜色改为红色 */ input[type="radio"]:checked+label { background-color: #666699; } </style> <body> <div class="wrapper"> <input type="radio" name="gender" id="bro1" checked/> <label for="bro1">查询结果</label> <div> <h4><span>${get}</span><h4> </div> <input type="radio" name="gender" id="bro2" /> <label for="bro2">查询结果</label> <div> <span>${get}</span> </div> <input type="radio" name="gender" id="bro3" /> <label for="bro3">查询结果</label> <div> <span>${get}</span> </div> </div> </body> </html>
defeat.jsp仅用作测试没有实际作用,在此不贴出;

package Dao; import subway.line; import subway.station; import subway.Mymain; import java.io.*; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.*; import util.Util; public class dao { public String serch_1(String st) { String station=""; Connection conn=null; Statement state=null; PreparedStatement ps=null; ResultSet rs=null; String sql="select * from ways where stations like '%"+st+"%'"; try { try { conn=Util.getConnection(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } ps=conn.prepareStatement(sql); rs=ps.executeQuery(sql); while(rs.next()) { station=station+rs.getString(1)+" "; } }catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return station; } public String serch_2(String line) { String station=""; Connection conn=null; Statement state=null; PreparedStatement ps=null; ResultSet rs=null; String sql="select * from ways where id ='"+line+"'"; try { try { conn=Util.getConnection(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } ps=conn.prepareStatement(sql); rs=ps.executeQuery(sql); while(rs.next()) { station=station+rs.getString(2)+" "; } }catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return station; } public String serch_3(String station1, String station2) { // TODO Auto-generated method stub String path=""; Mymain.getSubway(); String Line=""; String start=station1; String end=station2; Mymain.BFS(start,end); path=Mymain.PrintPath(start,end); return path; } }

package servlet; import java.io.IOException; import java.io.UnsupportedEncodingException; 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 Dao.dao; import util.Util; /** * Servlet implementation class Servlet */ @WebServlet("/Servlet") public class Servlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public Servlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setCharacterEncoding("utf-8"); String kind=request.getParameter("kind"); if(kind.equals("1")) { serch1(request,response); //request.getRequestDispatcher("serch1.html").forward(request, response); } else if(kind.equals("2")) { serch2(request,response); request.getRequestDispatcher("serch2.jsp").forward(request, response); } else if(kind.equals("3")) { serch3(request,response); request.getRequestDispatcher("serch3.jsp").forward(request, response); } else { request.getRequestDispatcher("defeat.html").forward(request, response); } } private void serch1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setCharacterEncoding("utf-8"); String station=request.getParameter("station1"); dao serch=new dao(); String get=serch.serch_1(station); request.setAttribute("get", get); request.getRequestDispatcher("serch1.jsp").forward(request, response); } private void serch2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String line=request.getParameter("line"); dao serch=new dao(); String get=serch.serch_2(line); request.setAttribute("get", get); request.getRequestDispatcher("serch2.jsp").forward(request, response); } private void serch3(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String station1=request.getParameter("station1"); String station2=request.getParameter("station2"); dao serch=new dao(); String get=serch.serch_3(station1,station2); request.setAttribute("get", get); request.getRequestDispatcher("serch2.jsp").forward(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

package subway; import java.util.ArrayList; import java.util.List; public class line { private String LineName; //线名 private List<String> stations= new ArrayList<String>(); //该线路中所有站 public List<String> getStations() { return stations; } public void setStations(List<String> stations) { this.stations = stations; } public String getLineName() { return LineName; } public void setLineName(String lineName) { LineName = lineName; } public void stationAdd(String name){ stations.add(name); } }

package subway; import java.io.*; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.*; import util.Util; public class Mymain { public static HashMap<String,station> map = new HashMap<>();//方便查找站点信息 public static List<line> LineSet= new ArrayList<>();//方便查找路线 public static void getSubway() {//读入线路数据 try { // InputStreamReader reader = new InputStreamReader(new FileInputStream(filename)); // BufferedReader br = new BufferedReader(reader); // String read = ""; // read = br.readLine();//线路数量 // int LineNum = 0; // LineNum = Integer.parseInt(read); // // for (int i = 0; i <= 22; i++) { // line linex = new line();//当前存的line // read = br.readLine(); // if(read==null){ // return; // } // String[] stations = read.split(" ");//读入的line对应的所有station Connection conn=null; Statement state=null; PreparedStatement ps=null; ResultSet rs=null; String line=""; String sql="select * from sub"; try { conn=Util.getConnection(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } ps=conn.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ { line=""; for(int z=1;z<51;z++) { if(rs.getString(z).equals("end")) break; else line=line+rs.getString(z)+" "; } //System.out.println(line); } System.out.println(line); String [] stations=line.split(" "); line linex=new line(); linex.setLineName(stations[0]);//输入线路名 if (stations.length<=1){ System.out.print("本线路无可乘站"); return; } for (int j = 1; j < stations.length - 1; j++) { station station1 = new station();//当前line中的station station station2 = new station(); if (map.containsKey(stations[j])) {//如果map中已经有该站点则把这个站点拿出来处理 station1 = map.get(stations[j]); map.remove(stations[j]); } else { station1.setStationName(stations[j]); station1.setVisited(false); } if (map.containsKey(stations[j + 1])) {//map中已经有该站后面的站点拿出来处理 station2 = map.get(stations[j + 1]); map.remove(stations[j + 1]); } else { station2.setStationName(stations[j + 1]); station2.setVisited(false); } if (!station1.getLine().contains(linex.getLineName()))//如果当前站未加入line中,则在line中当前站名 station1.AddStationLine(linex.getLineName()); if (!station2.getLine().contains(linex.getLineName()))//如果当前站未加入line中,则在line中当前站名 station2.AddStationLine(linex.getLineName()); if (!station1.getLinkStations().contains(station2)) station1.AddLinkStation(station2); if (!station2.getLinkStations().contains(station1)) station2.AddLinkStation(station1); station1.setPreStation(station1.getStationName()); station2.setPreStation(station2.getStationName()); map.put(stations[j], station1);//把station1重新放回map map.put(stations[j + 1], station2);//把station2重新放回map if (!linex.getStations().contains(station1.getStationName())) { linex.stationAdd(station1.getStationName()); } if (!linex.getStations().contains(station2.getStationName())) { linex.stationAdd(station2.getStationName()); } } LineSet.add(linex);//把线路加入LineSet } Util.close(rs, ps, conn); // br.close(); }catch(Exception e){ e.printStackTrace(); } } public static void getStationOfLine(String name ){ //根据线路名字查找该线路所有站点 //String Rt=""; int flag = 0; int index = -1; for (line line1 :LineSet){ index++; if(line1.getLineName().equals(name)) { flag = 1; break; } } if (flag==0) System.out.println("该地铁线路不存在"); else { System.out.print(name + ": "); for (String str : LineSet.get(index).getStations()) { System.out.print(str + " "); } } } public static void BFS(String start,String end){ int flagx = 0; if (!map.containsKey(start)){//判断起点站是否存在 System.out.println("起点站不存在"); flagx = 1; } if (!map.containsKey(end)){ System.out.println("终点站不存在");//判断终点站是否存在 flagx = 1; } if (flagx==1) return; for (String temp :map.keySet()){ map.get(temp).setVisited(false); map.get(temp).setDistance(0); } station nowStation = new station(); Queue<String> queue = new LinkedList<>();//存放遍历过的站点 nowStation = map.get(start); queue.add(start); while(!queue.isEmpty()){ String nowStationName = queue.poll(); map.get(nowStationName).setVisited(true); if (nowStation.getStationName().equals(end)){ break; } for (station station1 :map.get(nowStationName).getLinkStations()){ if(!map.get(station1.getStationName()).isVisited()){//未访问过的临近站点 map.get(station1.getStationName()).setPreStation(nowStationName);//为preStation赋值 map.get(station1.getStationName()).setDistance(map.get(nowStationName).getDistance()+1);//临近站的距离为本站距离加1 queue.offer(station1.getStationName()); } } } } public static String PrintPath(String start,String end){ String Returnpath=""; if (!map.containsKey(start)){//判断起点站是否存在 return "起点不存在"; } if (!map.containsKey(end)){ return "终点不存在"; } if (start.equals(end)){ //System.out.print("起点站与终点站相同 本站为"+end); return "起点站与终点站相同 本站为"+end; } List<String> path = new ArrayList<>(); Stack<String> printline = new Stack<>(); int numStation = 1;//第几站 int cnt = 0;//换乘次数 String str = end; while(!str.equals(start)){ path.add(str); printline.push(str); str = map.get(str).getPreStation(); } path.add(str);//把start放入path printline.push(str); for (int i=1;i<path.size()-1;i++){ if (map.get(path.get(i)).getLine().size()==1){ continue; } String temp1=""; String temp2=""; for (String str1 : map.get(path.get(i)).getLine()){//本站与前一站的共同拥有的线路存在temp1中 int flag=0; for (String str2 :map.get(path.get(i-1)).getLine()){ if (str1.equals(str2)){ temp1 = temp1+str1; flag=1; break; } } if (flag==1) break; } for (String str1 : map.get(path.get(i)).getLine()){//后一站与本站的共同拥有的线路存在temp2中 int flag=0; for (String str2 :map.get(path.get(i+1)).getLine()){ if (str1.equals(str2)){ temp2 = temp2+str1; flag=1; break; } } if (flag==1) break; } if (!temp1.equals(temp2))//若temp1和temp2两线路不同则本站为转乘站 map.get(path.get(i)).setIfchange(true); }//判断path中的换乘站 System.out.println("共"+path.size()+"站"); Returnpath=Returnpath+"共"+path.size()+"站"+":"; while(!printline.empty()){ String printStation = printline.pop(); if(numStation==1){ for (String strnow : map.get(printStation).getLine()){ for (String nextStation : map.get(path.get(path.size()-numStation-1)).getLine()){ if (strnow.equals(nextStation)) { System.out.println("当前线为:"+strnow); Returnpath=Returnpath+"最短线路为: "+strnow; } } } } if (map.get(printStation).isIfchange()){ String nowline =""; for (String strnow : map.get(printStation).getLine()){ //path.get(path.size()-numStation)换乘站下一站 两站共有的线路就是换乘到的线路 for (String nextStation : map.get(path.get(path.size()-numStation-1)).getLine()){ if (strnow.equals(nextStation)) nowline= nowline + strnow; } } cnt++; System.out.println(""); System.out.println("转线->"+nowline); Returnpath=Returnpath+"转线->"+nowline; } System.out.print(printStation+" "); Returnpath=Returnpath+printStation+" "; numStation++; } return Returnpath; } }
Mymain方法(最短路径求法)的逻辑来自前辈zhangjunze1/Subway (github.com)的java版本

package subway; import java.util.ArrayList; import java.util.List; public class station { private String StationName; //站点名 private List<String> Line = new ArrayList<String>(); //所在线路(换乘站有多条) private List<station> LinkStations= new ArrayList<station>(); //与之相邻的站点 private boolean visited;//是否访问过该站点 private String preStation;//本站之前访问的站点 private int distance=0;//本站距离起点站的站数 private boolean ifchange;//是否换乘 默认为false 用于结果 public boolean isIfchange() { return ifchange; } public void setIfchange(boolean ifchange) { this.ifchange = ifchange; } public int getDistance() { return distance; } public void setDistance(int distance) { this.distance = distance; } public void AddStationLine(String name){ Line.add(name); } public void AddLinkStation(station sta){ LinkStations.add(sta); } public String getStationName() { return StationName; } public void setStationName(String stationName) { StationName = stationName; } public List<String> getLine() { return Line; } public void setLine(List<String> line) { Line = line; } public List<station> getLinkStations() { return LinkStations; } public void setLinkStations(List<station> linkStations) { LinkStations = linkStations; } public boolean isVisited() { return visited; } public void setVisited(boolean visited) { this.visited = visited; } public String getPreStation() { return preStation; } public void setPreStation(String preStation) { this.preStation = preStation; } }

package util; import java.sql.*; public class Util { public static Connection getConnection() throws ClassNotFoundException, SQLException { Connection connection = null;//连接数据库 Statement stmt = null;//Statement 对象用于将 SQL 语句发送到数据库中。 ResultSet rs = null; //1. 导入驱动jar包 //2.注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT", "root", "230030"); return connection; } public static void close(Connection connection) { try { if (connection != null) { connection.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(PreparedStatement preparedStatement) { try { if (preparedStatement != null) { preparedStatement.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(ResultSet resultSet) { try { if (resultSet != null) { resultSet.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(Statement st) { try { if (st != null) { st.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(Statement state, Connection connection) { try { if (connection != null) { connection.close(); } if (state != null) { state.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void close(ResultSet rs, Statement state, Connection conn) { try { if (conn != null) { conn.close(); } if (state != null) { state.close(); } if(rs != null) { rs.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
本周目标,把web版转化为app版
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本