ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot+Vue前后端分离公交查询系统开发实践

SpringBoot+Vue前后端分离公交查询系统开发实践 1. 项目概述作为一名参与过多个企业级交通系统开发的全栈工程师我深知一个高效的公交查询系统对城市出行体验的重要性。这次分享的公交线路查询系统采用了当前主流的前后端分离架构后端基于SpringBootMyBatisMySQL技术栈前端使用Vue.jsElementUI实现。这种架构选择不仅提升了开发效率更重要的是为系统带来了更好的可维护性和扩展性。在实际开发过程中我发现传统耦合架构的公交查询系统存在几个痛点首先是前后端开发进度相互制约其次是接口变动带来的连锁修改成本高最后是性能优化空间有限。而采用前后端分离后前端可以专注于用户体验和交互逻辑后端则更关注数据服务和业务处理两者通过定义良好的API契约进行协作大大提升了开发效率。2. 系统架构设计2.1 技术选型考量后端选择SpringBoot框架主要基于以下几个考虑自动配置特性大幅减少了传统Spring项目的XML配置内嵌Tomcat服务器简化了部署流程丰富的Starter依赖可以快速集成MyBatis、Redis等组件Actuator模块提供了完善的系统监控能力前端选择Vue.jsElementUI组合是因为Vue的响应式数据绑定特别适合频繁更新的公交数据展示组件化开发模式便于复用线路查询、站点展示等UI组件ElementUI提供了丰富的现成组件加速了界面开发Vue CLI工具链完善支持热重载等开发体验优化2.2 系统分层架构系统采用典型的三层架构表现层Vue前端应用负责用户交互和数据可视化业务逻辑层SpringBoot后端服务处理核心业务逻辑数据访问层MyBatisMySQL负责数据持久化各层之间通过明确定义的接口进行通信这种松耦合设计使得各层可以独立演进。例如当需要更换数据库时只需调整MyBatis的映射配置不会影响其他层次。3. 数据库设计与实现3.1 核心数据表结构公交线路基础表(route_info)的设计特别注意了以下几点使用自增主键route_id而非线路名称作为主键因为线路名称可能有重复添加了route_type字段区分常规线路和夜班线路这对后续的查询筛选很重要记录了运营公司信息为可能的公司维度的统计分析预留了空间CREATE TABLE route_info ( route_id int(11) NOT NULL AUTO_INCREMENT, route_name varchar(50) NOT NULL, operator varchar(50) DEFAULT NULL, route_type varchar(20) DEFAULT 常规, start_station varchar(50) NOT NULL, end_station varchar(50) NOT NULL, PRIMARY KEY (route_id), KEY idx_route_name (route_name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3.2 站点信息表设计要点站点信息表(stop_info)的设计有几个关键考虑使用DECIMAL(10,6)存储经纬度精度足够满足城市公交定位需求建立了route_id外键关联确保站点必须属于某条有效线路添加了复合索引(route_id, stop_name)优化线路站点查询性能CREATE TABLE stop_info ( stop_id int(11) NOT NULL AUTO_INCREMENT, stop_name varchar(50) NOT NULL, longitude decimal(10,6) NOT NULL, latitude decimal(10,6) NOT NULL, route_id int(11) NOT NULL, PRIMARY KEY (stop_id), KEY idx_route_stop (route_id,stop_name), CONSTRAINT fk_route FOREIGN KEY (route_id) REFERENCES route_info (route_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;4. 后端核心功能实现4.1 SpringBoot应用配置在application.yml中进行了以下关键配置server: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/bus_system?useSSLfalseserverTimezoneUTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true特别注意设置了server.servlet.context-path使所有API都有/api前缀配置了mybatis.configuration.map-underscore-to-camel-case实现数据库字段到Java属性的自动驼峰转换使用MySQL 8.0需要指定serverTimezone参数4.2 线路查询接口实现线路查询接口需要考虑多种查询场景按线路名称模糊查询按起点/终点站查询按线路类型筛选分页查询支持对应的Controller实现RestController RequestMapping(/routes) public class RouteController { Autowired private RouteService routeService; GetMapping public ResultListRouteVO queryRoutes( RequestParam(required false) String keyword, RequestParam(required false) String routeType, RequestParam(defaultValue 1) int page, RequestParam(defaultValue 10) int size) { RouteQueryDTO queryDTO new RouteQueryDTO(); queryDTO.setKeyword(keyword); queryDTO.setRouteType(routeType); queryDTO.setPage(page); queryDTO.setSize(size); ListRouteVO routes routeService.queryRoutes(queryDTO); return Result.success(routes); } }Service层实现时特别注意了对空参数的兼容处理避免因为某个条件为空而导致查询结果不符合预期。5. 前端Vue实现细节5.1 前端项目结构采用Vue CLI创建的标准项目结构并做了以下调整src/ ├── api/ # 接口请求封装 ├── assets/ # 静态资源 ├── components/ # 公共组件 │ ├── RouteCard.vue # 线路卡片组件 │ ├── StopList.vue # 站点列表组件 │ └── ... ├── router/ # 路由配置 ├── store/ # Vuex状态管理 ├── utils/ # 工具函数 └── views/ # 页面组件 ├── Home.vue # 首页 ├── Query.vue # 查询页 └── ...5.2 线路查询页面实现查询页面主要包含查询条件表单查询结果列表分页控件关键代码片段template div classquery-container el-form :modelqueryForm submit.native.preventhandleQuery el-form-item label线路名称 el-input v-modelqueryForm.keyword placeholder输入线路名称/el-input /el-form-item el-form-item label线路类型 el-select v-modelqueryForm.routeType clearable el-option label常规线路 value常规/el-option el-option label夜班线路 value夜班/el-option /el-select /el-form-item el-button typeprimary native-typesubmit查询/el-button /el-form div classresult-list route-card v-forroute in routes :keyroute.routeId :routeroute click.nativeshowRouteDetail(route.routeId) /route-card /div el-pagination current-changehandlePageChange :current-pagepagination.current :page-sizepagination.size :totalpagination.total /el-pagination /div /template6. 系统部署方案6.1 后端部署推荐使用Docker部署SpringBoot应用Dockerfile配置如下FROM openjdk:8-jdk-alpine VOLUME /tmp ARG JAR_FILEtarget/*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT [java,-jar,/app.jar]构建和运行命令# 构建镜像 docker build -t bus-system-backend . # 运行容器 docker run -d -p 8080:8080 --name bus-backend bus-system-backend6.2 前端部署前端项目使用Nginx部署nginx.conf关键配置server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; } }使用Docker部署前端FROM nginx:alpine COPY dist/ /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf7. 开发中的经验总结7.1 接口设计规范在前后端分离架构中良好的接口规范至关重要。我们采用了以下规范统一响应格式{ code: 200, message: success, data: {...} }使用HTTP状态码正确反映操作结果接口版本控制所有API路径添加/v1前缀详细的Swagger文档7.2 性能优化实践针对公交查询系统的特点我们实施了以下优化措施高频查询结果缓存使用Redis缓存热门线路的查询结果数据库查询优化为常用查询条件添加复合索引避免SELECT *只查询必要字段前端数据懒加载长列表使用虚拟滚动技术接口响应压缩启用Gzip压缩减少传输数据量7.3 常见问题排查在实际开发中遇到过几个典型问题跨域问题现象前端请求接口时报CORS错误解决方案后端添加CrossOrigin注解或配置全局CORS过滤器时区问题现象数据库中的时间与Java应用中的时间不一致解决方案统一使用UTC时区在JDBC连接字符串中添加serverTimezoneUTCVue路由刷新404现象生产环境刷新非首页路由时报404解决方案Nginx配置中添加try_files $uri $uri/ /index.html8. 系统扩展方向基于当前系统还可以进一步扩展以下功能实时公交到站预测接入公交GPS数据计算车辆实时位置出行规划基于Dijkstra算法实现最优换乘方案推荐用户收藏功能允许用户收藏常用线路移动端适配开发响应式布局或单独的手机APP数据分析对查询数据进行统计分析发现出行热点在实现换乘推荐功能时我们采用了图论中的最短路径算法。将公交站点作为图的顶点同一线路相邻站点间的乘车时间作为边权值不同线路的可换乘站点间建立边并设置换乘时间权值。这样就将换乘问题转化为了图的最短路径问题。
返回列表