Spring Boot对接私有API实现分页功能技术求助(前端Thymeleaf+Bootstrap)
实现思路与示例
1. 模型层:适配私有API的分页返回结构
首先根据API返回的分页格式,创建两个核心模型类:一个是分页结果封装类,用来映射API返回的整体分页数据;另一个是业务数据模型类,映射每条搜索结果的具体字段。
示例代码:
// 业务数据模型,根据你的API返回的单条数据字段调整 public class SearchResultItem { private String id; private String title; // 其他字段... // Getter & Setter } // 分页结果封装类,完全匹配API返回的分页结构 public class ApiPageResponse<T> { private int currentPage; // 当前页码 private int totalPages; // 总页数 private int pageSize; // 每页条数 private long totalElements; // 总数据量 private List<T> content; // 当前页的数据列表 // Getter & Setter }
2. 控制器层:处理分页参数与API调用
控制器需要接收前端传递的搜索关键词和分页参数(当前页码page,可选每页条数size),调用私有API获取分页数据,再将分页信息和数据传递给前端视图。
核心分页跳转逻辑:
- 首页跳转:直接将页码设为
1,重新调用API - 下一页跳转:当前页码
+1,但不能超过totalPages - 末页跳转:直接将页码设为
totalPages - 边界处理:如果传入页码小于1,默认设为1;如果大于总页数,默认设为总页数
示例代码:
@Controller @RequestMapping("/search") public class SearchController { @Autowired private RestTemplate restTemplate; private static final String PRIVATE_API_URL = "https://your-private-api-domain/search"; private static final int DEFAULT_PAGE_SIZE = 10; // 默认每页条数 @GetMapping public String search(@RequestParam("keyword") String keyword, @RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "size", defaultValue = "10") int size, Model model) { // 1. 拼接API请求参数,注意匹配API的分页参数规则(比如部分API页码从0开始) UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(PRIVATE_API_URL) .queryParam("keyword", keyword) .queryParam("page", page - 1) // 若API用0-based页码则减1,1-based则直接传page .queryParam("size", size); // 调用私有API并解析返回结果 ResponseEntity<ApiPageResponse<SearchResultItem>> response = restTemplate.exchange( uriBuilder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference<ApiPageResponse<SearchResultItem>>() {} ); ApiPageResponse<SearchResultItem> pageData = response.getBody(); if (pageData == null) { // 处理API返回空的情况,构造空分页数据 pageData = new ApiPageResponse<>(); pageData.setContent(Collections.emptyList()); pageData.setTotalPages(0); } // 2. 修正当前页码,避免无效值 int currentPage = pageData.getCurrentPage() + 1; // 若API返回0-based页码,转成前端用的1-based int totalPages = pageData.getTotalPages(); currentPage = Math.max(1, Math.min(currentPage, totalPages)); // 3. 将分页数据传入模型 model.addAttribute("keyword", keyword); model.addAttribute("currentPage", currentPage); model.addAttribute("totalPages", totalPages); model.addAttribute("pageSize", size); model.addAttribute("searchResults", pageData.getContent()); return "search-result"; // 你的Thymeleaf视图名称 } }
3. 前端Thymeleaf + Bootstrap分页实现
利用Thymeleaf表达式渲染分页按钮,处理首页、上一页、下一页、末页的跳转逻辑,同时禁用无效状态的按钮(比如当前页是首页时,首页和上一页按钮禁用)。
示例代码(嵌入在Thymeleaf视图中):
<!-- 搜索结果列表 --> <div class="list-group"> <div th:each="item : ${searchResults}" class="list-group-item"> <h5 th:text="${item.title}"></h5> <!-- 其他字段展示 --> </div> </div> <!-- Bootstrap分页组件 --> <nav aria-label="Search results pagination"> <ul class="pagination justify-content-center"> <!-- 首页按钮 --> <li class="page-item" th:classappend="${currentPage == 1} ? 'disabled'"> <a class="page-link" th:href="@{/search(keyword=${keyword}, page=1, size=${pageSize})}">首页</a> </li> <!-- 上一页按钮 --> <li class="page-item" th:classappend="${currentPage == 1} ? 'disabled'"> <a class="page-link" th:href="@{/search(keyword=${keyword}, page=${currentPage - 1}, size=${pageSize})}">上一页</a> </li> <!-- 中间页码列表(显示当前页前后2页) --> <li class="page-item" th:each="pageNum : ${#numbers.sequence( Math.max(1, currentPage - 2), Math.min(totalPages, currentPage + 2) )}" th:classappend="${pageNum == currentPage} ? 'active'"> <a class="page-link" th:href="@{/search(keyword=${keyword}, page=${pageNum}, size=${pageSize})}" th:text="${pageNum}"></a> </li> <!-- 下一页按钮 --> <li class="page-item" th:classappend="${currentPage == totalPages} ? 'disabled'"> <a class="page-link" th:href="@{/search(keyword=${keyword}, page=${currentPage + 1}, size=${pageSize})}">下一页</a> </li> <!-- 末页按钮 --> <li class="page-item" th:classappend="${currentPage == totalPages} ? 'disabled'"> <a class="page-link" th:href="@{/search(keyword=${keyword}, page=${totalPages}, size=${pageSize})}">末页</a> </li> </ul> </nav>
关键注意事项
- 确认私有API的分页参数规则:是
page从0开始还是1开始,参数名是page还是pageNum,每页条数参数名是size还是pageSize,必须和API保持一致。 - 异常处理:调用私有API时要处理超时、返回错误码等情况,避免页面崩溃。
- 分页参数传递:确保搜索关键词在分页跳转时始终携带,避免跳页后丢失搜索条件。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

