UReport2 的 API 数据源怎样传参?3 种常用写法与排查思路

编程狮(w3cschool.cn) 2026-08-24 17:58:14 浏览数 (33)
反馈

UReport2 的 API 数据源怎样传参?答案很简单——UReport2 里并没有一种叫「API 数据源」的独立类型,对接 HTTP 接口要走 Spring Bean 数据源,外部参数最终会汇进 Bean 方法固定的第三个 Map 参数里,你在方法内部取出来再拼接口请求即可。很多人卡在这里,是因为在设计器的数据源列表里翻了半天也没找到「API」这一项,于是怀疑版本不对或者少装了插件。其实是概念对不上:UReport2 只提供三种数据源,接口调用属于「用 Java 代码自己取数」的那一类。这篇文章,编程狮把参数从哪儿进、怎么落到方法里、常见报错怎么查,一次讲清。

UReport2 的 API 数据源怎样传参?

本文先纠正数据源概念,再按「URL 传参 → 设计器声明参数 → Bean 方法接参」三层逐步拆解,最后给出选择标准和排查清单。看完你能自己搭出一条参数从前端到接口的完整链路。

一、先纠正概念:UReport2 只有三种数据源

这一步不搞清楚,后面的配置全是白忙。

1.1 三种数据源类型

类型 取数方式 参数怎么用 适合场景
数据库直连(JDBC) 设计器里配驱动、URL、账号密码,直接写 SQL SQL 里用 :paramName 命名参数 简单报表、数据就在库里
Spring Bean 数据源 调 Spring 容器里某个 Bean 的方法拿数据 方法第三个 Map 参数 数据要走接口、要先加工
内置数据源 实现 BuildinDatasource 接口自己提供连接 仍然回到 SQL 命名参数 复用已有连接池、动态切库

所谓「API 数据源」,实际落地就是第二种:写一个 Spring Bean,在方法里用 RestTemplateHttpClient 去调接口,把返回结果转成报表能吃的集合。

1.2 Bean 方法的签名是死规矩

Spring Bean 数据集对方法签名有硬要求——必须是三个参数,依次为 StringStringMap,否则设计器里的「选择方法」按钮根本列不出这个方法:

package cn.w3cschool.report;


import java.util.List;
import java.util.Map;


public class W3cschoolReportBean {


    /**
     * dsName      数据源名称
     * datasetName 数据集名称
     * parameters  外部传入的参数,全部在这里
     */
    public List<Map<String, Object>> loadReportData(
            String dsName, String datasetName, Map<String, Object> parameters) {
        return null;
    }
}

返回值只支持两种:List<Map<String, Object>>,或者一个普通 POJO 的 List。记住这两条约束,参数传递的整条链路就清楚了——你要做的事,就是让外部参数正确地出现在 parameters 这个 Map 里。设计器各个面板的位置和数据集配置细节,可以对照 Ureport2 教程 边看边配。

二、方法一:URL 上带参数,最快见效

调试阶段最省事的做法:直接把参数挂在预览地址后面。

UReport2 的预览地址形如下面这样,_u 指向报表文件,其余的查询参数会被原样收进 parameters Map:

# 基本形式:_u 指定报表文件,后面追加业务参数
http://localhost:8080/ureport/preview?_u=file:w3cschool-order.ureport.xml&year=2026&deptId=18


# 中文参数必须先做 URL 编码,否则到后端会变乱码
http://localhost:8080/ureport/preview?_u=file:w3cschool-order.ureport.xml&dept=%E7%BC%96%E7%A8%8B%E7%8B%AE

进到 Bean 方法里就是这样取:

public List<Map<String, Object>> loadOrderData(
        String dsName, String datasetName, Map<String, Object> parameters) {
    String year = (String) parameters.get("year");
    Object deptId = parameters.get("deptId");
    // 拿到参数后去调你自己的业务接口
    String api = "https://api.internal.example.com/orders?year=" + year + "&deptId=" + deptId;
    // ... 发请求、解析 JSON、组装成 List<Map> 返回
    return null;
}

要注意三件事:URL 里传过来的值默认都是字符串,需要数字或日期得自己转;参数名要和你在方法里 get 的键完全一致,大小写敏感;中文、空格、& 这类字符必须先做 URL 编码再拼进地址。

⚠️ 注意:URL 传参适合联调,别直接暴露给最终用户。像 deptId 这种能决定数据范围的参数,如果只依赖前端传值,用户改一下地址栏就能看到不该看的数据,权限校验必须在后端做。

三、方法二:设计器声明报表参数,配合命名参数

要让报表能被复用、能在页面上填条件查询,就得在设计器里正式声明参数。

操作步骤:

  1. 在设计器工具栏找到参数设置入口,新增一个参数;
  2. 填三项:参数名(要和 URL 里的键一致)、数据类型默认值
  3. 数据类型选对很关键——选了数字类型,引擎会帮你把字符串转成数字,SQL 里就不用再手动转;
  4. 声明完就有两种用法:在 SQL 数据集里写成命名参数,或者在单元格里直接引用。

SQL 数据集里的写法是冒号加参数名:

SELECT dept_name, order_month, SUM(amount) AS total
FROM w3cschool_order
WHERE order_year = :year
  AND dept_id = :deptId
GROUP BY dept_name, order_month

单元格里想把参数显示出来(比如标题写成「2026 年 XX 部门订单表」),用表达式引用:${year}

声明参数还有一个隐性好处:默认值兜底。用户没传 year 时,引擎会用你设的默认值,不至于因为参数为空直接查空或者报错。这一点在把报表挂到菜单上给别人用时特别重要。

💡 小提示:参数名建议统一用小驼峰且不带中文,deptId 而不是 部门ID。中文参数名在 URL 里要编码、在 SQL 里容易踩引号的坑,得不偿失。

四、方法三:Bean 方法里补参数,不全靠前端传

真实项目里,有些参数根本不该由前端传——比如当前登录人、所属租户、数据权限范围。这类参数正确的做法是在 Bean 方法内部补齐。

思路是:parameters 里只放业务筛选条件(年份、部门),身份类参数从后端上下文里取,两者合并后再去调接口:

@Component("w3cschoolReportBean")
public class W3cschoolReportBean {


    @Autowired
    private RestTemplate restTemplate;


    public List<Map<String, Object>> loadOrderData(
            String dsName, String datasetName, Map<String, Object> parameters) {


        Map<String, Object> query = new HashMap<>(parameters);
        // 身份类参数由后端补,前端改地址栏也绕不过去
        query.put("tenantId", CurrentUserHolder.getTenantId());
        query.put("operator", CurrentUserHolder.getUserId());


        ResponseEntity<W3cschoolApiResult> resp = restTemplate.postForEntity(
                "https://api.internal.example.com/report/orders", query, W3cschoolApiResult.class);


        return resp.getBody() == null ? Collections.emptyList() : resp.getBody().getRows();
    }
}

这种写法有三个好处:权限安全,关键参数不经前端;支持 POST,参数多、结构复杂时不受 URL 长度限制;方便加工,接口返回的嵌套 JSON 可以在这里拍平成报表要的扁平结构。

Bean 方法里会大量用到集合、流、日期这些基础 API,写得手生了可以翻 Java 速查手册 现查现用。

五、三种写法怎么选,附排查清单

写法 参数从哪来 安全性 适合阶段
URL 传参 地址栏查询参数 低,可被篡改 本地联调、快速验证
设计器声明参数 声明 + URL 或页面表单 中,有类型和默认值约束 报表要给多人复用
Bean 内部补参数 后端上下文 高,前端绕不过 正式上线、涉及数据权限

三条判断标准:

  1. 参数会影响能看到哪些数据吗:会 → 一律走方法三,从后端上下文取,不接受前端传值;
  2. 报表要给别人反复用吗:要 → 在设计器里正式声明参数并设默认值,别只靠 URL 硬拼;
  3. 数据要不要先加工:接口返回是嵌套结构、要合并多个接口 → 走 Bean 数据源在 Java 里处理,别指望在单元格表达式里硬凑。

五个高频问题的排查顺序:

  • 设计器里选不到方法:99% 是签名不对。三个参数、顺序是 String, String, Map,一个都不能少,返回值也必须是 List
  • parameters 拿到的是空的:先确认 URL 上参数名和 get 的键完全一致,再确认参数没被中间的网关或代理过滤掉;
  • 参数取到了但 SQL 查不出数:多半是类型问题,URL 传过来是字符串,跟数字列比较时先在设计器里把参数类型声明对;
  • 中文参数变乱码:预览地址里的中文没做 URL 编码,或者容器的请求编码没设成 UTF-8,两处都要检查;
  • Bean 找不到(NoSuchBean):数据源里填的是 Bean 的 ID,注意 @Component("xxx") 里写的名字和设计器里填的要一致。

Bean 注册不上、注入拿到 null 这类问题,多半出在包扫描范围和配置类的位置上,排查思路可以参考 SpringBoot 那些事 里的自动配置章节。

UReport2 参数从哪来?

总结

UReport2 的「API 数据源传参」,本质是一条从 URL 到 Java 方法的参数搬运链路。

要点带走:

  • UReport2 只有数据库直连、Spring Bean、内置数据源三种,接口取数走 Spring Bean 这条路;
  • Bean 数据集方法签名是死规矩:String, String, Map 三个参数,返回 List,外部参数全在第三个 Map 里;
  • 联调用 URL 传参最快,复用要在设计器里声明参数,涉及权限的参数一律在 Bean 方法内部从后端上下文补齐。

下一步建议先写一个只返回两三行假数据的 Bean 方法,把参数在方法里打印出来确认链路通了,再去接真实接口。这样出问题时你能立刻判断是参数没进来,还是接口本身有问题。

延伸学习

想把报表相关的后端功底补齐,可以按这个顺序来:

  1. 想系统补 Java,Java 零基础入门到就业 这套配套课程从语法到项目串了一遍;
  2. 项目里要整合 Spring 生态,Spring Boot 简化后端开发 讲清了自动配置与起步依赖的思路;
  3. 拼预览地址时中文老是乱码,用 URL 编码解码工具 先把参数转成编码再贴进地址栏。

常见问题

Q:设计器的数据源里为什么找不到「API 数据源」这一项?
A:因为它本来就不存在。UReport2 只提供数据库直连、Spring Bean、内置数据源三种,调接口属于 Spring Bean 这一类,你需要自己写一个 Bean 方法去请求接口并返回集合。

Q:Bean 方法的三个参数能不能只写一个 Map?
A:不能。引擎按固定签名反射调用,缺参数会导致设计器里根本列不出这个方法。前两个参数用不上也必须留着,方法体里忽略即可。

Q:参数太多,URL 拼不下怎么办?
A:把参数改成在 Bean 方法内部组装。前端只传少量筛选条件,其余从后端上下文或配置里取,然后用 POST 请求业务接口,就不受 URL 长度限制了。

Q:接口返回的是嵌套 JSON,报表读不出来怎么处理?
A:在 Bean 方法里先拍平。报表要的是 List<Map>List<POJO> 这种一行一条的扁平结构,嵌套层级要在 Java 里解开再返回,不要指望在单元格表达式里处理多层结构。

0 人点赞