【前言】
本文主要针对上一篇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的封装和组装。在构造框架时,很多时候需要深挖这些基础类。