SpringMVC自定义方法参数解析器 绑定mybatis分页PageBounds类型参数

By | 2016年3月2日

一、需求 

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";
}