【前言】
本文主要针对上一篇mybatis分页器实现一个不够合理的地方进行了优化。
原文链接 http://duanhengbin.iteye.com/blog/1998017
=================================================================================
今天研究了一下@RequestMapping 的文档,spring 提供了极其丰富的入参选择,利用HttpServletRequest 实现了一个简化 分页框架的方法。
先来看一下简化结果
【改造前】
@RequestMapping(value = "/user/users") public String list( @RequestParam(required = false, defaultValue = "1") int pageNo, @RequestParam(required = false, defaultValue = "5") int pageSize, @ModelAttribute("name") String name, @ModelAttribute("levelId") String levelId, @ModelAttribute("subjectId") String subjectId, Model model) { // 这里是“信使”诞生之地,一出生就加载了很多重要信息! Page page = Page.newBuilder(pageNo, pageSize, "users"); page.getParams().put("name", name); //这里再保存查询条件 page.getParams().put("levelId", levelId); page.getParams().put("subjectId", subjectId); model.addAttribute("users",userService.selectByNameLevelSubject( name, levelId, subjectId, page)); model.addAttribute("page", page); //这里将page返回前台 return USER_LIST_JSP; }
【改造后】
@RequestMapping(value = "/user/users") public String list( @ModelAttribute("name") String name, @ModelAttribute("levelId") String levelId, @ModelAttribute("subjectId") String subjectId, Model model, HttpServletRequest request) { Page page = Page.newBuilder2(5, request); // 第一个参数为每页行数 model.addAttribute("users",userService.selectByNameLevelSubject( name, levelId, subjectId, page)); model.addAttribute("page", page); //这里将page返回前台 return USER_LIST_JSP; }
newBuilder2()的结构要简洁得多,Controller入参无需再追加 pageNo 和pageSize了,也无需再将入参手动加入到page对象中,只是需要引入 HttpServletRequest对象。
另外,最大的好处在于,通用性增强了,将来请求接口发生变化时无需为分页修改代码。
现在看看 newBuilder2()的实现方法
/** * 从 HttpServletRequest 抽取请求入参来构造Page对象 */ public static Page newBuilder2(int pageSize, HttpServletRequest request){ Page page = new Page(); String uri = request.getRequestURI(); int pot= uri.lastIndexOf("/"); // 从uri中抽取右侧"/"后字符串作为的acton名 例子中对应的是 "users" page.setSearchUrl(uri.substring(pot+1)); // 这里是核心代码:遍历 request.getParameterMap() 提取请求参数,要注意数组的情况 for (Object key : request.getParameterMap().keySet()){ String[] args = request.getParameterValues(key.toString()); if (args.length>1){ page.getParamLists().put(key.toString(), convertParamArr(args,request)); }else{ page.getParams().put(key.toString(), convertIsoToUtf8(request.getParameter(key.toString()),request)); } } page.setPageSize(pageSize); // 这里是每页行数 if ( page.getParams().get("pageNo") == null ){ page.getParams().put("pageNo", "1"); // 当前页 原来缺省值设定改到了这里 }else{ page.setPageNo( Integer.parseInt(page.getParams().get("pageNo"))); // 点击分页标签时的请求 编辑totalRecord 项目(避免重复查询总记录数) page.setTotalRecord(Integer.parseInt(page.getParams().get("totalRecord"))); } return page; } /** * GET请求时,单个入参的转码处理 */ private static String convertIsoToUtf8(String strIn, HttpServletRequest request) { if (strIn == null || !request.getMethod().equalsIgnoreCase("get")) { return strIn; } try { String result = new String(strIn.getBytes("iso-8859-1"), "utf-8"); return result; } catch (UnsupportedEncodingException e) { return strIn; } } /** * GET请求时,数组型入参的转码处理 */ private static List<String> convertParamArr(String[] param, HttpServletRequest request) { List<String> list = Lists.newArrayList(); if (param != null) { for (String p : param) { String convertP = convertIsoToUtf8(p, request); if (!list.contains(convertP)) { list.add(convertP); } } } return list; }上面两个方法convertIsoToUtf8 和 convertParamArr 是为了处理Get请求时乱码问题。
【总结】
Spring提供了令人眼花缭乱的参数类型及相关注解方法来获取参数,但是本质上还是对 HttpSession, HttpServletRequest, HttpServletResponse等这些基础API的封装和组装。在构造框架时,很多时候需要深挖这些基础类。