Implementing a Three-Level Cascading Region Selector
Database Configuraton
Begin by executing the china.sql script against your MySQL instance. This initializes a regions table that stores hierarchical geographical data using id, name, and parent_id columns.
Client-Side Interface
The user interface consists of three interconnected selection boxes. jQuery manages asynchronous HTTP requests to dynamically populate child nodes based on the selected parent identifier.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Regional Selector</title>
<script src="js/jquery.min.js"></script>
<script>
$(document).ready(function() {
loadHierarchy(0, '#region-province');
});
function loadHierarchy(parentKey, targetSelector) {
$.ajax({
method: 'GET',
url: 'api/regions',
data: { parentKey: parentKey },
dataType: 'json',
success: function(dataCollection) {
$(targetSelector).empty().append('<option>-- Select --</option>');
$.each(dataCollection, function(index, item) {
$(targetSelector).append(
'<option value="' + item.regionId + '">' + item.regionName + '</option>'
);
});
// Clear dependent dropdowns when parent changes
if (targetSelector === '#region-city') {
$('#region-district').empty().append('<option>-- Select --</option>');
}
}
});
}
</script>
</head>
<body>
<label>Origin:</label>
<select id="region-province" onchange="loadHierarchy(this.value, '#region-city')">
<option>-- Select --</option>
</select>
<select id="region-city" onchange="loadHierarchy(this.value, '#region-district')">
<option>-- Select --</option>
</select>
<select id="region-district">
<option>-- Select --</option>
</select>
</body>
</html>
Server Architecture
Backend operations follow a three-tier model. Incoming requests are intercepted by a Servlet, routed to a Service component for processing, and finally queried via a DAO layer.
Request Handler
package com.example.web;
import com.example.service.RegionService;
import com.example.service.impl.RegionServiceImpl;
import com.example.model.Region;
import com.google.gson.Gson;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/api/regions")
public class RegionController extends HttpServlet {
private final RegionService regionService = new RegionServiceImpl();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
int parentId = 0;
try {
String param = request.getParameter("parentKey");
parentId = Integer.parseInt(param != null ? param : "0");
} catch (NumberFormatException e) {
parentId = 0;
}
List<Region> results = regionService.retrieveByParent(parentId);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(new Gson().toJson(results));
}
}
Service Implementation
package com.example.service.impl;
import com.example.dao.RegionDAO;
import com.example.dao.impl.RegionDAOImpl;
import com.example.model.Region;
import com.example.service.RegionService;
import java.util.List;
public class RegionServiceImpl implements RegionService {
private final RegionDAO regionDAO = new RegionDAOImpl();
@Override
public List<Region> retrieveByParent(int parentId) {
return regionDAO.findByParentIdentifier(parentId);
}
}
Data Access Component
package com.example.dao.impl;
import com.example.dao.BaseDAO;
import com.example.dao.RegionDAO;
import com.example.model.Region;
import java.util.List;
public class RegionDAOImpl extends BaseDAO implements RegionDAO {
@Override
public List<Region> findByParentIdentifier(int parentId) {
String query = "SELECT id AS regionId, name AS regionName, parent_id FROM regions WHERE parent_id = ?";
return executeQuery(Region.class, query, parentId);
}
}