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

本文先纠正数据源概念,再按「URL 传参 → 设计器声明参数 → Bean 方法接参」三层逐步拆解,最后给出选择标准和排查清单。看完你能自己搭出一条参数从前端到接口的完整链路。
一、先纠正概念:UReport2 只有三种数据源
这一步不搞清楚,后面的配置全是白忙。
1.1 三种数据源类型
| 类型 | 取数方式 | 参数怎么用 | 适合场景 |
|---|---|---|---|
| 数据库直连(JDBC) | 设计器里配驱动、URL、账号密码,直接写 SQL | SQL 里用 :paramName 命名参数 |
简单报表、数据就在库里 |
| Spring Bean 数据源 | 调 Spring 容器里某个 Bean 的方法拿数据 | 方法第三个 Map 参数 |
数据要走接口、要先加工 |
| 内置数据源 | 实现 BuildinDatasource 接口自己提供连接 |
仍然回到 SQL 命名参数 | 复用已有连接池、动态切库 |
所谓「API 数据源」,实际落地就是第二种:写一个 Spring Bean,在方法里用 RestTemplate 或 HttpClient 去调接口,把返回结果转成报表能吃的集合。
1.2 Bean 方法的签名是死规矩
Spring Bean 数据集对方法签名有硬要求——必须是三个参数,依次为 String、String、Map,否则设计器里的「选择方法」按钮根本列不出这个方法:
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这种能决定数据范围的参数,如果只依赖前端传值,用户改一下地址栏就能看到不该看的数据,权限校验必须在后端做。
三、方法二:设计器声明报表参数,配合命名参数
要让报表能被复用、能在页面上填条件查询,就得在设计器里正式声明参数。
操作步骤:
- 在设计器工具栏找到参数设置入口,新增一个参数;
- 填三项:参数名(要和 URL 里的键一致)、数据类型、默认值;
- 数据类型选对很关键——选了数字类型,引擎会帮你把字符串转成数字,SQL 里就不用再手动转;
- 声明完就有两种用法:在 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 内部补参数 | 后端上下文 | 高,前端绕不过 | 正式上线、涉及数据权限 |
三条判断标准:
- 参数会影响能看到哪些数据吗:会 → 一律走方法三,从后端上下文取,不接受前端传值;
- 报表要给别人反复用吗:要 → 在设计器里正式声明参数并设默认值,别只靠 URL 硬拼;
- 数据要不要先加工:接口返回是嵌套结构、要合并多个接口 → 走 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 的「API 数据源传参」,本质是一条从 URL 到 Java 方法的参数搬运链路。
要点带走:
- UReport2 只有数据库直连、Spring Bean、内置数据源三种,接口取数走 Spring Bean 这条路;
- Bean 数据集方法签名是死规矩:
String, String, Map三个参数,返回List,外部参数全在第三个 Map 里; - 联调用 URL 传参最快,复用要在设计器里声明参数,涉及权限的参数一律在 Bean 方法内部从后端上下文补齐。
下一步建议先写一个只返回两三行假数据的 Bean 方法,把参数在方法里打印出来确认链路通了,再去接真实接口。这样出问题时你能立刻判断是参数没进来,还是接口本身有问题。
延伸学习
想把报表相关的后端功底补齐,可以按这个顺序来:
- 想系统补 Java,Java 零基础入门到就业 这套配套课程从语法到项目串了一遍;
- 项目里要整合 Spring 生态,Spring Boot 简化后端开发 讲清了自动配置与起步依赖的思路;
- 拼预览地址时中文老是乱码,用 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 里解开再返回,不要指望在单元格表达式里处理多层结构。

免费 AI IDE



