使用 Spring Boot 从数据库实现动态下拉菜单
动态下拉菜单(或依赖下拉菜单)的概念对于编码来说是令人兴奋且具有挑战性的。动态下拉列表意味着一个下拉列表中的值取决于前一个下拉列表中选择的值。一个简单的示例是三个下拉框,显示区、taluk 和村庄的名称,其中 taluk 中的值取决于区中选择的值,村庄中的值取决于 taluk 下拉列表中选择的值。动态下拉可以使用以下技术来实现:
- 任何数据库都可用于加载要在下拉列表中填充的地区、塔鲁克和村庄的详细信息。在本例中,我们将使用
PostgreSQL
。 - 连接数据库的服务类可以使用Java和
Spring Boot
来实现。 HTML、CSS、JavaScript、jQuery
和AJAX
可用于实现下拉列表。
构建数据库
建议单独创建Spring Boot项目,并将网页单独创建在另一个项目中。
构建服务端项目:
以下教程中介绍了创建 Spring Boot 项目的过程:Spring Boot
– 用于显示响应代码和自定义错误代码的服务类示例。数据库部分由每个表的一个 CREATE 命令和每个表的一些 INSERT 命令组成。下面列出了表的创建命令和相应的插入命令:
CREATE TABLE district (id int SERIAL PRIMARY KEY,name varchar(50),distcode varchar(4));
insert into district (name,distcode) values('Chennai','1');
insert into district (name,distcode) values('Coimbatore','2');
CREATE TABLE taluk (id int SERIAL PRIMARY KEY,name varchar(50),distcode varchar(4),talukcode varchar(4));
insert into taluk (name,distcode,talukcode) values('Avadi','1','12');
insert into taluk (name,distcode,talukcode) values('Sulur','2','3');
CREATE TABLE village (id int SERIAL PRIMARY KEY,name varchar(50),distcode varchar(4),talukcode varchar(4),villagecode varchar(4));
insert into village (name,distcode,talukcode,villagecode) values('Pothur','1','12','15');
insert into village (name,distcode,talukcode,villagecode) values('Arasur','2','10','9');
各数据库的图片如下所示:
地区数据库
DBController.java
代码语言:javascript复制package com.springboot.springbootdemo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.websocket.server.PathParam;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin
public class DBController {
PreparedStatement ps;
Connection con;
String sql;
@GetMapping("/dist")
@CrossOrigin
public String saylistDistrict() throws SQLException
{
PreparedStatement ps;
ResultSet myRs;
JSONArray districtlist = new JSONArray();
try {
Class.forName("org.postgresql.Driver");
con = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/test?allowPublicKeyRetrieval=true",
"postgres", "password");
sql = "SELECT distcode, name FROM district";
ps = con.prepareStatement(sql);
myRs = ps.executeQuery();
while (myRs.next()) {
JSONObject jsonobj = new JSONObject();
jsonobj.put("districtcode",
myRs.getString("distcode")
.toString()
.trim());
jsonobj.put("districtname",
myRs.getString("name")
.toString()
.trim());
districtlist.add(jsonobj);
}
System.out.println("districtlist"
districtlist.size());
close(con, ps, myRs);
}
catch (Exception e) {
System.out.println("getservice Exception==>"
e);
}
return (districtlist.toString());
}
@RequestMapping(value = "/taluk",
method = RequestMethod.GET)
@ResponseBody
@CrossOrigin
public String
ListTaluk(@RequestParam String Discode)
throws ParseException
{
String districtcode = Discode;
JSONArray taluklist = new JSONArray();
try {
Class.forName("org.postgresql.Driver");
con = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/test?allowPublicKeyRetrieval=true",
"postgres", "password");
sql = " select * from taluk where distcode=?";
ps = con.prepareStatement(sql);
ps.setString(1, districtcode);
ResultSet res = ps.executeQuery();
while (res.next()) {
JSONObject jsontaluk = new JSONObject();
jsontaluk.put("districtcode",
res.getString("distcode")
.toString()
.trim());
jsontaluk.put("talukcode",
res.getString("talukcode")
.toString()
.trim());
jsontaluk.put("talukname",
res.getString("name")
.toString()
.trim());
taluklist.add(jsontaluk);
}
System.out.println("taluklist"
taluklist.size());
close(con, ps, res);
}
catch (Exception e) {
System.out.println(
"getservice Edistid1xception==>" e);
}
return (taluklist.toString());
}
@RequestMapping(value = "/village",
method = RequestMethod.GET)
@ResponseBody
@CrossOrigin
public String
Listvillage(@RequestParam String Discode,
@RequestParam String Talukcode)
throws ParseException
{
String districtcode = Discode;
String talukcode = Talukcode;
JSONArray villagelist = new JSONArray();
try {
Class.forName("org.postgresql.Driver");
con = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/test?allowPublicKeyRetrieval=true",
"postgres", "password");
sql = "select * from village where distcode=? and talukcode=?";
ps = con.prepareStatement(sql);
ps.setString(1, districtcode);
ps.setString(2, talukcode);
ResultSet resl = ps.executeQuery();
while (resl.next()) {
JSONObject jsonvillage = new JSONObject();
jsonvillage.put("districtcode",
resl.getString("distcode")
.toString()
.trim());
jsonvillage.put("talukcode",
resl.getString("talukcode")
.toString()
.trim());
jsonvillage.put(
"villagecode",
resl.getString("villagecode")
.toString()
.trim());
jsonvillage.put("villagename",
resl.getString("name")
.toString()
.trim());
villagelist.add(jsonvillage);
}
System.out.println("villagelist"
villagelist.size());
close(con, ps, resl);
}
catch (Exception e) {
System.out.println("getservice Exception==>"
e);
}
return (villagelist.toString());
}
private static void close(Connection myConn,
Statement myStmt,
ResultSet myRs)
{
try {
if (myRs != null) {
myRs.close();
}
if (myStmt != null) {
myStmt.close();
}
if (myConn != null) {
myConn.close();
}
}
catch (Exception exc) {
exc.printStackTrace();
}
}
}
代码解释:
- 需要 @RestController 注解来标识 Java 服务类,建议仅在授权发送请求的 URL 时使用 @CrossOrigin 注解。
- @GetMapping(“/dist”) 注释用在 saylistDistrict() 函数之前,以便每当调用包含“/dist”的 URL 时都会调用该函数。
- 函数 saylistDistrict() 从数据库检索数据,处理并返回 JSON 格式的数据,具体解释如下:
- 建立数据库连接并调用相应的选择查询来检索地区详细信息及其各自的代码。
SELECT distcode, name FROM District
查询检索地区名称以及地区代码,然后将其存储在结果集myRs
中。然后迭代 ResultSet,并将地区数据存储在 JSON 对象jsonobj
中。- 迭代每个地区后,生成的
JSONObject
将被添加到主 JSONArray“地区列表”中。使用close(Connection myConn, Statement myStmt, ResultSet myRs)
方法关闭数据库连接,其中Connection
、ResultSet
和Statement
均被关闭。
注意:每次在 Web 应用程序中使用后关闭数据库连接非常重要。如果不这样做,当用户向数据库服务器请求数据库连接时,可能会导致内存泄漏、性能下降、连接短缺。
return(districtlist.toString());
命令将JSONArray
转换为 String,然后将其返回到调用 Java 方法的实体。-
ListTaluk()
函数还使用与saylistDistrict()
函数相同的注释,除了附加注释@RequestMapping(value = “/taluk”, method = RequestMethod.GET)
@RequestMapping(value = “/taluk”, method = RequestMethod.GET)
注释简化了 URL 参数与@RequestParam
注释的映射。- 当 URL 包含
@RequestMapping
注释的 value 参数中提到的值时,将调用此方法。method 参数提到了请求方法,在本例中是GET
方法。RequestMethod
是一个为此目的而编写的内置 Java 类,它在方法名称之前使用,并用点 (.) 分隔 @RequestParam
注释从 URL 读取 distid1 值并将该值存储在String Discode
变量中。然后将值 Discode 存储到字符串变量“discode”中。- 随后的操作和命令与前面的方法类似,除了一些细微的变化之外,这些变化在下面给出的子点中进行了解释:
- 检索 taluk 名称以及相应的地区代码和 taluk 代码的查询是
select * from taluk where distcode=?
?表示地区代码的值。 ps.setString(1,districtcode)
设置查询中的地区代码的值。- 使用命令
ResultSet res = ps.executeQuery();
执行查询并将其存储在ResultSet
中。 jsontaluk
是用于存储每次迭代中的 taluk 名称的JSONObject
。例如,jsontaluk.put("districtcode", res.getString("distcode").toString().trim());
是将地区值存储在JSONObject
中的命令。- 同样,在接下来的三行中,
taluk
代码和taluk名称也存储在JSONObject中,并且该对象存储在JSONArray“taluklist”中 - 使用
return(taluklist.toString());
转换为字符串后返回JSONArray
。命令。 Listvillage()
方法中使用的所有注释与 ListTaluk() 注释中使用的注释相同。- 与
Listvillage()
方法中的操作方式类似,使用查询检索村庄名称、区代码、taluk代码和村庄代码。检索到的数据存储在JSONArray
中,该JSONArray
在方法末尾以字符串格式返回。
构建前端网页
dropdown.jsp
代码语言:javascript复制<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<script type="text/javascript" src="jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="Ajaxcall.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table border="1" cellpadding="10px" cellspacing="5px">
<tr>
<td>District: </td>
<td>
<select id="districtlist" name="districtlist" required>
<option disabled selected>Select District</option>
</select>
</td>
</tr>
<tr>
<td>Taluk: </td>
<td>
<select id="taluklist" name="taluklist" required>
<option disabled>Select Taluk</option>
</select>
</td>
</tr>
<tr>
<td>Village: </td>
<td>
<select id="villagelist" name="villagelist" required>
<option disabled>Select Village</option>
</select>
</td>
</tr>
</table>
</body>
</html>
插件 jquery-3.6.0.min.js 需要导入到 HTML 项目中,当插件部署在本地项目中并导入时效果最佳。该网页很简单,只有基本布局,没有太多 CSS,因为本教程的范围只是解释基于数据库的动态下拉列表。现在下拉菜单的网页布局已经编码,是时候编写 AJAX 调用了。名为 Ajaxcall.js 的 JavaScript 文件用于填充下拉列表。它也是调用链接到 Java 服务方法的 URL 的地方。
Ajaxcall.js
代码语言:javascript复制var dis;
var tal;
var vill;
$(document).ready(function () {
$.ajax({
type: "GET",
url: "http://localhost:8075/dist",
data: "json",
contentType: "application/json",
success: function (data) {
let obj = $.parseJSON(data);
$.each(obj, function (key, value) {
$('#districtlist').append('<option value="' value.districtcode '">' value.districtcode '--' value.districtname '</option>');
});
},
error: function (data) {
$('#districtlist').append('<option>District Unavailable</option>');
},
});
/*$('#districtlist').trigger("change");*/
$('#districtlist').change(function () {
$('#taluklist').find('option').remove();
$('#taluklist').append('<option>Select taluk</option>');
$('#villagelist').find('option').remove();
$('#villagelist').append('<option>Select village</option>');
var distid1 = $('#districtlist').val();
var inputValObj = {};
alert(distid1);
inputValObj.Discode = distid1;
var inputVal = JSON.stringify(inputValObj);
alert(inputVal);
var data = inputVal.toString();
alert(data);
$.ajax({
type: "GET",
url: "http://localhost:8075/taluk?Discode=" distid1,
/*data: 1,*/
contentType: "application/json",
success: function (data) {
let obj = $.parseJSON(data);
$.each(obj, function (key, value) {
$('#taluklist').append('<option value="' value.talukcode '">' value.talukcode '--' value.talukname '</option>');
});
},
error: function (data) {
$('#taluklist').append('<option>Taluk Unavailable</option>');
},
});
});
$('#taluklist').change(function () {
$('#villagelist').find('option').remove();
$('#villagelist').append('<option>Select village</option>');
var distid1 = $('#districtlist').val();
var talukid = $('#taluklist').val();
alert(distid1);
alert(talukid);
var inputValObj = {};
inputValObj.Discode = distid1;
inputValObj.talucode = talukid;
var inputVal = JSON.stringify(inputValObj);
var data = inputVal.toString();
$.ajax({
type: "GET", //POST
url: "http://localhost:8075/village?Discode=" distid1 "&" "Talukcode=" talukid,
contentType: "application/json",
success: function (data) {
let obj = $.parseJSON(data);
$.each(obj, function (key, value) {
$('#villagelist').append('<option value="' value.villagecode '">' value.villagecode '--' value.villagename '</option>');
});
},
error: function (data) {
$('#villagelist').append('<option>village Unavailable</option>');
},
});
});
});
###代码解释
当文档准备好时,在第一次 AJAX 调用中使用http://localhost:8075/distURL 调用 saylistDistrict() 函数,并且提取的数据进入 success 函数。现在,数据被解析并存储到变量obj中,然后使用 jQuery 中的 .each进行迭代,然后使用'('#districtlist').append('<option value=”' value.districtcode '”>' value.districtcode '–' 将迭代中的每个条目附加到地区下拉列表中value.districtname '</option>'); 命令。
当区域下拉列表更改时,jQuery '('#districtlist').change(function () {}); 被调用,url http://localhost:8075/taluk?Discode=” distid1 调用 Java 函数 ListTaluk()。然后使用 ('#taluklist').append('<option value=”' value.talukcode '”>' value.talukcode '–' value 将返回的数据填充到 taluk 下拉列表中。 talukname '</选项>');' 命令。
jQuery '('#taluklist').change(function () {});' 当 taluk 下拉值更改时调用。http://localhost:8075/village?Discode=” distid1 ”&” ”Talukcode=” talukid 调用 Java 函数 Listvillage()。然后使用 '
此外,每当修改下拉列表时,依赖于修改的下拉列表的其他下拉列表值都会被删除,并插入“选择”占位符。使用 .remove() 函数删除下拉值,如上面的示例所示,并使用以下模板中的命令插入“Select”占位符$('#taluklist').append('<option>Select taluk</”选项>');
。
在任何 Spring Boot
项目中,都会有一个带有 @SpringBootApplication 注释的 Java 类,该类必须使用右键单击并运行为 _> Java 应用程序来运行。第一个项目必须以这种方式运行。第二个项目必须在服务器上运行,方法是右键单击 -Run as -> Run on the server。使用以下方法运行 dropdown.jsp
后,可以观察本教程的输出。