一、需求
mybatis整合了分页插件mybatis-paginator之后,我们需要从构造一个PageBounds类传入Mapper完成分页,构造PageBounds需要一些参数,比如当前页,分页尺寸,排序字段,排序参数等。这些参数我们可以通过request.getParameter()方式获取:
int page = null==request.getParameter("page") ? 1 : request.getParemeter("page"); //..... PageBounds pageBounds = new PageBounds(page,limit);
也可以通过如下方式,对每个参数都通过参数绑定的形式获取:
@RequestMapping(value = { "/index.action", "/list.action" }) @RequiresAuthentication public String list(Model model, @RequestParam(required = false, defaultValue = "1") int page, @RequestParam(required = false, defaultValue = "15") int limit, @RequestParam(required = false) String sort, @RequestParam(required = false) String dir) { PageBounds pageBounds = new PageBounds(page, limit); PageList couponList = (PageList) couponService.findByPage(pageBounds); model.addAttribute("couponList", couponList); model.addAttribute("page", couponList.getPaginator()); return "coupon/list"; }
但是,一个项目中,我们会有很多这样的分类,比如:产品列表分页,订单分页分页,会员列表分页。如果我们每个模块都用上面的方式去完成PageBounds的实例化,不仅影响代码的编写效率和可读性,也会造成很多代码的重复!
所以此处,我们可以使用HandlerMethodArgumentResolver 自定义解析器实现请求参数绑定,已达到自动注入PageBounds类型参数的效果:
@RequestMapping(value = { "/index.action", "/list.action" }) @RequiresAuthentication public String list(Model model, PageBounds pageBounds) { PageList couponList = (PageList) couponService.findByPage(pageBounds); model.addAttribute("couponList", couponList); model.addAttribute("page", couponList.getPaginator()); return "coupon/list"; }
二、实现
2.1、自定义一个解析器,来解析PageBounds类型参数,代码中已注解说明:
package com.renyiwei.web.resolver; import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import com.github.miemiedev.mybatis.paginator.domain.PageBounds; /** * 自定义PageBounds方法参数解析器 * * @author RenYiwei * */ public class PageBoundsMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { // 获取参数类型 Class<?> paramType = parameter.getParameterType(); // 如果该参数类型是PageBounds类自身或者子类,则返回true,表示这个解析器可以解析此类型 return PageBounds.class.isAssignableFrom(paramType); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { // 在此处通过request.getParameter()方式获取分页所需参数 // 获取页码 这些字段可以通过自定义注解来指定 int page = null == webRequest.getParameter("page") ? 1 : new Integer(webRequest.getParameter("page")); // 获取分页尺寸 int limit = null == webRequest.getParameter("limit") ? 15 : new Integer(webRequest.getParameter("limit")); // 创建PageBounds实例 这里还可以传入排序方式等参数,构造更完美的PageBounds实例,此处为了简洁就以简单的为例 PageBounds pageBounds = new PageBounds(page, limit); // 返回PageBounds实例,这个pageBounds就会以方法形参的方式传入控制器类的方法中 return pageBounds; } }
上面的PageBounds只是简单地构造了一下,还可以参入排序方式等参数来构造更完善的实例。
另外,也可以自定义注解,注解在方法参数中,来指定参数名称,默认值等,再通过methodParameter获取注解来读取自定义的值,这里就不作介绍了。
2.2、申明自定方法参数解析器,在springmvc的配置文件中配置,我的配置文件是spring-mvc.xml:
<mvc:annotation-driven validator="validator" conversion-service="conversion-service"> <mvc:argument-resolvers> <bean class="com.renyiwei.web.resolver.PageBoundsMethodArgumentResolver" /> </mvc:argument-resolvers> </mvc:annotation-driven>
2.3、在控制器方法中指定参数为PageBounds类型,在调用service时可以直接传入:
@RequestMapping(value = { "/index.action", "/list.action" }) @RequiresAuthentication public String list(Model model, PageBounds pageBounds) { PageList couponList = (PageList) couponService.findByPage(pageBounds); model.addAttribute("couponList", couponList); model.addAttribute("page", couponList.getPaginator()); return "coupon/list"; }