Web应用添加「按流派搜索」功能异常,请求排查代码问题
问题排查与修复:流派筛选不生效返回全部数据
核心问题分析
你的代码存在三个关键问题导致流派筛选失效:
1. 数据库查询逻辑错误
findByKeyword方法中同时执行了关键词查询和流派查询,并将两个结果集的所有数据合并返回。即使选择了流派,也会先返回所有匹配关键词(关键词为空时是全部数据)的内容,再追加流派匹配的内容,最终结果就是全部数据。
2. 未处理流派参数为空的情况
Servlet中只处理了word为空的情况,没处理genre为空的场景。当用户未选择流派时,genre为null,传到DAO层后会生成Genre like "%null%"的查询条件,这显然不符合预期。
3. JSP按钮Value写法冗余且易出错
按钮的value属性使用<%= genre = "Fantasy" %>这种赋值表达式完全没必要,直接写固定字符串即可,否则如果genre变量未提前声明还会引发编译错误。
修复步骤
步骤1:修正JSP表单按钮
把按钮的value改为直接写流派名称,去掉冗余的JSP赋值(同时补充搜索框输入项,确保关键词功能正常):
<form action="ItemListController"> <div class="btn-group me-2" role="group" aria-label="Genres"> <button class="btn btn-outline-secondary" type="submit" name="gnr" value="Fantasy">Fantasy</button> <button class="btn btn-outline-secondary" type="submit" name="gnr" value="Action">Action</button> <button class="btn btn-outline-secondary" type="submit" name="gnr" value="FPS">FPS</button> </div> <input type="text" name="keyword" placeholder="搜索游戏..." value="${word}"> <button type="submit">搜索</button> </form>
步骤2:修正Servlet的参数处理
补充genre为空的处理,确保空参数不会干扰查询:
@WebServlet("/ItemListController") public class ItemListController extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String word = request.getParameter("keyword"); String genre = request.getParameter("gnr"); // 处理空参数 if (word == null) { word = ""; } if (genre == null) { genre = ""; } ItemModel im = new ItemModel(); List<Item> items = im.findByKeyword(getServletContext(), word, genre); request.setAttribute("items", items); request.setAttribute("word", word); request.setAttribute("genre", genre); request.getRequestDispatcher("/itemListView3.jsp").forward(request, response); } }
步骤3:重构DAO层的查询逻辑
根据word和genre的实际值动态生成SQL,实现关键词和流派的组合筛选,而不是分开查询再合并:
public List<Item> findByKeyword(ServletContext context, String word, String genre) { List<Item> result = new ArrayList<>(); Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { Class.forName("org.sqlite.JDBC"); String url = "jdbc:sqlite:" + context.getRealPath("WEB-INF/webapp.db"); conn = DriverManager.getConnection(url); // 动态构建SQL条件,1=1用于简化条件拼接 StringBuilder sqlBuilder = new StringBuilder("select * from games where 1=1"); List<Object> params = new ArrayList<>(); // 添加关键词筛选条件 if (!word.isEmpty()) { sqlBuilder.append(" and GameName like ?"); params.add("%" + word + "%"); } // 添加流派筛选条件 if (!genre.isEmpty()) { sqlBuilder.append(" and Genre like ?"); params.add("%" + genre + "%"); } sqlBuilder.append(" order by GameID"); stmt = conn.prepareStatement(sqlBuilder.toString()); // 批量设置参数 for (int i = 0; i < params.size(); i++) { stmt.setObject(i + 1, params.get(i)); } rs = stmt.executeQuery(); // 封装结果集 while (rs.next()) { Item item = new Item(); item.setItemId(rs.getInt("GameID")); item.setItemName(rs.getString("GameName")); item.setGenre(rs.getString("Genre")); item.setDescription(rs.getString("Description")); item.setImage(rs.getString("GameCover")); item.setPrice(rs.getInt("Price")); item.setLink(rs.getString("Link")); result.add(item); } } catch (Exception e) { e.printStackTrace(); } finally { // 统一关闭数据库资源,避免连接泄漏 try { if (rs != null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (Exception e) { e.printStackTrace(); } } return result; }
额外优化说明
- 资源管理:改用
finally块统一关闭数据库连接、语句和结果集,避免内存泄漏。 - 组合筛选:现在支持同时使用关键词和流派筛选,比如搜索"war"并选择"Action",会返回名称含war且流派为Action的游戏,符合常规搜索需求。
内容的提问来源于stack exchange,提问作者furkanzdm
相关产品推荐
相关产品推荐

