1、主要使用的技术
- HTML/CSS
 
- Bootstrap5
 
- javascript/jQuery/jQuery-UI
 
- JSP
 
2、前期调查与设计
搜索引擎主要分为两个界面,主界面和搜索结果界面
主界面

从图看出,主界面的组成有
logo
采用居中设计,在输入框的正上方
搜索框&搜索按钮
整体是一个表单,搜索框可使用Bootstrap5的form-control类,搜索按钮可采用Bootstrap5的按钮样式
表单以GET请求方式请求到搜索结果界面
搜索提示
内部使用js实现,通过发送AJAX请求给后台获取对应的推荐数据,在进行展示。到时候应用jQuery发送AJAX请求和jQuery-UI中的autocompletion插件即可
搜索结果界面
顶部

底部

分析图中的元素构成
- logo
 
- 搜索框&搜索按钮
 
- 搜索结果数量
 
- 选择时间的工具
 
- 一块搜索结果,包含
 
- 分页导航栏
 
排版分析
logo&搜索框&搜索按钮
在Bootstrap5中,可以将他们放在一个container-fluid的容器中,通过Bootstrap5的网格系统,row&col来实现响应式网页
其中表单的组成为搜索框&搜索按钮,提交GET请求给自己让自己处理
搜素结果&选择时间的工具
他们也可以放在一个container中,通过Bootstrap5的网格系统来实现响应式网页。
在该项目的设计中,我将选择时间的工具简化成一个下拉菜单,通过选择相应的选项来实现按时间范围查找功能
如图所示:

搜索结果
首先他们也在一个container中,然后将他们放进一个div,这个div中有a、div.content、a。将对应的样式设计好后,通过jsp循环输出即可
分页导航栏
分页导航栏是动态的,而且这种东西网上肯定有人写过了,果不其然,jqPaginator就能满足我们的需求,只需要简单的创建一个无序列表就能实现,样式的话我们可以采用Bootstrap5的样式,也算可以了
3、设计思路
项目目前采用的是Bootstrap5的框架,由于此次时间有限就采取默认风格,通过学习一些简单的Bootstrap5可以稍微跳过一些CSS的学习,而且更容易创建响应式界面。
基本思路:将元素的组合划分为一个个独立的container或container-fluid,在使用Bootstrap5的样式进行调整即可
4、代码实现
经过3的分析,可以知道大致需要index.html、search.jsp这两个主要文件,和一些处理前端数据的Servlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | <div class="container mb-5 mt-5">     <form action="search.jsp" method="get">         <div class="row">             <div class="col-lg-3"></div>             <div class="input-group mx-auto col">                 <label for="searchInput"></label>                 <input type="search"                        id="searchInput"                        class="form-control search-input"                        placeholder="Enter content"                        name="inputText">                 <button type="submit" class="btn btn-primary">搜索一下</button>             </div>             <div class="col-lg-3"></div>         </div>     </form> </div>
   | 
 
form标签中,action为请求资源路径,method为请求方式;搜索按钮的类型一定要是submit才能提交表单
search.jsp的获取搜索结果部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | <%     
 
 
      request.setCharacterEncoding("utf-8");     String inputText = request.getParameter("inputText");     String page1 = request.getParameter("page");     String beginDate = request.getParameter("beginDate");     String endDate = request.getParameter("endDate");
           if(page1 == null) {         page1 = "1";     }     int currentPage = Integer.parseInt(page1);
           Search search = new EsSearch();     List<ResultEntry> searchResult = new ArrayList<>();     if(inputText != null) {         if(beginDate == null && endDate == null) {             searchResult = search.search(inputText, currentPage);         } else if (endDate == null) {             searchResult = search.search(inputText, currentPage, beginDate);         }     }     long searchCount = search.getSearchCount();
  %>
   | 
 
这个没啥好说的,向后台的ES请求资源
search.jsp的搜索结果输出部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
   | <div class="container">     <div class="result">         <%             for(ResultEntry resultEntry : searchResult) {                 out.println("<div class=\"col col-lg-7 mt-3\">");                 out.println("<a class=\"address\" href="+resultEntry.getUrl()+" target=\"_blank\">"+resultEntry.getTitle()+"</a>");                                  int front = resultEntry.getText().indexOf("<span");                 int tail = resultEntry.getText().lastIndexOf("span>");                 front -= 10; tail += 25;                 if(front < 0) {                     front = 0;                 }                 if(tail > resultEntry.getText().length() - 1) {                     tail = resultEntry.getText().length() - 1;                     do {                         if(!"\"".equals(resultEntry.getText().charAt(tail))) {                             tail++;                             break;                         }                         tail--;                     }while (tail > 0);                 }                 String content = resultEntry.getText().substring(front, tail);                 out.println("<div class=\"content\">"+content+"</div>");                 out.println("<a href="+resultEntry.getUrl()+" style=\"font-size: small; color: gray\">"+resultEntry.getUrl()+"</a>");                 out.println("</div>");             }         %>     </div> </div>
   | 
 
将搜索结果放进一个循环,输出对应的样式即可
其中对content的摘要后面可优化到Servlet里,前端就不会有这么复杂的逻辑处理
SearchSuggest.java获取搜索建议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | @WebServlet("/SearchSuggest") public class SearchSuggest extends HttpServlet {     @Override     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {         request.setCharacterEncoding("utf-8");         String input = request.getParameter("input");         if(input != null) {             Search search = new EsSearch();             List<String> searchSuggest = search.getSearchSuggest(input);             response.setContentType("text/html;charset=utf-8");             PrintWriter out = response.getWriter();             out.println(JSON.toJSONString(searchSuggest));             out.close();             search.close();         }     }
      @Override     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {         this.doGet(request, response);     } }
  | 
 
这个就是获取请求返回对应的JSON字符串,采用了alibaba的fastjson
my-js.js中的jQuery-UI的autocompletion插件的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   |  $(function () {     $(".search-input").autocomplete({         source: function( request, response ) {             var input = $(".search-input").val();             var source = "";             $.ajax({                 type : "get",                 url : "SearchSuggest",                 datatype : "json",                 data: {"input": input},                 async : false,                 error : function() {                     console.error("Load recommand data failed!");                 },                 success : function(data) {                     source = data;                 }             });             response(JSON.parse(decodeURI(source)));         }     }) })
 
  | 
 
autocompletion的回调函数中,response就是响应autocompletion的source的数据
分页跳转功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | $("#my-pagination").jqPaginator({     totalPages: <%=searchCount/10+1%>,     visiblePages: 10,     currentPage: <%=currentPage%>,     first: '<li class="first page-item"><a class="page-link" href="javascript:;">首页</a></li>',     prev: '<li class="prev page-item"><a class="page-link" href="javascript:;">上一页</a></li>',     next: '<li class="next page-item"><a class="page-link" href="javascript:;">下一页</a></li>',     last: '<li class="last page-item"><a class="page-link" href="javascript:;">末页</a></li>',     page: '<li class="page page-item"><a class="page-link" href="javascript:;">{{page}}</a></li>',     onPageChange: function (num, type) {         $('#my-pagination-text').html('当前第' + num + '页');         if("change" == type) {              let inputText = getQueryVariable("inputText");             let beginDate = getQueryVariable("beginDate");                          if(beginDate != "") {                 window.location.href = "search.jsp?inputText="+inputText+"&page="+num+"&beginDate="+beginDate;             } else {                 window.location.href = "search.jsp?inputText="+inputText+"&page="+num;             }         }     } });
  | 
 
使用插件时注意引用Bootstrap5的样式,才可以达到自己的预期效果,还要注意回调函数的两个参数
5、参考链接
w3c-从无到有
菜鸟教程你值得拥有
jQuery