使用MethodInterceptor和ResponseBodyAdvice做分页处理

目录

一、需求

二、代码实现

父pom文件

pom文件

配置文件

手动注册SqlSessionFactory(MyBatisConfig )

对象

实体类Users

 抽象类AbstractQuery 

查询参数类UsersQuery 

三层架构

 UsersController 

 UsersServiceImpl 

 UsersMapper 

 UsersMapper.xml

PageX 注解

MyResponseBodyAdvice 

构造返回对象泛型ResponseDto

拦截器PageMethodInterceptor

拦截器注入(PageMethodInterceptorConfig )

结果展示


一、需求

使用ResponseBodyAdvice做分页处理_骑着蜗牛打天下的博客-CSDN博客

在之前使用过用ResponseBodyAdvice来做分页处理,但是我们还可以结合着Aop中的MethodInterceptor拦截器对分页进一步封装;

使用ResponseBodyAdvice的做法:

使用MethodInterceptor和ResponseBodyAdvice做分页处理_第1张图片

 使用MethodInterceptor和ResponseBodyAdvice做分页处理_第2张图片

 这样的做法就是使用ResponseBodyAdvice去拦截controller层返回值,然后对返回的page类型的值进行封装成带有 total、pages、body等;

而本篇的目的是使用aop拦截器去拦截标注切点的方法然后对此方法进行拦截,拦截后就在拦截器内去做 PageHelper.startPage处理,然后在controller层返回时再使用ResponseBodyAdvice拦截,进一步的把数据给封装!

二、代码实现

使用MethodInterceptor和ResponseBodyAdvice做分页处理_第3张图片

父pom文件



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        
        2.2.5.RELEASE
         
    
    com.chensir
    springboot
    0.0.1-SNAPSHOT
    springboot
    springboot
    
        8
        5.8.3
        1.18.24
        2.0.0
    

    pom

    
        servlet
        spring-interceptor
        spring-aop
        spring-united-reslut
        spring-jdbc
        spring-mybatis
        spring-mybatis-pageX
    

    
        

           
            
                com.aliyun
                alibaba-dingtalk-service-sdk
                ${alibaba-sdk.version}
            

            
                cn.hutool
                hutool-all
                ${hutool.version}
            

            
                org.projectlombok
                lombok
                ${lombok.version}
            











        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


pom文件



    4.0.0
    
        com.chensir
        springboot
        0.0.1-SNAPSHOT
        ../pom.xml
    

    spring-mybatis-pageX

    
        
            org.springframework.boot
            spring-boot-starter-aop
        

        
            com.github.pagehelper
            pagehelper
            5.1.10
        

        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.1.4
        

        
            mysql
            mysql-connector-java
            runtime
        

        
            cn.hutool
            hutool-all
        

        
            org.projectlombok
            lombok
             true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter-test
            2.1.4
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    


配置文件

spring.datasource.url=jdbc:mysql://localhost/db1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

aop.MethodInterceptor.point = @annotation(com.chensir.annotation.PageX)

 手动注册SqlSessionFactory(MyBatisConfig )

package com.chensir.config;

import com.github.pagehelper.PageInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Configuration
@Slf4j
public class MyBatisConfig {

    @Autowired
    private ConfigurationCustomizer configurationCustomizer;
    /**
     * 自己注册SqlSessionFactory 目的是增强功能,添加分页插件
     * @param ds 代表数据源
     * @return
     * @throws Exception
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource ds) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        // 设置数据源
        factoryBean.setDataSource(ds);

        // 把分页插件设置到SqlSessionFactory插件库
        factoryBean.setPlugins(new PageInterceptor());
        // 配置mapper.xml地址
        factoryBean.setMapperLocations(resolveMapperLocations());

        //驼峰映射注册到SqlSessionFactory中
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configurationCustomizer.customize(configuration);
        factoryBean.setConfiguration(configuration);


        // 返回具体实例对象
        SqlSessionFactory bean = factoryBean.getObject();
        return bean;
    }


    /**
     * 开启驼峰映射
     * @return
     */
    @Bean
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }

    /**
     * 查找 xxxMapper.xml
     * @return
     */
    public Resource[] resolveMapperLocations() {
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        List mapperLocations = new ArrayList<>();
        mapperLocations.add("classpath*:mapper/*Mapper.xml");
//        mapperLocations.add("classpath*:com/meiwei/ping/dao/**/*Mapper.xml");
        List resources = new ArrayList();
        if (!CollectionUtils.isEmpty(mapperLocations)) {
            for (String mapperLocation : mapperLocations) {
                try {
                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
                    resources.addAll(Arrays.asList(mappers));
                } catch (IOException e) {
                    log.error("Get myBatis resources happened exception", e);
                }
            }
        }

        return resources.toArray(new Resource[resources.size()]);
    }

}

对象

实体类Users

@Data
public class Users {

    private Long id;

    private String name;

    private Integer age;

    private String sex;

    private String tel;

    // 数据库timestamp类型时间转化java规定格式时间
    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
    // 接受前端表单传递过来的字符串类型的时间数
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date createTime;

    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDateTime updateTime;
}

 抽象类AbstractQuery 

public abstract class AbstractQuery implements Serializable {

    private Integer pageNum = 1;

    private Integer pageSize = 10;

    public Integer getPageNum() {
        return pageNum;
    }

    public void setPageNum(Integer pageNum) {
        this.pageNum = pageNum;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }
}

查询参数类UsersQuery 

@Data
public class UsersQuery extends AbstractQuery {

    private Long id;

    private String name;

    private Integer age;

    private String sex;

    private String tel;
}

三层架构

 UsersController 

@RestController
public class UsersController {

    @Resource
    private UsersService usersService;

    @PostMapping("/pageQuery")
    public List selectUsersByPageQuery(@RequestBody UsersQuery usersQuery){

        // 使用MethodInterceptor进行分页 @PageX为切点,使用地方开启分页处理
        List usersList = usersService.selectUsersByPageQuery(usersQuery);
        return usersList;
    }

    @GetMapping("/demo1")
    public List selectUsersList(Integer pageNum,Integer pageSize) {

        // 启用分页,查询第一页,每页3条
        PageHelper.startPage(pageNum,pageSize);
        //-------------PageInfo方式---------------
//        PageInfo usersPageInfo = new PageInfo<>(usersService.selectUsersList());
//        return usersPageInfo;
        //-------------PageInfo方式---------------

        //-------------Page方式---------------
//        List users = usersService.selectUsersList();
//        Page page = (Page) users;
//        int pages = page.getPages();
//        long total = page.getTotal();
//
//
//        Map pageMap = new HashMap<>();
//        pageMap.put("pages",pages);
//        pageMap.put("total",total);
//        pageMap.put("items",users);
//        return pageMap;
        //-------------Page方式---------------


        //-----------使用ResponseBodyAdvice------------
        List users = usersService.selectUsersList();
        return users;
        //-----------使用ResponseBodyAdvice------------
    }

    @GetMapping("/demo2")
    public Users selectUsers(){
        Users users = usersService.selectUsers();
        return users;
    }

    @GetMapping("/demo3")
    public Map selectUsersToMap(){
        return usersService.selectUsersToMap();
    }
}

 UsersServiceImpl 

@Service
public class UsersServiceImpl implements UsersService {

    @Resource
    private UsersMapper usersMapper;

    @Override
    public List selectUsersList() {
        return usersMapper.selectUsersList();
    }

    @Override
    public Users selectUsers() {
        return usersMapper.selectUsers();
    }

    @Override
    public Map selectUsersToMap() {
        return usersMapper.selectUsersToMap();
    }

    @Override
    public List selectUsersByPageQuery(UsersQuery usersQuery) {
        return usersMapper.selectUsersByPageQuery(usersQuery);
    }
}

 UsersMapper 

@Mapper
public interface UsersMapper {

    List selectUsersList();

    Users selectUsers();

    Map selectUsersToMap();

    //此接口带有@PageX 拦截器会拦截它 然后做分页处理
    @PageX
    List selectUsersByPageQuery(UsersQuery usersQuery);
}

 UsersMapper.xml






    
    
    
    

 PageX 注解

注解来作为切点,使用时,在配置文件中先配置,注入@bean时使用@value取值,然后对带有此注解的方法进行扫描拦截;

@Deprecated
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PageX {
}

MyResponseBodyAdvice 

package com.chensir.advice;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

// 拦截范围为 com.chensir.controller包下内容
@RestControllerAdvice(basePackages = {"com.chensir.controller"})
public class MyResponseBodyAdvice implements ResponseBodyAdvice {
    // 是否开启拦截 true开启 false不开启
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        // 此处应该改为true,否则除了异常外 走到此处为false后就直接返回,也不再继续往下走了!
        return true;
    }

    // 如果接口返回异常就在此处拦截 进行封装;value = Exception.class 对所有的异常均拦截!
    @ExceptionHandler(value = Exception.class)
    public Object defaultErrorHandler(HttpServletRequest req, Exception ex){
        ResponseDto responseDto = new ResponseDto<>();
        responseDto.setCode(501);
        responseDto.setMessage(ex.getMessage());
        return responseDto;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        ResponseDto responseDto = new ResponseDto<>();
        // 先用hutool定义为null
        String message = StrUtil.EMPTY;
        responseDto.setCode(0);
        responseDto.setMessage(message);

        if (body instanceof Page){
            Page page = (Page) body;
            int pages = page.getPages();//总页数
            long total = page.getTotal();//总条数
            Dict dict = Dict.create()
                    .set("total",total)
                    .set("pages",pages)
                    .set("item",body);
            responseDto.setData(dict);
        }else {
            responseDto.setData(body);
        }

        // 如果是string类型就用json封装一下;
        if (aClass == StringHttpMessageConverter.class) {
            return JSONUtil.toJsonStr(responseDto);
        } else {
            return responseDto;
        }

    }
}
 
  

构造返回对象泛型ResponseDto

// 泛型
@Data
public class ResponseDto implements Serializable {

    // 返回码(内部拟定)
    private int code;

    // 返回信息
    private String message;

    private T data;
}

拦截器PageMethodInterceptor

package com.chensir.interceptor;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.chensir.domain.AbstractQuery;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;


@Slf4j
public class PageMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 获取方法
        Method method = invocation.getMethod();
        //获取参数
        Object[] arguments = invocation.getArguments();

        //获取第一个参数
        Object arg0 = arguments[0];

        if (arg0 instanceof AbstractQuery) {
            AbstractQuery query = (AbstractQuery) arg0;
            Integer pageNum = query.getPageNum();//参数 第几页
            Integer pageSize = query.getPageSize();//参数 每页多少条

            if (ObjectUtil.isNotEmpty(pageNum) && ObjectUtil.isNotEmpty(pageSize)) {
                //走到这肯定要分页了
                PageHelper.startPage(pageNum,pageSize);
            }
        }

        //获取返回值
        Object value = invocation.proceed();
        log.info("方法:{},参数:{},返回值:{}", method.getName(), JSONUtil.toJsonStr(arguments), value);
        return value;
    }
}

拦截器注入(PageMethodInterceptorConfig )

advisor.setExpression(point); 拦截切点为@PageX的注解

@Configuration
public class PageMethodInterceptorConfig {

    @Value("${aop.MethodInterceptor.point}")
    private String point;

    @Bean
    public AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor(){
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setAdvice(new PageMethodInterceptor());
        advisor.setExpression(point);
        return advisor;
    }
}

结果展示

使用MethodInterceptor和ResponseBodyAdvice做分页处理_第4张图片

 

使用MethodInterceptor和ResponseBodyAdvice做分页处理_第5张图片

 

你可能感兴趣的:(java,java,开发语言,spring,boot,spring)