文章目录
- 后端
- 新建图片类型Picture
- 创建图片接口类PictureController
- 新建PictureQueryRequest
- 创建Service类
- 创建实现类PictureServiceImpl
- 前端
- 添加接口获取后端数据
- 修改picture页面内容
- 添加文章,图片的搜索功能
- 修改查询参数的获取,实现查询用户功能
- 存在的问题
- 几种不同的业务场景
后端
新建图片类型Picture
@Data
public class Picture implements Serializable {private String title;private String url;private static final long serialVersionUID = 1L;
}
创建图片接口类PictureController
@RestController
@RequestMapping("/picture")
@Slf4j
@CrossOrigin(originPatterns = {"http://localhost:8081"}, allowCredentials = "true", allowedHeaders = {"*"})
public class PictureController {@Resourceprivate PictureService pictureService;/*** 分页搜索(从 ES 查询,封装类)** @param pictureQueryRequest* @param request* @return*/@PostMapping("/search/page/vo")public BaseResponse<Page<Picture>> searchPictureByPage(@RequestBody PictureQueryRequest pictureQueryRequest,HttpServletRequest request) {long size = pictureQueryRequest.getPageSize();long current = pictureQueryRequest.getCurrent();// 限制爬虫ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);String searchText = pictureQueryRequest.getSearchText();Page<Picture> picturePage = pictureService.searchPicture(searchText,current,size);return ResultUtils.success(picturePage);}}
新建PictureQueryRequest
@Data
public class PictureQueryRequest extends PageRequest implements
Serializable {private String SearchText;private static final long serialVersionUID = 1L;
}
创建Service类
@Service
public interface PictureService {Page<Picture> searchPicture(String searchText, long pageNum, long pageSize);
}
创建实现类PictureServiceImpl
@Service
@Slf4j
public class PictureServiceImpl implements PictureService {@Overridepublic Page<Picture> searchPicture(String searchText, long pageNum, long pageSize) {long current = (pageNum - 1) * pageSize;String url = String.format("https://cn.bing.com/images/search?q=%s&first=%s",searchText,current);Document doc = null;try {doc = Jsoup.connect(url).get();} catch (IOException e) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "数据抓取失败");}Elements elements = doc.select(".iuscp.isv"); //数组,每个元素是每一张图片List<Picture> pictures = new ArrayList<>();for (Element element : elements) {//取图片地址murlString m = element.select(".iusc").attr("m");Map<String, Object> map = JSONUtil.toBean(m, Map.class);String murl = (String) map.get("murl");//取标题String title = element.select(".inflnk").attr("aria-label");Picture picture = new Picture();picture.setTitle(title);picture.setUrl(murl);pictures.add(picture);if (pictures.size() >= pageSize)break;}Page<Picture> picturePage = new Page<>(pageNum,pageSize);picturePage.setRecords(pictures);return picturePage;}}
前端
添加接口获取后端数据
坐标:src/pages/InderxPage.vue
<template><div class="index-page"><a-tabs v-model:activeKey="activeKey" @change="onTabchange"><a-tab-pane key="picture" tab="图片" force-render><PictureList :picture-list="pictureList" /></a-tab-pane></a-tabs></div>
</template>
<script setup lang="ts">const pictureList = ref([]);myAxios.post("/picture/list/page/vo", {}).then((res: any) => {pictureList.value = res.records;});
</script>
修改picture页面内容
坐标:src/components/PictureList.vue
<template><!-- 获取每一张图片的pictureList --><a-list item-layout="horizontal" :data-source="props.pictureList":grid="{ gutter: 16, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: 3 }"><template #renderItem="{ item }"><a-list-item><a-card hoverable><template #cover><img alt="example" :src="item.url" /></template><a-card-meta :title="item.title" /></a-card></a-list-item></template></a-list>
</template>
<script setup lang="ts">import { withDefaults, defineProps } from "vue";// 接口和默认值interface Props {pictureList: any[];}const props = withDefaults(defineProps<Props>(), {pictureList: () => [],});
</script>
<style scoped>.image-list {display: flex;flex-wrap: wrap;}
</style>
添加文章,图片的搜索功能
坐标:src/pages/InderxPage.vue
<script setup lang="ts">
/*** 加载数据* @param params*/
const loadData = (params: any) => {const query = {...params,searchText: params.text,};myAxios.post("/post/list/page/vo", query).then((res: any) => {postList.value = res.records;});myAxios.post("/user/list/page/vo", query).then((res: any) => {userList.value = res.records;});myAxios.post("/picture/list/page/vo", query).then((res: any) => {pictureList.value = res.records;});
};
const searchParams = ref(initSearchParams);
// 首次请求
loadData(initSearchParams);
const onSearch = (value: string) => {console.log(value);router.push({query: searchParams.value,});// 根据条件查询loadData(searchParams.value);
};
</script>
修改查询参数的获取,实现查询用户功能
因为用户只能根据用户名来查
坐标:src/pages/InderxPage.vue
<script setup lang="ts">
/*** 加载数据* @param params*/
const loadData = (params: any) => { const postQuery = {...params,searchText: params.text,};myAxios.post("/post/list/page/vo", postQuery).then((res: any) => {postList.value = res.records;});const pictureQuery = {...params,searchText: params.text,};myAxios.post("/picture/list/page/vo", pictureQuery).then((res: any) =>
{pictureList.value = res.records;});const userQuery = {...params,userName: params.text,};myAxios.post("/user/list/page/vo", userQuery).then((res: any) => {userList.value = res.records;});
};
</script>
存在的问题
- 请求数量过多,可能会受到浏览器的限制
- 请求不同的接口的参数可能不一致,增加前后端沟通成本
- 前端写调用多个接口的代码,重复代码
几种不同的业务场景
(目前在加载页面时,分别调用接口获取文章,图片,用户数据)
- 用户点击某个tab时,只调用这个tab的接口
- 针对聚合内容的网页,一个请求搞定
- 有可能要查询每个模块数据的总数,反馈给用户