Java 三级联动:省市县接口实现

在现代Web开发中,三级联动选择器越来越受到欢迎。它使用户在选择地址时能更加方便、直观。特别是在填写地址信息时,用户需要先选择省份,再选择市,最后选择县。这种层级选择常常被称为三级联动选择。本文将探讨如何在Java中实现一个简单的省市县三级联动接口,并提供相应的代码示例。

1. 项目结构

在开始之前,我们需要一个基本的项目结构。可以使用Maven来管理我们的依赖和构建项目。以下是我们的项目结构:

address-selector
│
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           ├── AddressController.java
│   │   │           ├── AddressService.java
│   │   │           └── AddressRepository.java
│   │   └── resources
│   │       └── application.properties
│   └── test
│       └── java
│           └── com
│               └── example
│                   └── AddressServiceTest.java

2. 数据模型

我们首先定义一个数据模型,用于存储省、市和县的信息。在这里,我们采用简单的POJO类。

// Province.java
package com.example;

public class Province {
    private String id;
    private String name;

    // Getter and Setter
}

// City.java
package com.example;

public class City {
    private String id;
    private String name;
    private String provinceId;

    // Getter and Setter
}

// County.java
package com.example;

public class County {
    private String id;
    private String name;
    private String cityId;

    // Getter and Setter
}

3. 数据库模拟

在我们的示例中,假设已经有省市县的数据,我们可以模拟一个简单的数据库。为了简单起见,这里使用一个内存列表来模拟数据存储。

// AddressRepository.java
package com.example;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class AddressRepository {
    private List<Province> provinces = new ArrayList<>();
    private List<City> cities = new ArrayList<>();
    private List<County> counties = new ArrayList<>();

    public AddressRepository() {
        // 初始化省、市、县数据
        provinces.add(new Province("1", "省A"));
        provinces.add(new Province("2", "省B"));

        cities.add(new City("1", "市A1", "1"));
        cities.add(new City("2", "市A2", "1"));
        cities.add(new City("3", "市B1", "2"));

        counties.add(new County("1", "县A1", "1"));
        counties.add(new County("2", "县A2", "1"));
        counties.add(new County("3", "县B1", "3"));
    }

    public List<Province> getProvinces() {
        return provinces;
    }

    public List<City> getCitiesByProvinceId(String provinceId) {
        return cities.stream()
            .filter(city -> city.getProvinceId().equals(provinceId))
            .collect(Collectors.toList());
    }

    public List<County> getCountiesByCityId(String cityId) {
        return counties.stream()
            .filter(county -> county.getCityId().equals(cityId))
            .collect(Collectors.toList());
    }
}

4. 服务层

服务层用于处理与 AddressRepository 的交互,向控制层提供服务。

// AddressService.java
package com.example;

import java.util.List;

public class AddressService {
    private AddressRepository addressRepository;

    public AddressService() {
        this.addressRepository = new AddressRepository();
    }

    public List<Province> getAllProvinces() {
        return addressRepository.getProvinces();
    }

    public List<City> getCities(String provinceId) {
        return addressRepository.getCitiesByProvinceId(provinceId);
    }

    public List<County> getCounties(String cityId) {
        return addressRepository.getCountiesByCityId(cityId);
    }
}

5. 控制层

控制层负责接收用户请求,并返回相应的结果。

// AddressController.java
package com.example;

import java.util.List;
import spark.Request;
import spark.Response;
import spark.Spark;

public class AddressController {
    private AddressService addressService;

    public AddressController() {
        this.addressService = new AddressService();
        setupRoutes();
    }

    private void setupRoutes() {
        Spark.get("/provinces", this::getProvinces);
        Spark.get("/cities/:provinceId", this::getCities);
        Spark.get("/counties/:cityId", this::getCounties);
    }

    private List<Province> getProvinces(Request request, Response response) {
        return addressService.getAllProvinces();
    }

    private List<City> getCities(Request request, Response response) {
        String provinceId = request.params(":provinceId");
        return addressService.getCities(provinceId);
    }

    private List<County> getCounties(Request request, Response response) {
        String cityId = request.params(":cityId");
        return addressService.getCounties(cityId);
    }
}

6. 启动应用

为了启动我们的应用,我们只需在 main 方法中调用 AddressController 的构造函数:

// Main.java
package com.example;

public class Main {
    public static void main(String[] args) {
        new AddressController();
    }
}

7. API 交互示例

我们使用工具(如Postman)来模拟API请求。以下是省市县的请求示例:

请求类型 请求路径 请求参数 返回结果
GET /provinces [{"id": "1", "name": "省A"}, {"id": "2", "name": "省B"}]
GET /cities/1 provinceId=1 [{"id": "1", "name": "市A1"}, {"id": "2", "name": "市A2"}]
GET /counties/1 cityId=1 [{"id": "1", "name": "县A1"}, {"id": "2", "name": "县A2"}]

8. 序列图展示

下面用Mermaid语法展示我们的API交互序列图:

sequenceDiagram
    participant User
    participant Controller
    participant Service
    participant Repository
    
    User->>Controller: GET /provinces
    Controller->>Service: getAllProvinces()
    Service->>Repository: getProvinces()
    Repository-->>Service: provinces list
    Service-->>Controller: provinces list
    Controller-->>User: provinces list

    User->>Controller: GET /cities/1
    Controller->>Service: getCities("1")
    Service->>Repository: getCitiesByProvinceId("1")
    Repository-->>Service: cities list
    Service-->>Controller: cities list
    Controller-->>User: cities list

结尾

在本篇文章中,我们实现了一个简单的Java应用来创建省市县的三级联动接口。通过定义数据模型、模拟数据库、构建服务层和控制层,我们可以实现对地址信息的管理和查询。用户通过API请求可以方便地获取到所需的地址信息。

这种三级联动的实现方式不仅能够提高用户体验,还可以灵活地应用于各种表单和系统中。随着需求的增加,这个基础程序可以不断扩展,以适应更复杂的业务需求。希望本文对你理解Java中省市县三级联动接口的实现有所帮助!