简体   繁体   English

使用@ResourceMapping和@ModelAttribute在Spring Portlet Controller中访问RequestBody

[英]Access RequestBody inside Spring Portlet Controller using @ResourceMapping and @ModelAttribute

My problem is similar to the following posts: JSON ajax POST to Spring Portlet Controller @ResourceMapping conversion issue and @ResourceMapping that accepts JSON from Ajax request 我的问题类似于以下帖子: JSON ajax POST到Spring Portlet Controller @ResourceMapping转换问题@ResourceMapping接受来自Ajax请求的JSON

I have tried the Tipps there, but without success. 我在那儿尝试过Tipps,但没有成功。 I have the following Technologies in place: 我拥有以下技术:

  1. liferay-portal 6.2 CE 救生门6.2 CE
  2. custom portlet-plugin for liferay based on spring 3.0.7 基于spring 3.0.7的liferay定制portlet-plugin
  3. kendo-ui for jsp kendo-ui for jsp

On the client-side I produce a stringified json-Object with the functionality of kendo-ui for jsp, which is submitted in the request body. 在客户端,我生成了一个带有kendo-ui for jsp功能的字符串化json-Object,该对象在请求正文中提交。 Currently it contains just some filter-parameters (but it can also contain additional parameters for server-side paging, sorting, grouping,..). 当前,它仅包含一些过滤器参数(但还可以包含用于服务器端分页,排序,分组等的其他参数)。

In Firefox developer tools the request-body (payload) looks like following: 在Firefox开发人员工具中,请求正文(有效负载)如下所示:

{
"filter" : {
    "logic" : "and",
    "filters" : [{
            "field" : "name",
            "value" : ""
        }, {
            "field" : "city",
            "value" : ""
        }, {
            "field" : "zip",
            "value" : ""
        }, {
            "field" : "country",
            "value" : ""
        }
    ]
  }
}

On the server-side I have a POJO for that structure. 在服务器端,我有一个用于该结构的POJO。 I tested this in a Spring Web MVC Servlet enviroment with success. 我在Spring Web MVC Servlet环境中成功进行了测试。 Using @RequestBody and Jackson the deserialization of the JSON Object works. 使用@RequestBodyJackson可以反序列化JSON对象。

Working in liferay-portlet enviroment I cannot use @RequestBody and httpServletRequest . liferay-portlet环境中工作,我无法使用@RequestBodyhttpServletRequest

The Controller looks like following: 控制器如下所示:

@ResourceMapping(value = "test")
public void searchProviderTest(ResourceRequest request, ResourceResponse response,
        @ModelAttribute("filter") DataSourceRequest dataSourceRequest) {

    LOGGER.info(">>>>>> JsonOjekt per Parameter übergeben:  " + request.getParameter("filter"));
    LOGGER.info(">>>>>>>> DatasourceRequest: " + dataSourceRequest);

}

The DataRequestObject has no values. DataRequestObject没有值。 I see all the attributes, but they are empty. 我看到了所有属性,但是它们是空的。 And there is no request parameter "filter" (as exspected) 并且没有请求参数“ filter”(如预期)

Here is my DataSourceRequest-Object (abstract): 这是我的DataSourceRequest-Object(抽象):

public class DataSourceRequest {
private int page;
private int pageSize;
private int take;
private int skip;
private List<SortDescriptor> sort;
private List<GroupDescriptor> group;
private List<AggregateDescriptor> aggregate;
private HashMap<String, Object> data;

private FilterDescriptor filter;

public DataSourceRequest() {
    filter = new FilterDescriptor();
    data = new HashMap<String, Object>();
}

...(getters and setters)

public static class FilterDescriptor {
    private String logic;
    private List<FilterDescriptor> filters;
    private String field;
    private Object value;
    private String operator;
    private boolean ignoreCase = true;

    public FilterDescriptor() {
        filters = new ArrayList<FilterDescriptor>();
    }

    ...(getters and setters)

Im am searching for a solution since a few weecks, but I do not get the JSON-Object converted (deserialized?) to the DataSourceRequest-Object using the portlet-controller. 我正在寻找解决方案,因为有一些麻烦,但是我没有使用portlet-controller将JSON-Object转换(反序列化?)到DataSourceRequest-Object。 I even do not have an idea how to access the JSON-String in the request-body (payload) from the portlet-controller. 我什至不知道如何从portlet-controller访问请求正文(有效负载)中的JSON-String。

Following the second mentioned post , the nested objects might be the problem. 提到第二篇文章之后嵌套对象可能是问题所在。 I contacted the kendo-ui support with the question, how I can submit the request to get the format described in the post. 我与kendo-ui支持人员联系,询问有关如何提交请求以获取帖子中所述格式的问题。 But they told me, that is not possible (eg using parameterMap-attribute of the datasource object)and I have to solve it on the server-side. 但是他们告诉我,这是不可能的(例如,使用数据源对象的parameterMap-attribute),我必须在服务器端解决它。

The first post describes a solution with @ModelAttribute , but then I get only the empty object-and when I try to get the JSON with @RequestParam I get an error, that the parameter is not in the request (I think because it is in the body) 第一篇文章描述了使用@ModelAttribute的解决方案,但是随后我只得到了一个空对象,当我尝试使用@RequestParam获得JSON时,我得到一个错误,该参数不在请求中(我认为是因为该参数位于身体)

I was thinking about setting up an additional RESTFul API , based on Spring Web MVC Servlet - I even tried it and it works- but I am not sure if that is really meaningful, because liferay already has a RESTFul -API. 我当时正在考虑基于Spring Web MVC Servlet设置一个额外的RESTFul API-我什至尝试了并且它可以工作-但我不确定这是否真的有意义,因为liferay已经有了RESTFul -API。

Is there a way to convert the JSON Object to an JAVA Object inside the Portlet Controller ? 有没有办法在Portlet Controller中将JSON对象转换为JAVA对象? or Do I need the additional API? 还是我需要其他API?

Any tips are welcome!! 欢迎任何提示!!

I had the same problem while serializing and deserializing Json with Liferay. 在使用Liferay序列化和反序列化Json时,我遇到了同样的问题。 The solution for me was to send the json as a parameter in a form-data. 对我来说,解决方案是将json作为参数发送到表单数据中。 That way a I was able to retrive the Json with the following method: 这样,我就可以使用以下方法检索Json:

String paramJson = ParamUtil.getString(request, "myJson");

And then make use of Gson api to deserialize: 然后使用Gson api反序列化:

new Gson().fromJson(paramJson, MyPOJO.class);

You won't have so many troubles with Gson. 您对Gson不会有那么多麻烦。 You can also use Gson to serialize objects in the return of your services, this will avoid problems with nested objects witch Liferay doesn't serialize properly. 您还可以使用Gson在服务返回时序列化对象,这样可以避免Liferay无法正确序列化嵌套对象的问题。

This code show how to send the Json as request body: 此代码显示如何发送Json作为请求正文:

The request will be processed by method 'serveResource' in a MVCPortlet. 该请求将由MVCPortlet中的“ serveResource”方法处理。

var portletUrl = Liferay.PortletURL.createResourceURL();
portletUrl.setPortletId(<portletId>);
portletUrl.setResourceId('publicar'); // Any identifier

var formData = new FormData();           
formData.append(<portlet-namespace> + 'myJson', JSON.stringify(object)); 
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', callbackSuccess, false);
xhr.open('POST', urlPortlet);
xhr.send(formData);

To share my experience hera are the steps: 要分享我的经验,请执行以下步骤:

  1. in JS set contentType to application/x-www-form-urlencoded . 在JS中将contentType设置为application / x-www-form-urlencoded Thats the code for kendo-ui (uses jQuery Ajax in Background) 多数民众赞成在kendo-ui的代码(在后台使用jQuery Ajax)

     <kendo:dataSource-transport-parameterMap> function parameterMap(options,type) { if(type==="read"){ return "osdeFilter=" + encodeURIComponent(JSON.stringify(options)); } else { return "osdeModels=" + encodeURIComponent(JSON.stringify(options.models)); } } </kendo:dataSource-transport-parameterMap> 
  2. Get the Parameter and in my case use Jackson manualy to deserialize the JSON String 获取参数,在我的情况下,手动使用Jackson来反序列化JSON字符串

     @ResourceMapping(value = "test") public void searchProviderTest(ResourceRequest request, ResourceResponse response) throws JsonParseException, JsonMappingException, IOException { String osdeFilter = URLDecoder.decode(request.getParameter("osdeFilter"),"UTF-8"); LOGGER.info(">>>>>> JsonOjekt per Parameter übergeben: " + request.getParameter("osdeFilter")); ObjectMapper objectMapper = new ObjectMapper(); DataSourceRequest dataSourceRequest = objectMapper.readValue(osdeFilter, DataSourceRequest.class); LOGGER.info(">>>>>>>> DatasourceRequest: " + dataSourceRequest); } 

Differ from @giovani I do not need to submit the portlet-namespace. 与@giovani不同,我不需要提交portlet-namespace。 To achieve that, you must add the following configuration to liferay-portlet.xml 为此,必须将以下配置添加到liferay-portlet.xml中

<requires-namespaced-parameters>false</requires-namespaced-parameters>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM