首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java 实战打造城市公园信息管理系统 2025 最新技术实现指南

Java 实战打造城市公园信息管理系统 2025 最新技术实现指南

原创
作者头像
啦啦啦191
发布2025-08-16 13:15:59
发布2025-08-16 13:15:59
1540
举报
文章被收录于专栏:Java开发Java开发

Java实战:城市公园信息管理系统(2025最新技术实现)

随着智慧公园概念的普及,传统的公园管理方式已无法满足现代城市发展需求。本文将基于2025年最新技术栈,提供一套完整的城市公园信息管理系统实操指南,涵盖从环境搭建到核心功能实现的全过程。

一、技术栈升级与环境配置

1. 最新技术选型

考虑到系统性能、开发效率和未来扩展性,我们采用以下技术栈:

  • 后端框架:Spring Boot 3.2.0(支持虚拟线程,提升并发处理能力)
  • 数据访问:Spring Data JPA + Hibernate 6.4(简化数据操作)
  • 前端框架:Vue 3 + Vite 5(更快的构建速度和更好的TypeScript支持)
  • 数据库:MySQL 8.3(支持JSON数据类型,优化空间数据处理)
  • 安全框架:Spring Security 6.2 + JWT(增强的安全特性)
  • API文档:SpringDoc-OpenAPI 2.3(生成OpenAPI 3.0规范文档)
  • 部署工具:Docker + Docker Compose(简化部署流程)

2. 开发环境搭建

首先确保安装以下工具:

  • JDK 21(必须,支持虚拟线程)
  • Node.js 20.x + npm 10.x
  • Docker 25.x
  • IntelliJ IDEA 2024.2(或其他IDE)

项目初始化命令

代码语言:bash
复制
# 创建Spring Boot后端项目
spring init --dependencies=web,data-jpa,mysql,security,validation,prometheus,actuator \
  --language=java --java-version=21 --packaging=jar \
  --groupId=com.park --artifactId=park-management --name=ParkManagement \
  --description="City Park Information Management System" --version=1.0.0

# 创建Vue前端项目
npm create vite@latest park-frontend -- --template vue-ts
cd park-frontend
npm install axios vue-router pinia element-plus @element-plus/icons-vue

二、数据库设计与实现

采用MySQL 8.3的新特性,优化空间数据存储和查询性能。

1. 核心数据表设计

代码语言:sql
复制
-- 公园基本信息表(使用新的JSON类型存储额外属性)
CREATE TABLE parks (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    area DECIMAL(10,2) NOT NULL COMMENT '面积(公顷)',
    location POINT NOT NULL COMMENT '地理位置',
    opening_hours VARCHAR(255) NOT NULL,
    contact_phone VARCHAR(20),
    description TEXT,
    extra_attributes JSON, -- 存储动态扩展属性
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_location (location) USING GEO
);

-- 设施表
CREATE TABLE facilities (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    park_id BIGINT NOT NULL,
    name VARCHAR(100) NOT NULL,
    type VARCHAR(50) NOT NULL,
    status ENUM('normal', 'maintenance', 'closed') DEFAULT 'normal',
    location POINT,
    last_maintained_at TIMESTAMP,
    FOREIGN KEY (park_id) REFERENCES parks(id) ON DELETE CASCADE,
    INDEX idx_park_id (park_id)
);

使用MySQL的空间数据类型POINT存储地理位置,便于后续实现基于位置的查询功能。

2. JPA实体类实现

代码语言:java
复制
@Entity
@Table(name = "parks")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Park {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @NotBlank(message = "公园名称不能为空")
    private String name;
    
    @NotNull(message = "面积不能为空")
    private BigDecimal area;
    
    @NotNull(message = "位置信息不能为空")
    @Convert(converter = PointConverter.class) // 自定义转换器
    private Point location;
    
    private String openingHours;
    private String contactPhone;
    private String description;
    
    // 存储额外属性,使用HashMap映射JSON字段
    @Column(columnDefinition = "JSON")
    private Map<String, Object> extraAttributes;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    // 关联设施
    @OneToMany(mappedBy = "park", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Facility> facilities = new ArrayList<>();
}

自定义Point转换器处理空间数据类型:

三、核心功能实现

1. 公园信息管理API

使用Spring Boot 3.2的虚拟线程特性提升并发处理能力:

代码语言:java
复制
@RestController
@RequestMapping("/api/v1/parks")
@RequiredArgsConstructor
public class ParkController {
    
    private final ParkService parkService;
    
    // 使用虚拟线程提高并发处理能力
    @GetMapping
    public ResponseEntity<Page<ParkDTO>> getAllParks(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String name) {
        
        // Spring Boot 3.2+ 自动使用虚拟线程执行控制器方法
        Page<ParkDTO> parks = parkService.findParks(name, PageRequest.of(page, size));
        return ResponseEntity.ok(parks);
    }
    
    @GetMapping("/nearby")
    public ResponseEntity<List<ParkDTO>> getNearbyParks(
            @RequestParam double latitude,
            @RequestParam double longitude,
            @RequestParam(defaultValue = "2000") double radius) {
        
        List<ParkDTO> parks = parkService.findNearbyParks(latitude, longitude, radius);
        return ResponseEntity.ok(parks);
    }
    
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<ParkDTO> createPark(@Valid @RequestBody ParkCreateDTO parkDTO) {
        ParkDTO created = parkService.createPark(parkDTO);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }
    
    // 其他API方法...
}

服务层实现(使用Spring Data JPA的空间查询):

代码语言:java
复制
@Service
@RequiredArgsConstructor
@Transactional
public class ParkServiceImpl implements ParkService {
    
    private final ParkRepository parkRepository;
    private final ParkMapper parkMapper;
    
    @Override
    @Transactional(readOnly = true)
    public List<ParkDTO> findNearbyParks(double latitude, double longitude, double radius) {
        // 创建查询点
        Point userLocation = GEOMETRY_FACTORY.createPoint(new Coordinate(longitude, latitude));
        
        // 计算距离(米),使用MySQL的空间函数
        List<Park> parks = parkRepository.findByLocationWithin(
            userLocation, radius
        );
        
        return parks.stream()
                .map(parkMapper::toDto)
                .collect(Collectors.toList());
    }
    
    // 其他方法实现...
}

2. 前端实现(Vue 3 + TypeScript)

使用Composition API实现公园列表和地图展示:

代码语言:vue
复制
<template>
  <div class="park-container">
    <el-row :gutter="20">
      <el-col :span="8">
        <el-input 
          v-model="searchQuery" 
          placeholder="搜索公园名称" 
          clearable
          @clear="handleSearch"
          @input="handleSearchDebounced"
        >
          <template #append>
            <el-button @click="handleSearch" icon="Search" />
          </template>
        </el-input>
        
        <el-card class="park-list" v-if="parks.length > 0">
          <el-scrollbar height="calc(100vh - 200px)">
            <el-row :gutter="10" v-for="park in parks" :key="park.id" class="park-item">
              <el-col :span="24">
                <el-card @click="showParkDetails(park)">
                  <h3>{{ park.name }}</h3>
                  <p>面积: {{ park.area }} 公顷</p>
                  <p>开放时间: {{ park.openingHours }}</p>
                  <el-tag :type="getDistanceTagType(park.distance)">{{ formatDistance(park.distance) }}</el-tag>
                </el-card>
              </el-col>
            </el-row>
          </el-scrollbar>
        </el-card>
      </el-col>
      
      <el-col :span="16">
        <div class="map-container">
          <!-- 地图组件 -->
          <park-map 
            :parks="parks" 
            :center="mapCenter" 
            :user-location="userLocation"
            @park-clicked="showParkDetails"
          />
        </div>
      </el-col>
    </el-row>
  </div>
</template>

TypeScript逻辑部分:

代码语言:typescript
复制
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { useDebounceFn } from '@vueuse/core';
import ParkMap from '@/components/ParkMap.vue';
import { getParks, getNearbyParks } from '@/api/park';
import { ParkDTO } from '@/types/park';

// 状态定义
const searchQuery = ref('');
const parks = ref<ParkDTO[]>([]);
const loading = ref(false);
const userLocation = ref<{latitude: number, longitude: number} | null>(null);
const mapCenter = ref<{latitude: number, longitude: number}>({
  latitude: 39.9042,  // 默认北京坐标
  longitude: 116.4074
});

// 防抖处理搜索
const handleSearchDebounced = useDebounceFn(handleSearch, 500);

// 方法定义
async function handleSearch() {
  loading.value = true;
  try {
    if (searchQuery.value) {
      // 按名称搜索
      const response = await getParks({ name: searchQuery.value });
      parks.value = response.data.content;
    } else if (userLocation.value) {
      // 按当前位置搜索附近公园
      const response = await getNearbyParks({
        latitude: userLocation.value.latitude,
        longitude: userLocation.value.longitude,
        radius: 2000
      });
      parks.value = response.data;
    }
  } catch (error) {
    console.error('获取公园信息失败', error);
    ElMessage.error('获取公园信息失败,请稍后重试');
  } finally {
    loading.value = false;
  }
}

// 获取用户位置
function getUserLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        userLocation.value = {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude
        };
        mapCenter.value = { ...userLocation.value };
        handleSearch();
      },
      (error) => {
        console.warn('无法获取位置信息', error);
        ElMessage.warning('无法获取位置信息,将显示默认区域公园');
        handleSearch();
      }
    );
  } else {
    ElMessage.warning('您的浏览器不支持地理位置服务');
    handleSearch();
  }
}

// 格式化距离显示
function formatDistance(meters: number): string {
  if (meters < 1000) {
    return `${Math.round(meters)}米`;
  } else {
    return `${(meters / 1000).toFixed(1)}公里`;
  }
}

// 根据距离返回标签类型
function getDistanceTagType(meters: number): string {
  if (meters < 500) return 'success';
  if (meters < 1000) return 'warning';
  return 'info';
}

// 生命周期钩子
onMounted(() => {
  getUserLocation();
});
</script>

3. 安全配置(Spring Security 6.2)

代码语言:java
复制
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/v1/auth/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
                .requestMatchers(HttpMethod.GET, "/api/v1/parks/**").permitAll()
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .cors(cors -> cors.configurationSource(corsConfigurationSource()));
            
        return http.build();
    }
    
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:5173"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        configuration.setExposedHeaders(Arrays.asList("Authorization"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

四、容器化部署配置

使用Docker Compose实现一键部署:

后端Dockerfile:

代码语言:dockerfile
复制
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/park-management-1.0.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

前端Dockerfile:

代码语言:dockerfile
复制
# 构建阶段
FROM node:20-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 生产阶段
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

五、系统扩展与优化建议

  1. 性能优化
    • 使用Redis缓存热门公园信息和用户会话
    • 实现数据库读写分离,提高查询性能
    • 对图片等静态资源使用CDN加速
  2. 功能扩展
    • 集成天气API,显示公园实时天气
    • 添加预约管理模块,支持公园内设施预约
    • 实现环境监测数据采集与展示(空气质量、噪音等)
  3. 安全增强
    • 实现API请求限流,防止恶意攻击
    • 添加数据备份与恢复机制
    • 定期进行安全审计和漏洞扫描

通过本实操指南,你可以基于最新的Java技术栈构建一个功能完善、性能优异的城市公园信息管理系统。该系统不仅能满足基本的公园信息管理需求,还具备良好的扩展性,可根据实际需求进一步增强功能。


Java 实战,城市公园信息管理系统,2025 最新技术,技术实现指南,管理系统开发,Java 项目实战,公园管理系统,Java 技术应用,系统开发指南,企业级系统搭建,数字化管理方案,Java 实战案例,信息系统开发,2025 Java 框架,公园信息化建设

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java实战:城市公园信息管理系统(2025最新技术实现)
    • 一、技术栈升级与环境配置
      • 1. 最新技术选型
      • 2. 开发环境搭建
    • 二、数据库设计与实现
      • 1. 核心数据表设计
      • 2. JPA实体类实现
    • 三、核心功能实现
      • 1. 公园信息管理API
      • 2. 前端实现(Vue 3 + TypeScript)
      • 3. 安全配置(Spring Security 6.2)
    • 四、容器化部署配置
    • 五、系统扩展与优化建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档