RequestMappingHandlerMapping 实现通用导出

通用导出

通常一个系统存在很多导出, 是可以复用接口的, 但是却需要写多份, 有点麻烦

实现

通过url path 在RequestMappingHandlerMapping中找到对应的处理contoller, 利用反射调用实现通用导出


/**
 * 通用导出demo
 *
 * @author L
 * @date 2021/3/23
 * @since
 */
@AllArgsConstructor
@Api(tags = "导出测试")
@RestController
@RequestMapping("/export")
public class ExportController {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;


    @GetMapping
    @ApiOperation(value = "导出")
    public void queryList(@RequestParam String url, @RequestParam Map<String, Object> params,
                                             HttpServletResponse response) {
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
        Optional<RequestMappingInfo> anyMatch =
                handlerMethods.keySet().stream().filter(i -> i.getMethodsCondition().getMethods().contains(RequestMethod.GET) && i.getPatternsCondition().getPatterns().contains(url)).findAny();

        if(!anyMatch.isPresent()) {
            // 抛出业务异常
            throw new RuntimeException("请检查导出参数是否正确!");
        }
        RequestMappingInfo requestMappingInfo = anyMatch.get();
        HandlerMethod handlerMethod = handlerMethods.get(requestMappingInfo);
        Method method = handlerMethod.getMethod();
        
        // 通过spring 容器得到实际的Controller对象
        Object bean = BeanLocator.getBean(handlerMethod.getBeanType());
        Class<?>[] parameterTypes = method.getParameterTypes();

        // 如果是无参数则不需要分页
        if(ArrayUtil.isEmpty(parameterTypes)) {

            // 规定此接口返回值类型必须为统一返回包装对象
            ResultTemplate<?> invoke = ReflectUtil.invoke(bean, method);
            List<?> objects = invoke.get();
            // TODO: excelWriter.write(objects, sheet)
        }else {
            // 如果有参数,约定只有一个包装参数, 并且实现某个分页接口或父类
            Class<? extends PageParam> parameterType = (Class<? extends PageParam>)parameterTypes[0];
            PageParam query = JSONObject.parseObject(JSONObject.toJSONString(params), parameterType);
            int page = 1;
            final int size = 500;
            // 设置分页条数
            query.setSize(size);
            int total = 0;
            do {
                // 设置分页页数
                query.setIndex(page);
                ResultTemplate<?> resultTemplate = ReflectUtil.invoke(bean, method, query);
                // 总数
                //total = resultTemplate.getTotal();
                // 查询的数据
                List<?> objects = resultTemplate.get();
                // 加入流式导出的容器里
                // TODO: excelWriter.write(objects, sheet)

                page += 1;
            }while((page - 1) * size < total);
        }
        // 导出
        // TODO:  excelWriter.finish
    }

}

上一篇:java类反射获取成员方法


下一篇:跳转到代理对象关联的handler对象的invoke方法