40

Suppose I am having three dropdownlist controls named dd1, dd2 and dd3. The value of each dropdownlist comes from database. dd3's value depends upon value of dd2 and dd2's value depends on value of dd1. Can anyone tell me how do I call servlet for this problem?

4

4 回答 4

49

基本上有三种方法可以实现这一点:

  1. 在第一个下拉列表的 onchange 事件期间提交表单到 servlet(您可以使用 Javascript),让 servlet 获取第一个下拉列表的选定项作为请求参数,让它从数据库中获取第二个下拉列表的关联值作为一个Map<String, String>,让它将它们存储在请求范围内。最后让 JSP/JSTL 显示第二个下拉列表中的值。您可以为此使用JSTL(只需将jstl-1.2.jar放入/WEB-INF/libc:forEach标签。您可以在与 JSP 页面关联的doGet()方法中预填充第一个列表。Servlet

     <select name="dd1" onchange="submit()">
         <c:forEach items="${dd1options}" var="option">
             <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
         </c:forEach>
     </select>
     <select name="dd2" onchange="submit()">
         <c:if test="${empty dd2options}">
             <option>Please select parent</option>
         </c:if>
         <c:forEach items="${dd2options}" var="option">
             <option value="${option.key}" ${param.dd2 == option.key ? 'selected' : ''}>${option.value}</option>
         </c:forEach>
     </select>
     <select name="dd3">
         <c:if test="${empty dd3options}">
             <option>Please select parent</option>
         </c:if>
         <c:forEach items="${dd3options}" var="option">
             <option value="${option.key}" ${param.dd3 == option.key ? 'selected' : ''}>${option.value}</option>
         </c:forEach>
     </select>
    

    然而,一旦需要注意的是,这将提交整个表单并导致“内容闪现”,这可能对用户体验不利。您还需要根据请求参数以相同的形式保留其他字段。您还需要在 servlet 中确定请求是更新下拉列表(子下拉列表值为空)还是提交实际表单。

  2. 将第二个和第三个下拉列表的所有可能值打印为 Javascript 对象,并在第一个下拉列表的 onchange 事件期间使用 Javascript 函数根据第一个下拉列表的选定项填充第二个下拉列表。这里不需要提交表单,也不需要服务器周期。

     <script>
         var dd2options = ${dd2optionsAsJSObject};
         var dd3options = ${dd3optionsAsJSObject};
         function dd1change(dd1) {
             // Fill dd2 options based on selected dd1 value.
             var selected = dd1.options[dd1.selectedIndex].value;
             ...
         }
         function dd2change(dd2) {
             // Fill dd3 options based on selected dd2 value.
             var selected = dd2.options[dd2.selectedIndex].value;
             ...
         }
     </script>
    
     <select name="dd1" onchange="dd1change(this)">
         <c:forEach items="${dd1options}" var="option">
             <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
         </c:forEach>
     </select>
     <select name="dd2" onchange="dd2change(this)">
         <option>Please select parent</option>
     </select>
     <select name="dd3">
         <option>Please select parent</option>
     </select>
    

    但是,需要注意的是,当您拥有大量物品时,这可能会变得不必要的冗长和昂贵。想象一下,每 100 个可能的项目有 3 个步骤,这意味着 JS 对象中有 100 * 100 * 100 = 1,000,000 个项目。HTML 页面的长度将超过 1MB。

  3. 利用Javascript中的XMLHttpRequest在第一个下拉菜单的onchange事件期间向servlet发起一个异步请求,让servlet获取第一个下拉菜单的选中项作为请求参数,让它从第一个下拉菜单中获取第二个下拉菜单的关联值数据库,将其作为 XML 或JSON字符串返回。最后让 Javascript 通过 HTML DOM 树显示第二个下拉列表中的值(Ajax 方式,如前所述)。最好的方法是使用jQuery

     <%@ page pageEncoding="UTF-8" %>
     <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
     <!DOCTYPE html>
     <html lang="en">
         <head>
             <title>SO question 2263996</title>
             <script src="http://code.jquery.com/jquery-latest.min.js"></script>
             <script>
                 $(document).ready(function() {
                     $('#dd1').change(function() { fillOptions('dd2', this); });
                     $('#dd2').change(function() { fillOptions('dd3', this); });
                 });
                 function fillOptions(ddId, callingElement) {
                     var dd = $('#' + ddId);
                     $.getJSON('json/options?dd=' + ddId + '&val=' + $(callingElement).val(), function(opts) {
                         $('>option', dd).remove(); // Clean old options first.
                         if (opts) {
                             $.each(opts, function(key, value) {
                                 dd.append($('<option/>').val(key).text(value));
                             });
                         } else {
                             dd.append($('<option/>').text("Please select parent"));
                         }
                     });
                 }
             </script>
         </head>
         <body>
             <form>
                 <select id="dd1" name="dd1">
                     <c:forEach items="${dd1}" var="option">
                         <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
                     </c:forEach>
                 </select>
                 <select id="dd2" name="dd2">
                     <option>Please select parent</option>
                 </select>
                 <select id="dd3" name="dd3">
                     <option>Please select parent</option>
                 </select>
             </form>
         </body>
     </html>
    

    ..Servlet后面/json/options看起来像这样:

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         String dd = request.getParameter("dd"); // ID of child DD to fill options for.
         String val = request.getParameter("val"); // Value of parent DD to find associated child DD options for.
         Map<String, String> options = optionDAO.find(dd, val);
         String json = new Gson().toJson(options);
         response.setContentType("application/json");
         response.setCharacterEncoding("UTF-8");
         response.getWriter().write(json);
     }
    

    这里GsonGoogle Gson,它可以轻松地将完全有价值的 Java 对象转换为 JSON,反之亦然。另请参阅如何使用 Servlet 和 Ajax?

于 2010-02-15T15:55:29.877 回答
4

You may need multiple servlets for this.

Servlet 1: Load the values for the first drop down list from the database. On the JSP page construct the drop down list. On the user selecting a value submit to servlet two.

Servlet 2: retrieve the value from the first list and perform your database search for the values of the second list. Construct the second list. When the user selects the second value submit it to servlet 3.

Servlet 3: retrieve the value selected in the second drop down and perform the database search to get values for the last drop down.

You may want to consider AJAX to make the populating of the lists appear seamless to the users. jQuery has some very nice plugins for making this quite easy if you are willing to do that.


     <form action="servlet2.do">
          <select name="dd1" onchange="Your JavaScript Here">
               <option>....
          </select>
     </form>

You can write JavaScript that submits the form in the onchange event. Again, If you use an existing library like jQuery it will be 10 times simpler.

于 2010-02-15T04:12:08.207 回答
4

从您的问题来看,您实际上并没有使用 Web 框架,而是使用 servlet 来呈现 html。

我会很高兴地说您落后于时代大约十年 :),人们使用 JSP(以及类似 struts 的 Web 框架)来处理这类事情。然而,话虽如此,这里是:

  1. 在表单中创建一个隐藏字段并将值设置为“1”、“2”或“3”,具体取决于要填充的下拉列表;
  2. 在您的 servlet 中,捕获此值 (request.getParamter()) 并使用它作为“case”/if/else 语句来返回适当的下拉值。

我再说一遍,只需使用 web 框架,或者至少使用普通的旧 jsp 来执行此操作。

于 2010-02-15T04:53:17.020 回答
3

这是一个很棒的简单解决方案。我喜欢 JQuery 代码有多小,并且非常感谢 GSON API 的链接。所有示例都使这成为一个简单的实现。

在使用对父 SELECT (例如)的引用构建 JSON 服务器 URL 时遇到一个问题$(this).val()[需要指定:selected属性]。我稍微修改了脚本以包含建议的更新。感谢您的初始代码。

<script>
$(document).ready(function() 
{
    $('#dd1').change(function() { fillOptions('dd1', 'dd2'); });
    $('#dd2').change(function() { fillOptions('dd2', 'dd3'); });
});

function fillOptions(parentId, ddId) 
{
    var dd = $('#' + ddId);
    var jsonURL = 'json/options?dd=' + ddId + '&val=' + $('#' + parentId + ' :selected').val();
    $.getJSON(jsonURL, function(opts) 
    {
        $('>option', dd).remove(); // Clean old options first.
        if (opts) 
        {
            $.each(opts, function(key, value) 
            {
                dd.append($('<option/>').val(key).text(value));
            });
        } 
        else 
        {
            dd.append($('<option/>').text("Please select parent"));
        }
    });
}
</script>
于 2010-10-24T21:12:35.380 回答