如何无需手动构造数组,从WebSocket消息中转递请求参数?
问题描述
我有一个应用作用域Bean,通过OmniFaces Socket向通道推送JSON对象,最初的实现需要手动拆解JSON参数,再传递给PrimeFaces的remoteCommand,代码如下:
<o:socket channel="controllerEventChannel" onmessage="function(message) { var controllerId = message.controllerId; var deviceId = message.deviceId; var companyKey = message.companyKey; onMessage([ { name: 'controllerId', value: controllerId }, { name: 'deviceId', value: deviceId }, { name: 'companyKey', value: companyKey } ]); }" /> <p:remoteCommand name="onMessage" actionListener="#{controllerGroupDashboardBean.refreshListener()}" update="MainForm:showList MainForm:equipmentView MainForm:mapEquipmentView"/>
为了简化代码,我尝试直接将JSON对象传递给remoteCommand,修改后的代码如下:
<o:socket channel="controllerEventChannel" onmessage="function(message) { onMessage(message); }" /> <p:remoteCommand name="onMessage" actionListener="#{controllerGroupDashboardBean.refreshListener()}" update="MainForm:showList MainForm:equipmentView MainForm:mapEquipmentView"/>
但这种方式无法正常工作,后台通过以下代码提取参数时,所有参数都返回null,且参数Map中出现键为undefined、值为空字符串的项:
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); String companyKey = params.get("companyKey"); String controllerId = params.get("controllerId"); String deviceId = params.get("deviceId");
解决方案
方案1:适配PrimeFaces remoteCommand的参数格式
PrimeFaces的remoteCommand对应的JavaScript函数,要求传入的参数是包含name和value属性的对象数组,而非直接的JSON对象。可以用Object.entries()快速将JSON对象转换为符合要求的格式:
<o:socket channel="controllerEventChannel" onmessage="function(message) { // 将JSON对象转换为remoteCommand所需的参数数组 const params = Object.entries(message).map(([name, value]) => ({ name, value })); onMessage(params); }" /> <p:remoteCommand name="onMessage" actionListener="#{controllerGroupDashboardBean.refreshListener()}" update="MainForm:showList MainForm:equipmentView MainForm:mapEquipmentView"/>
修改后,后台原有的getRequestParameterMap()代码即可正常获取companyKey、controllerId、deviceId参数。
方案2:传递JSON字符串并后台解析
如果需要直接传递完整的JSON对象,可以将其序列化为字符串,后台再解析为对象(需引入JSON解析库,如Jackson):
前端代码
<o:socket channel="controllerEventChannel" onmessage="function(message) { // 将JSON对象转为字符串作为单个参数传递 onMessage([{ name: 'messageJson', value: JSON.stringify(message) }]); }" /> <p:remoteCommand name="onMessage" actionListener="#{controllerGroupDashboardBean.refreshListener()}" update="MainForm:showList MainForm:equipmentView MainForm:mapEquipmentView"/>
后台代码
import com.fasterxml.jackson.databind.ObjectMapper; import javax.faces.context.FacesContext; import java.util.Map; public void refreshListener() { Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); String messageJson = params.get("messageJson"); // 解析JSON字符串为Map或自定义实体类 ObjectMapper objectMapper = new ObjectMapper(); Map<String, String> messageMap = objectMapper.readValue(messageJson, Map.class); String companyKey = messageMap.get("companyKey"); String controllerId = messageMap.get("controllerId"); String deviceId = messageMap.get("deviceId"); // 后续业务逻辑处理 }
这种方式更适合参数较多或需要传递复杂对象的场景。
问题根源说明
直接传递JSON对象给remoteCommand函数时,PrimeFaces内部无法正确识别参数格式,遍历对象属性时出错,最终生成了无效的undefined键值对,导致后台无法获取有效参数。
内容的提问来源于stack exchange,提问作者Mats
相关产品推荐
相关产品推荐

