【从0做项目】Java搜索引擎(7) web模块

阿华代码,不是逆风,就是我疯

你们的点赞收藏是我前进最大的动力!!

希望本文内容能够帮助到你!!

目录

文章导读

零:项目结果展示

一:后端web模块

1:思路

2:设计

3:注意点

(1)设置响应头格式

(2)方法返回类型

(3)实例化DocSearch

二:前端代码

 1:head标签

 2:body标签

(1)div标签

(2)style标签

(3)script标签

三:前端显示优化&后端联动

1:实现前端搜索关键字标红

(1)实现逻辑

(2)正则表达式

2:后端代码

3:呈现效果


文章导读

阿华将发布项目复盘系列的文章,旨在:

1:手把手细致带大家从0到1做一个完整的项目,保证每2~3行代码都有详细的注解

2:通过文字+画图的方式,对项目进行整个复盘,更好的理解以及优化项目

3:总结自己的优缺点,扎实java相关技术栈,增强文档编写能力

零:项目结果展示

项目目前已经上线,小伙伴们可以进行使用!!!

Java 文档搜索

简述:在我的搜索引擎网站,用户进行关键字搜索,就可以查询到与这个关键字相关的java在线文档,(包含标题,关键字附近的简述,url),用户点击标题,即可跳转到相关在线文档,适用于JDK17版本。

一:后端web模块

1:思路

提供一个web接口,最终以网页的形式,把我们的程序呈现给用户~~

前端(HTML+CSS+JS)+ 后端(Java,Script、Spring)

约定前后端通信接口,

需要明确的描述出,服务器能够接收什么样的请求,返回什么样的响应~~

2:设计

这里我们只需要实现一个搜索接口即可~~!!

3:注意点

(1)设置响应头格式

这里我们还是使用Jackson库(Jackson我滴神)中ObjectMapper类来实现json和Java对象之间的转换~~,在返回的ContentType中我们需要设置一下 produces= “application/json;charset=utf-8”

(2)方法返回类型

这里我们把多个Result封装为集合的形式进行返回

(3)实例化DocSearch

我们用到DocSearch类中的search方法所以需要对类进行实例化

@RestController
@RequestMapping("/docSearch")
@Slf4j
public class DocSearcherController{private static DocSearcher docSearcher = new DocSearcher();//这里实例化对象后,直接就把构造好的索引加载到内存当中了。(DocSearcher中的构造方法)private ObjectMapper objectMapper = new ObjectMapper();@RequestMapping(value = "/searcher" , produces = "application/json;charset=utf-8")@ResponseBodypublic String search(@RequestParam("query") String query) throws JsonProcessingException {log.info("后端接收到参数query:{}",query);List<Result> results = docSearcher.search(query);return objectMapper.writeValueAsString(results);}
}

二:前端代码

注:博主是后端选手,前端代码这里学的比较浅,通过多方面的帮助,以及阿华的修改查验,完成了前端页面的个性化简单制作,这里我只对我们js代码中的ajax请求进行讲解,大家可以根据自己的审美进行前端页面的制作!!

js源代码不会整的可以在阿华博文中搜索jquery,手把手教你

 1:head标签

<!doctype html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Java 文档搜索</title>
</head>

 2:body标签

(1)div标签

<!-- 通过 .container 来表示整个页面的元素容器 --><div class="container"><!-- 搜索框+搜索按钮 --><div class="header"><input type="text"><button id="search-btn">搜索</button></div><!-- 显示搜索结果 --><div class="result"><!-- 每一条item表示一个结果 --><!-- <div class="item"><a href="#">我是标题</a><div class="desc">我是一段描述嘿嘿嘿,落魄谷中寒风吹,春秋蝉鸣少年归,荡魂山处石人泪,定仙游走魔向北</div><div class="url">https://blog.csdn.net/qq_42257666/article/details/105701914</div></div><div class="item"><a href="#">我是标题</a><div class="desc">我是一段描述嘿嘿嘿,落魄谷中寒风吹,春秋蝉鸣少年归,荡魂山处石人泪,定仙游走魔向北</div><div class="url">https://blog.csdn.net/qq_42257666/article/details/105701914</div></div> --></div></div>

(2)style标签

<style>/*去除浏览器默认样式*/* {margin: 0;padding: 0;box-sizing: border-box;}/* 指定页面高度 */html,body {height: 100%;background-image: url(image/light.jpg);/* 不平铺 */background-repeat: no-repeat;/* 设置背景图位置 */background-position: center center;/* 背景图大小 */background-size: cover;}/* 对内容实现版心效果 */.container {width: 1200px;height: 100%;/* 水平居中 */margin: 0 auto;/* 背景色和透明度 */background-color: rgba(255, 255, 255, 0.6);/* 圆角 */border-radius: 10px;/* 内边距 */padding: 20px;/* 页面滚动 */overflow: auto;}/* 对内容样式进行设置 */.header{width: 100%;height: 50px;/* 框+按钮弹性设置 */display: flex;justify-content: space-between;align-items: center;}.header>input{width: 1050px;height:50px;/* 输入框中字体大小,高度,左边距 */font-size: 22px;line-height: 50px;padding-left: 10px;border-radius: 10px;}.header>button{width: 100px;height: 50px;/* 按钮颜色、字体大小、高度 */background-color:rgb(42, 107, 205) ;color: antiquewhite;font-size: 22px;line-height: 50px;/* 圆角 */border-radius: 10px;border: none;}.header>button:active{background-color: gray;}/* 给搜索结果数字统计css一下 */.result .count{color: gray;margin-top: 10px;}.item{width: 100%;/* 元素顶部外边距,把每一条item间隔开来 */margin-top: 20px;}.item a{/* 块级元素 */display: inline;height: 40px;/* 字体大小高度粗度 */font-size: 20px;line-height: 40px;font-weight: 700;color:rgb(42, 107, 205);}.item .desc{font-size: 18px;}.item .url{font-size: 18px;color: rgb(0,128,0);}/* 把后端设置的i标签中的内容加红 */.item .desc i {color: red; /* 去斜体 */font-style: normal;}</style>

(3)script标签

<script src="js/jquery.js"></script>

思路:

第一步:前端返回的list集合中有好多个Result对象

第二步:我们遍历,对每一个Result进行处理

这里逻辑比较简单,大家边看代码边看注释会比较好理解一点!

<script>// js核心代码let button = document.querySelector("#search-btn");button.onclick = function(){//获取输入框的内容let input = document.querySelector(".header input");let query = input.value;console.log("query:" + query);$.ajax({type: "GET",url: "docSearch/searcher?query=" + query,success: function(data , status){buildResult(data);}});}function buildResult(data){// 把data中每一个元素,把每一个元素都构建成一个div.item,再加入到div.result中let result = document.querySelector('.result');//每次搜索把前一次的结果清空result.innerHTML = '';//显示搜索的结果个数let countDiv = document.createElement('div');countDiv.innerHTML = '当前找到' + data.length + '个结果';countDiv.classNamee = 'count';result.appendChild(countDiv);for(var item of data){let itemDiv = document.createElement('div');itemDiv.className = 'item';//构造一个标题let title = document.createElement('a');title.href = item.url;title.innerHTML = item.title;title.target = '_blank';itemDiv.appendChild(title);//构造描述let desc = document.createElement('div');desc.className = 'desc';desc.innerHTML = item.desc;itemDiv.appendChild(desc);//构造urllet url = document.createElement('div');url.className = 'url';url.innerHTML = item.url;itemDiv.appendChild(url);result.appendChild(itemDiv);}}</script>

三:前端显示优化&后端联动

1:实现前端搜索关键字标红

【从0做项目】Java搜索引擎(5)-CSDN博客

这篇文章介绍了正文的一个处理逻辑

(1)实现逻辑

①我们修改后端代码,生成搜索结果的时候,把其中包含查询词的部分,加上一个标记,例如:给这部分加<i>标签,这样前端就可以进行处理了

②前端针对这个<i>标签设置样式,我是给标红了!!(写的时候华也红温了)


(2)正则表达式

依然是掏出我们的正则表达式

2:后端代码

第一步:对正文进行处理,转小写,把标点和空格全部替换成空格,这样单词与单词之间就以空格分隔开来

第二步:遍历搜索词句的分词,在正文中锁定位置(只要找到一个就break)

第三步:截取一定长度正文,这里不做过多描述,之前有详细介绍

第四步:在正文中把所有term关键字给替换成

举个例子:

单词1 空格 word 空格 单词2 空格 ——》     

"空格"+word+"空格"     ——>     <i>word<i/>

"(?i)"这是一个正则表达式的修饰符,表示忽略大小写,可以理解成,在匹配过程中,不区分字母的大小写。

    private String GenDesc(String content , List<Term> terms){//遍历分词结果,看哪个int firstPos = -1;for(Term term : terms){String word = term.getName();
//            firstPos = content.toLowerCase().indexOf(" " + word + " ");//避免包含关系 例:查array  结果查到ArrayList//使用正则表达式,indexOf不支持正则,我们曲线救国!!content = content.toLowerCase().replaceAll("\\b" + word + "\\b" , " " + word + " ");//匹配标点符号和空格,全部替换成空格firstPos = content.indexOf(" " + word + " ");//女少if(firstPos >= 0){break;//找到了位置,可能这个content中会包含多个term,我们只取第一个}}//用户输入的词,在正文中没有出现,虽然有点扯,但还是处理一下这种情况if(firstPos == -1){if(content.length() > 160){return content.substring(0,160) + "...";}return content;//我去测试了一下,还真有这种情况离谱!说明查的词在标题中出现了,但是正文没出现666,这里也要对正文的长度做一下判断}//截取一部分正文String desc = "";int descBeg = firstPos < 60 ? 0 : firstPos - 60;if(descBeg + 160 > content.length()){desc = content.substring(descBeg);}else {desc = content.substring(descBeg , descBeg + 160) + "...";}for(Term term : terms){String word = term.getName();desc = desc.replaceAll("(?i) " + word + " " , "<i> " + word + "</i> ");//正则忽略大小写全字段匹配,那头单词和尾单词呢?}return desc;}

3:呈现效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/70371.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Visual Studio Code 集成 Baidu Comate

文章目录 安装Baidu Comate插件 安装Baidu Comate插件 从左主侧栏中 点击 【扩展】这个图标&#xff0c;然后在上方输入栏中输入 baidu comate —>选中列出的Bai Comate —>点击 【安装】按钮&#xff0c;等待安装完毕…

WeMos D1+PIR+Android 的小场景制作

最近在做一个有趣的小场景功能&#xff0c;其实已经有成熟产品&#xff0c;但是考虑到没法实现场景扩展&#xff0c;所以自己开始动手做。 场景描述&#xff1a;玄关人体感应&#xff0c;有人进门&#xff0c;致欢迎词&#xff0c;有人离开&#xff0c;致欢送词。 硬件设备&a…

Android ListPreference使用

Android ListPreference使用 参考 添加链接描述 导入 androidx.preference.ListPreferenceListPreference是Android中的一个Preference子类,用于显示一个可选择的列表,并且可以保存用户所选择的值。它继承自DialogPreference,可以在用户点击时弹出一个对话框,显示可选择的…

Spring Security实现记住我功能的实战指南

在现代Web应用中&#xff0c;"记住我"功能是提升用户体验的重要特性之一。用户无需在每次访问时重新登录&#xff0c;这不仅方便&#xff0c;还能增强用户对应用的粘性。今天&#xff0c;我们将通过一个具体的实例&#xff0c;详细探讨如何在Spring Security中实现&q…

用命令模式设计一个JSBridge用于JavaScript与Android交互通信

用命令模式设计一个JSBridge用于JavaScript与Android交互通信 在开发APP的过程中&#xff0c;通常会遇到Android需要与H5页面互相传递数据的情况&#xff0c;而Android与H5交互的容器就是WebView。 因此要想设计一个高可用的 J S B r i d g e JSBridge JSBridge&#xff0c;不…

ModuleNotFoundError: No module named ‘timm.optim.novogr两种解决方法

运行报错 from timm.optim.novograd import NovoGradModuleNotFoundError: No module named ‘timm.optim.novograd’。 问题原因 timm版本过高&#xff0c;novograd函数已被抛弃。 解决办法 方法1&#xff1a;安装更低版本的timm pip install timm0.4.12方法2&#xff1a…

DeepSeek 本地部署指南:从零开始搭建 AI 搜索工具

1. 引言 背景介绍 DeepSeek 是一款基于 AI 的搜索工具&#xff0c;能够高效处理海量数据&#xff0c;提供精准的搜索结果。它结合了 Ollama 的模型管理能力&#xff0c;使得部署更加便捷。 为什么选择本地部署 本地部署可以确保数据隐私&#xff0c;避免云端传输的风险&…

昇腾DeepSeek模型部署优秀实践及FAQ

2024年12月26日&#xff0c;DeepSeek-V3横空出世&#xff0c;以其卓越性能备受瞩目。该模型发布即支持昇腾&#xff0c;用户可在昇腾硬件和MindIE推理引擎上实现高效推理&#xff0c;但在实际操作中&#xff0c;部署流程与常见问题困扰着不少开发者。本文将为你详细阐述昇腾 De…

vscode复制到下一行

linux中默认快捷键是ctrl shift alt down/up 但是在vscode中无法使用&#xff0c;应该是被其他的东西绑定了&#xff0c;经测试&#xff0c;可以使用windows下的快捷键shift alt down/up { “key”: “shiftaltdown”, “command”: “editor.action.copyLinesDownAction”…

网络爬虫学习:借助DeepSeek完善爬虫软件,实现模拟鼠标右键点击,将链接另存为本地文件

一、前言 最近几个月里&#xff0c;我一直在学习网络爬虫方面的知识&#xff0c;每有收获都会将所得整理成文发布&#xff0c;不知不觉已经发了7篇日志了&#xff1a; 网络爬虫学习&#xff1a;从百度搜索结果抓取标题、链接、内容&#xff0c;并保存到xlsx文件中 网络爬虫学…

Arduino 第十六章:pir红外人体传感器练习

Arduino 第十六章&#xff1a;PIR 传感器练习 一、引言 在 Arduino 的众多有趣项目中&#xff0c;传感器的应用是非常重要的一部分。今天我们要学习的主角是 PIR&#xff08;被动红外&#xff09;传感器。PIR 传感器能够检测人体发出的红外线&#xff0c;常用于安防系统、自动…

CV -- YOLOv8 图像分割(GPU环境)

目录 参考视频&#xff1a; 标注 JSON转为TXT 训练 验证 参考视频&#xff1a; 使用 Yolov8 自定义数据集进行图像分割_哔哩哔哩_bilibili 标注 数据集&#xff1a; 我使用的是一些苹果数据集&#xff0c;可以在我的csdn资源中下载&#xff1a; https://download.csdn.net/do…

深入理解 lua_KFunction 和 lua_CFunction

在 Lua C API 中,lua_KFunction 和 lua_CFunction 是两个核心概念,尤其在处理协程和 C 函数扩展时扮演着至关重要的角色。lua_CFunction 作为一种 C 函数类型,允许开发者将 C 函数注册到 Lua 环境中,使得这些 C 函数可以在 Lua 脚本中被调用,进而实现 Lua 的功能扩展。而 …

基于微信小程序的电影院订票选座系统的设计与实现,SSM+Vue+毕业论文+开题报告+任务书+指导搭建视频

本系统包含用户、管理员两个角色。 用户角色&#xff1a;注册登录、查看首页电影信息推荐、查看电影详情并进行收藏预定、查看电影资讯、在线客服、管理个人订单等。 管理员角色&#xff1a;登录后台、管理电影类型、管理放映厅信息、管理电影信息、管理用户信息、管理订单等。…

【Linux网络编程】应用层协议HTTP(请求方法,状态码,重定向,cookie,session)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ Linux网络编程笔记&#xff1a; https://blog.cs…

Vue3 打造 Windows 桌面个性高效组件工具

软件介绍 Widgets 这款基于 Vue3 构建的开源 Windows 桌面小部件工具超实用。 其多样化组件库涵盖超 20 种&#xff0c;从倒计时、打工进度等实用工具&#xff0c;到抖音热榜等实时资讯组件应有尽有&#xff0c;各组件独立运行&#xff0c;满足多场景需求。 高度自定义布局支持…

Tailwind CSS 和 UnoCSS简单比较

一、Tailwind CSS 和 UnoCSS简介 Tailwind CSS 和 UnoCSS 都是流行的原子化 CSS 框架&#xff0c;它们有很多相似之处&#xff0c;但也存在一些明显的区别&#xff0c;以下从多个方面对它们进行比较&#xff1a; 1. 基本概念和原理 Tailwind CSS 是最早提出并推动原子化 CSS…

什么是语料清洗、预训练、指令微调、强化学习、内容安全; 什么是megatron,deepspeed,vllm推理加速框架

什么是语料清洗、预训练、指令微调、强化学习、内容安全 目录 什么是语料清洗、预训练、指令微调、强化学习、内容安全语料清洗预训练指令微调强化学习内容安全什么是megatron,deepspeed,vllm推理加速框架语料清洗 语料清洗是对原始文本数据进行处理的过程,旨在去除数据中的…

C++(23):lambda可以省略()

C越来越多的使用了lambda&#xff0c;C23也进一步的放宽了对lambda的限制&#xff0c;这一次&#xff0c;如果lambda没有参数列表&#xff0c;那么可以直接省略掉()&#xff1a; #include <iostream> using namespace std;void func() {auto f []{cout<<"in…

自制操作系统分享第四天

今天要做什么&#xff1f; &#xff08;1&#xff09;分享 我们上面已经说过INT 0x13这种指令&#xff08;调用BIOS的INT指令&#xff09;&#xff0c;我们知道这是调用BIOS的0x13函数&#xff0c;但还不明白它到底是干什么用的&#xff1a; AH 0x02;# 读盘 AH 0x03;# 写…