jQuery实现级联下拉框实战(5)


Posted in Javascript onFebruary 08, 2017

今天来完成jQuery实战的级联下拉框效果。效果功能如下:

jQuery实现级联下拉框实战(5)

页面默认只提供汽车厂商,当选择了具体的某品牌汽车,汽车类型下拉框就会动态的显示出来,选择对应的类型,然后出来该汽车类型对应的轮胎类型下拉框显示出来,选中轮胎类型,页面的正中间会显示出汽车的图片。
思路分析如图:

jQuery实现级联下拉框实战(5)

建立我们的html页面,程序清单如下:

代码清单1.1: chainSelect.jsp

<body>
 <div class="loading">
 <p><img src="../image/data-loading.gif" alt="数据装载中" /></p>
 <p>数据装载中......</p>
 </div> 
 <div class="car">
 <span class="carname"> 
 汽车厂商:
 <select>
 <option value="" selected="selected">请选择汽车厂商</option>
 <option value="BMW">宝马</option>
 <option value="Audi">奥迪</option>
 <option value="VW">大众</option>
 </select>
 <img src="../image/pfeil.gif" alt="有数据">
 </span>
 <span class="cartype">
 汽车类型:
 <select>
 <option selected="selected">默认选项</option>
 <option>Test1</option>
 </select>
 <img alt="有数据" src="../image/pfeil.gif">
 </span>
 <span class="wheeltype">
 车轮类型:
 <select>
 <option selected="selected">默认选项</option>
 <option>Test1</option>
 </select>
 </span>
 </div>
 <div class="carimage">
 <p><img src="../image/img-loading.gif" alt="图片装载中" class="carloading"></p>
 <p><img src="" alt="汽车图片" class="carimg"></p>
 </div>
</body>

body体里面囊括了3个div,第一个div的作用是显示“数据正在装载中…”的图片和文字。第二个div显示级联下拉效果。第三个div显示车辆图片。

css代码如下:

代码清单1.2:chainSelect.css

.loading {
 width: 400px;
 margin: 0 auto;
/* visibility: hidden; */
}
.loading p {
 text-align: center;
}
p {
 margin: 0;
}
.car {
 text-align: center;
}
.carimage {
 text-align: center;
}
.cartype, .wheeltype, .carloading, .carimg, .car img {
 display: none;
}

代码清单1.3:chainSelect.js

$(document).ready(function(){
 //找到三个下拉框
 var carnameSelect = $(".carname").children("select");
 var cartypeSelect = $(".cartype").children("select");
 var wheeltypeSelect = $(".wheeltype").children("select");

 carnameSelect.change(function(){
 console.log("汽车厂商触发onChange事件");
 });
 cartypeSelect.change(function(){
 console.log("汽车类型触发onChange事件");
 });
 wheeltypeSelect.change(function(){
 console.log("车轮触发onChange事件");
 });
});

首先用jQuery的class选择器选择出三个下拉的框,当它们的值改变时触发对应的jQuery函数,对jQuery函数的处理才是重点的内容。
首先说到jQuery中的ajax交互。前一篇我们用到get()的请求方式,今天来用以用post()方法的请求方式。

jQuery.post(url, [data], [callback], [type])

概述:

通过远程 HTTP POST 请求载入信息.这是一个简单的 POST 请求功
能以取代复杂ajax() 。请求成功时可调>用回调函数。如果需要在出错时执行函数,请使用 $.ajax。

参数含义:

url:发送请求地址。
data:待发送 Key/value 参数。
callback:发送成功时回调函数。
type:返回内容格式,xml, html, script, json, text, _default。

案例如下:

代码清单1.4:demo.js

$(document).ready(function(){
 //发起ajax请求
 $.post("../chainSelect", {name: "John", time: "2pm"}, function(data){
 console.log("name : " + data.name);
 console.log("type : " + data.type);
 }, "json");
});

后台Serlvet处理如下(当然你可以使用java框架,也可以使用其他后台语言)。

代码清单1.5:demo.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ChainSelect extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 System.out.println("name = " + request.getParameter("name"));
 System.out.println("time = " + request.getParameter("time"));

 response.setCharacterEncoding("UTF-8");
 response.setContentType("application/json; charset=utf-8");
 String jsonStr = "{\"name\":\"fly\",\"type\":\"虫子\"}";
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.write(jsonStr);
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 out.close();
 }
 }

 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request, response);
 }
}

别忘了纯Serlvet部属要在你的web.xml做配置。我的Serlvet的完整路进地址是:http://localhost:8080/JqueryStudy/chainSelect ,两句System.out.println()输出ajax传递过来的参数name和time。response.setCharacterEncoding(“UTF-8”)的作用是告诉浏览器字符串为utf-8的编码,防止中文乱码问题。response.setContentType(“application/json; charset=utf-8”)将返回的字符串以json格式形式返回。out对象是输出流,如果返回的是数组,格式应该如下:[“test1”, “test2”, “test3”],如果是json类,则格式如下:{“name”:”fly”,”type”:”虫子”}。

上诉案例返回的是json对象,后台控制台输出:

name = John
time = 2pm

前端浏览器的控制台输出:

name : fly
type : 虫子

Servlet返回数组的案例如下:

代码清单1.6:demo.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ChainSelect extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 System.out.println("name = " + request.getParameter("name"));
 System.out.println("time = " + request.getParameter("time"));

 response.setCharacterEncoding("UTF-8");
 response.setContentType("application/json; charset=utf-8");
 String jsonStr = "[\"test1\", \"test2\", \"test3\"]";
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.write(jsonStr);
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 out.close();
 }
 }

 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request, response);
 }
}

前端jQuery代码:

$(document).ready(function(){
 //发起ajax请求
 $.post("../chainSelect", {name: "John", time: "2pm"}, function(data){
 for(var i = 0; i < data.length; i++) {
 console.log((i+1) + " : " + data[i]);
 }
 }, "json");
});

后台之需要给jsonStr赋值为数组格式而已,而前端jQuery代码由于接收到的字符串数组,所以这里需要用遍历数组的形式来遍历。

本案例的Servlet代码清单:

代码清单1.7:ChainSelect.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ChainSelect extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 response.setCharacterEncoding("UTF-8");
 response.setContentType("application/json; charset=utf-8");
 String jsonStr = this.getStr(request.getParameter("keyword"), request.getParameter("type"));
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.write(jsonStr);
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 out.close();
 }
 }

 }

 private String getStr(String keyword, String type) {
 String jsonStr = "";
 if("top".equals(type)) {
 if("BMW".equals(keyword)) {
 jsonStr = "[\"316ti\", \"6ercupe\"]";
 } else if("Audi".equals(keyword)) {
 jsonStr = "[\"tt\"]";
 } else if("VW".equals(keyword)) {
 jsonStr = "[\"Golf4\"]";
 }
 } else if("sub".equals(type)) {
 if("tt".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\", \"rhc\"]";
 } else if("316ti".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\"]";
 } else if("6ercupe".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\", \"rhc\"]";
 } else if("Golf4".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\"]";
 }
 }
 return jsonStr;
 }
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request, response);
 }
}

代码清单1.7与清单1.6的区别是,后者多了getStr()的方法,该方法用于判断前端传递过来的是一级(top)下拉框的值,还是二级(sub)下拉框的值,并根据传递的keyword返回需要的字符串。与本后台交互的是程序清单1.8所示的代码。

程序清单1.8:chainSelect.js

/**
 * 级联下拉框效果
 */

$(document).ready(function(){
 //找到三个下拉框
 var carnameSelect = $(".carname").children("select");
 var cartypeSelect = $(".cartype").children("select");
 var wheeltypeSelect = $(".wheeltype").children("select");

 carnameSelect.change(function(){
 var carname = carnameSelect.val();
 if(carname != "") {
 //汽车厂商不为空发起ajax请求
 $.post("../chainSelect", {keyword: carname, type : "top"}, function(data){
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
 }
 }, "json");
 } else {
 //3.如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏
 $(".cartype").hide();
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 }
 });

 cartypeSelect.change(function(){
 var cartype = cartypeSelect.val();
 if(cartype != "") {
 //汽车类型不为空发起ajax请求
 $.post("../chainSelect", {keyword: cartype, type : "sub"}, function(data){
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  wheeltypeSelect.html("");
  $("<option value=''>请选择车轮类型</option>").appendTo(wheeltypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(wheeltypeSelect);
  }
  $(".wheeltype").show();
  cartypeSelect.next("img").show();
 }
 }, "json");
 } else {
 //汽车类型为空
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 } 
 });

 wheeltypeSelect.change(function(){
 //选中的车轮类型
 var wheeltype = wheeltypeSelect.val();

 if(wheeltype != "") {
 //选中的车辆厂商
 var carname = carnameSelect.val();
 //选中的车辆类型
 var cartype = cartypeSelect.val();

 //图片的名称
 var carimgName = carname + "_" + cartype + "_" + wheeltype + ".jpg";
 console.log("carimgName : " + carimgName);

 $(".carimage").show();

 $(".carimg").attr("src", "../image/" + carimgName).load(function(){
 //隐藏loading图片
 $(".carloading").hide("slow");
 });
 $(".carimage p img").show("slow");
 } else {
// alert("内容为空");
// $("img").hide();
 $(".carimage").hide();
 }
 });

 //给数据装载中的节点定义ajax事件,实现动画提示效果
 $(".loading").ajaxStart(function(){
 $(this).css("visibility", "visible");
 $(this).animate({
 opacity: 1
 },0);
 }).ajaxStop(function(){
 $(this).animate({
 opacity: 0
 },500);
 });
});

jQuery代码的思路是,用class选择器选择出三个下拉框,赋值给变量carnameSelect,cartypeSelect,wheeltypeSelect,默认carnameSelect下拉框是显示的,其他下拉框是隐藏。然后给他们三者注册change()事件,当用户选择下拉框的值的时候执行事件函数体里面的内容。这里我以第一级下拉框为例来讲解处理的过程。如果用户选择了第一级下拉框”汽车厂商”的”宝马”,则执行如下代码:

carnameSelect.change(function(){
 var carname = carnameSelect.val();
 if(carname != "") {
 //汽车厂商不为空发起ajax请求
 $.post("../chainSelect", {keyword: carname, type : "top"}, function(data){
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
 }
 }, "json");
 } else {
 //3.如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏
 $(".cartype").hide();
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 }
 });

先将第一级下拉框内容取出来,如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏。如果有内容, 则用该行代码$.post(“../chainSelect”, {keyword: carname, type : “top”}, function(data){}, “json”)向上诉的Serlvet发起post请求,post的第一个参数是Serlvet的后台地址,第二个参数画括号括起来的json数据,第三个参数是回调函数,第四个参数”json”表明发送的json数据。在回调函数中,参数data接收Serlvet返回的值,由于Serlvet返回的是可以解析为字符串数组的数据,所以用for循环来遍历得到的数据,并生成option新节点appenTo()插入到select之后。

程序清单1.8中,值得注意的地方还有$(“.loading”).ajaxStart(function(){}).ajaxStop(function(){}),这是为了美化汽车图片加载的代码。这里用到jQuery的动画专用效果的animate(),使程序淡入淡出更加的和谐。

到此几乎把级联效果实现了,但是如果在高并发环境下,每次用户切换选项都向服务器发送请求,服务器的压力可能过大。所以这里我们用jQuery的缓存来保存那些已经缓存过的请求。可以使用jQuery的data()方法。

定义和用法

从被选元素中返回附加的数据。

$(selector).data(name)

name 可选。规定要取回的数据的名称。
如果没有规定名称,则该方法将以对象的形式从元素中返回所有存储的数据。

向元素附加数据

$(selector).data(name,value)

name 必需。规定要设置的数据的名称。
value 必需。规定要设置的数据的值。
data()的使用案例如程序清单1.9:

<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
 $("#btn1").click(function(){
 $("div").data("greeting", "Hello World");
 });
 $("#btn2").click(function(){
 alert($("div").data("greeting"));
 });
});
</script>
</head>
<body>
<button id="btn1">把数据添加到 div 元素</button><br />
<button id="btn2">获取已添加到 div 元素的数据</button>
<div></div>
</body>
</html>

加上缓存之后的完整jQuery代码如下程序清单。
程序清单2.0:chainSelect.js

/**
 * 级联下拉框效果
 */

$(document).ready(function(){
 //找到三个下拉框
 var carnameSelect = $(".carname").children("select");
 var cartypeSelect = $(".cartype").children("select");
 var wheeltypeSelect = $(".wheeltype").children("select");

 carnameSelect.change(function(){
 var carname = carnameSelect.val();
 if(carname != "") {
 if (!carnameSelect.data(carname)) {
 //汽车厂商不为空发起ajax请求
 $.post("../chainSelect", {keyword: carname, type : "top"}, function(data){
  if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
  }
  //将data放入缓存
  carnameSelect.data(carname, data);
 }, "json");
 } else {
 //从缓存中取出数据
 var data = carnameSelect.data(carname);
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
 }
 }
 } else {
 //3.如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏
 $(".cartype").hide();
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 }
 });

 cartypeSelect.change(function(){
 var cartype = cartypeSelect.val();
 if(cartype != "") {
 if(!cartypeSelect.data(cartype)) {
 //汽车类型不为空发起ajax请求
 $.post("../chainSelect", {keyword: cartype, type : "sub"}, function(data){
  if(data != null && data.length != 0) {
  //清除上一次change的内容
  wheeltypeSelect.html("");
  $("<option value=''>请选择车轮类型</option>").appendTo(wheeltypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(wheeltypeSelect);
  }
  $(".wheeltype").show();
  cartypeSelect.next("img").show();
  }
  cartypeSelect.data(cartype, data);
 }, "json");
 } else {
 var data = cartypeSelect.data(cartype);
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  wheeltypeSelect.html("");
  $("<option value=''>请选择车轮类型</option>").appendTo(wheeltypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(wheeltypeSelect);
  }
  $(".wheeltype").show();
  cartypeSelect.next("img").show();
 }
 }
 } else {
 //汽车类型为空
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 } 
 });

 wheeltypeSelect.change(function(){
 //选中的车轮类型
 var wheeltype = wheeltypeSelect.val(); 
 if(wheeltype != "") {
 //选中的车辆厂商
 var carname = carnameSelect.val();
 //选中的车辆类型
 var cartype = cartypeSelect.val();

 //图片的名称
 var carimgName = carname + "_" + cartype + "_" + wheeltype + ".jpg";

 $(".carimage").show(); 
 //通过Javascript中的Image对象预装载图片
 var cacheimg = new Image();
 $(cacheimg).attr("src", "../image/" + carimgName).load(function(){
 //隐藏loading图片
 $(".carloading").hide("slow");
 $(".carimg").attr("src", "../image/" + carimgName);
 });


 $(".carimage p img").show("slow");
 } else {
 $(".carimage").hide();
 }
 });

 //给数据装载中的节点定义ajax事件,实现动画提示效果
 $(".loading").ajaxStart(function(){
 $(this).css("visibility", "visible");
 $(this).animate({
 opacity: 1
 },0);
 }).ajaxStop(function(){
 $(this).animate({
 opacity: 0
 },500);
 });
});

用了data()之后,当用户选择了下拉框,并不是直接奔着服务器请求而去的,而是先判断缓存是否为空,carnameSelect.data(carname)。如果为空,则发起ajax请求,并将返回的结果放进缓存carnameSelect.data(carname, data)。如果不为空,在循环添加option节点之前data从缓存中拿到var data = carnameSelect.data(carname)。同样的,图片的缓存放进我们的Image对象中var cacheimg = new Image(),这行代码往后的第一行和第四行将缓存中的图片取出并显示出来。

代码下载地址:https://github.com/shizongger/JqueryInAction

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jQuery的ajax功能实现web service的json转化
Aug 29 Javascript
JS实现一键回顶功能示例代码
Oct 28 Javascript
Visual Studio中js调试的方法图解
Jun 30 Javascript
IE中鼠标经过option触发mouseout的解决方法
Jan 29 Javascript
jquery中trigger()无法触发hover事件的解决方法
May 07 Javascript
JQuery日历插件My97DatePicker日期范围限制
Jan 20 Javascript
AngularJS基础 ng-include 指令简单示例
Aug 01 Javascript
如何实现星星评价(jquery.raty.js插件)
Dec 21 Javascript
使用微信内嵌H5网页解决JS倒计时失效问题
Jan 13 Javascript
jQuery图片加载失败替换默认图片方法汇总
Nov 29 jQuery
微信小程序项目实践之主页tab选项实现
Jul 18 Javascript
使用axios发送post请求,将JSON数据改为form类型的示例
Oct 31 Javascript
webpack入门+react环境配置
Feb 08 #Javascript
JavaScript实现鼠标点击导航栏变色特效
Feb 08 #Javascript
jQuery实现优雅的弹窗效果(6)
Feb 08 #Javascript
JavaScript中的子窗口与父窗口的互相调用问题
Feb 08 #Javascript
深入理解js中的加载事件
Feb 08 #Javascript
滚动条的监听与内容随着滚动条动态加载的实现
Feb 08 #Javascript
JQuery页面随滚动条动态加载效果的简单实现(推荐)
Feb 08 #Javascript
You might like
php 计算两个时间戳相隔的时间的函数(小时)
2009/12/18 PHP
PHP打开和关闭文件操作函数总结
2014/11/18 PHP
php实现无限级分类
2014/12/24 PHP
php表单处理操作
2017/11/16 PHP
Javascript 写的简单进度条控件
2008/01/22 Javascript
jQuery 学习第七课 扩展jQuery的功能 插件开发
2010/05/17 Javascript
JS实现鼠标单击与双击事件共存
2014/03/08 Javascript
jQuery Mobile操作HTML5的常用函数总结
2016/05/17 Javascript
jquery validate表单验证插件
2016/09/06 Javascript
vue组件表单数据回显验证及提交的实例代码
2018/08/30 Javascript
小程序scroll-view组件实现滚动的示例代码
2018/09/20 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2永雾林渊版本开启新篇章
2020/12/22 DOTA
python中map()与zip()操作方法
2016/02/27 Python
Python 实现微信防撤回功能
2019/04/29 Python
python实时检测键盘输入函数的示例
2019/07/17 Python
Django实现web端tailf日志文件功能及实例详解
2019/07/28 Python
给大家整理了19个pythonic的编程习惯(小结)
2019/09/25 Python
Python jieba库用法及实例解析
2019/11/04 Python
Python中的四种交换数值的方法解析
2019/11/18 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
2020/03/12 Python
Django与pyecharts结合的实例代码
2020/05/13 Python
Django用户登录与注册系统的实现示例
2020/06/03 Python
python ssh 执行shell命令的示例
2020/09/29 Python
pycharm配置python 设置pip安装源为豆瓣源
2021/02/05 Python
俄罗斯首家面向中国消费者的一站式购物网站:Wruru
2020/05/08 全球购物
大学生毕业求职简历的自我评价
2013/10/24 职场文书
执行总经理岗位职责
2014/02/03 职场文书
开业庆典策划方案
2014/02/18 职场文书
利群广告词
2014/03/20 职场文书
请假条的格式
2014/04/11 职场文书
奉献家乡演讲稿
2014/09/13 职场文书
结婚幸福感言
2015/08/01 职场文书
2019朋友新婚祝福语精选
2019/10/10 职场文书
oracle覆盖导入dmp文件的2种方法
2021/05/21 Oracle
SpringBoot整合RabbitMQ的5种模式实战
2021/08/02 Java/Android
MySQL范围查询优化的场景实例详解
2022/06/10 MySQL