很多项目在开发的时候都会遇到分页的问题,一般分页主要用到两个参数page和limit,page是第几页,limit是请求多少条数据。而一般在请求数据库的时候我们用不到page参数,用到的是用page和limit计算出来的index参数。index的计算方法为 index=(page-1)*limit;。如果在搭建的框架没有任何措施的时候,那么page和limit参数需要我们手动写代码去判断其是否合法(page和limit必须大于0),并且index需要我们自己去计算。这时我们就可以自定义一个参数解析器,在请求接口之前让框架帮我们完成判断和计算的任务,我们只需要写一个注解即可。
自定义分页注解
这个注解用在controller的page参数上,下方会有示例。
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义分页注解
* @author Jiajiajia
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Page {
}
自定义参数解析器
如何封装请求参数,都可以这个解析器中按照我们的意愿完成,前提是controller的参数上必须携带Page注解。
import com.dzqc.dormitorycommon.entity.PageParam;
import javax.servlet.http.HttpServletRequest;
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;
/**
* 自定义分页参数解析器
* @author Jiajiajia
*/
public class RequestPageHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
//绑定注解标签
return methodParameter.hasParameterAnnotation(Page.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
String page=request.getParameter("page");
if(page==null)
throw new PageException("missing paging parameters page");
String limit=request.getParameter("limit");
if(limit==null)
throw new PageException("missing paging parameters limit");
Integer p = null;
Integer l = null;
try {
p = Integer.valueOf(page);
if(p<=0)
throw new PageException("page 参数必须大于0");
l = Integer.valueOf(limit);
if(l<=0)
throw new PageException("limit 参数必须大于0");
} catch (Exception e) {
throw new PageException("分页参数错误");
}
return new PageParam(p,l);
}
}
封装分页参数PageParam类
/**
* 参数接受
* @author 硅谷探秘者(jia)
*/
public class PageParam {
private Integer page;
private Integer limit;
private Integer index;
public PageParam(int page,int limit) {
this.page=page;
this.limit=limit;
this.index=(page-1)*limit;
}
//get set方法省略
}
自定义异常类
/**
* 自定义分页异常
* @author Jiajiajia
*/
public class PageException extends Exception{
private static final long serialVersionUID = 1L;
public PageException(String msg) {
super(msg);
}
}
最后完成配置自定义参数解析器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new RequestPageHandlerMethodArgumentResolver());
}
}
测试
上述配置完成以后 写一个测试的方法:注意参数加了@Page注解
@RequestMapping("test")
@ResponseBody
public Map<String,Object> test(@Page PageParam page) {
System.out.println(page);//打印分装好的分页请求数据
Map<String, Object> map=new HashMap<String, Object>();
map.put("are you ok?","ok!");
return map;
}
正常请求时,如:.../test?page=2&limit=10 打印如下:PageParam [page=2, limit=10, index=10]并且正常返回数据,当缺失某个参数的时候如:.../test?page=2,就会报如下错误:

这样返回错误信息似乎不太雅观。接下来就写一个配置,如果出现PageException异常的时候,将其拦截,并且返回json格式的提示,配置如下。
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 自定义异常捕获
* @author Jiajiajia
*/
@RestControllerAdvice
public class PageExceptionHandler {
@ExceptionHandler(value=PageException.class)
public Object handleMyException(PageException e, HttpServletRequest request) {
Map<String,Object> map=new HashMap<String, Object>();
map.put("code",500);
map.put("msg",e.getMessage());
return map;
}
}
这样再报错的时候就会返回json数据:

经过上述配置以后,再写分页接口的时候,只需要在controller中加 @Page PageParam page 即可,参数的判断和计算都由框架完成。