@ResourceMapping that accepts JSON from Ajax reque

2019-04-02 12:00发布

问题:

I'm searching how I can interprete a JSON parameter in my @ResourceMapping in Spring Portlet MVC. When I add @RequestBody, I got the message: @RequestBody is not supported... Really stuck on this one.

I have this:

View side:

<portlet:resourceURL var="getTest" id="ajaxTest" ></portlet:resourceURL>

    <p>
        <button onClick="executeAjaxTest();">Klik mij!</button>
        <button onClick="$('#ajaxResponse').html('');">Klik mij!</button>
    </p>
    <p>
        <h3>Hieronder het antwoord:</h3>
        <h4 id="ajaxResponse"></h4>
    </p>

    <script>
        function executeAjaxTest() {

            var jsonObj = {
                    user: "Korneel",
                    password: "testpassword",
                    type: {
                        testParam: "test",
                    }
                }

            console.debug(JSON.stringify(jsonObj));
            $.ajax({
                dataType: "json",
                contentType:"application/json",
                mimeType: 'application/json',
                url:"<%=getTest%>",
                data:JSON.stringify(jsonObj),
                success : function(data) {
                    $("#ajaxResponse").html(data['testString']);
                }
            });

        }
    </script>

Controller side:

@ResourceMapping(value="ajaxTest")
    @ResponseBody
    public void ajaxTestMethod(ResourceRequest request, ResourceResponse response) throws IOException, ParseException {

        LOGGER.debug("ajax method");

        JSONObject json = JSONFactoryUtil.createJSONObject();
        json.put("testString", "Ik ben succesvol verstuurd geweest!");
        response.getWriter().write(json.toString());
}

How can I use the spring magic to auto map this JSON data to my own model? Note: It's Spring Portlet MVC, not regular Spring MVC..

回答1:

You need to build your json object like this:

var jsonObj = {
                user: "Korneel",
                password: "testpassword",
                "type.testParam" : "test"
            };

$.ajax({
            dataType: "json",
            contentType:"application/json",
            mimeType: 'application/json',
            url:"<%=getTest%>",
            data:jsonObj,
            success : function(data) {
                $("#ajaxResponse").html(data['testString']);
            }
        });

In your Controller you should use the @ModelAttribute annotation:

@ModelAttribute(value = "jsonObj")
public JsonObjCommand obtenerJsonObjCommand() {
    JsonObjCommand jsonObjCommand = new JsonObjCommand();
    return jsonObjCommand;
}

@ResourceMapping(value = "ajaxTest")
public void ajaxTestMethod(
        ResourceRequest request,
        ResourceResponse response,
        @ModelAttribute(value = "jsonObj") JsonObjCommand jsonObjCommand)
        throws IOException, ParseException {
    LOGGER.debug("USER: " + jsonObjCommand.getUser());
    LOGGER.debug("Password: " + jsonObjCommand.getPassword());
    LOGGER.debug("TestParam: " + jsonObjCommand.getType().getTestParam());
    LOGGER.debug("ajax method");

    JSONObject json = JSONFactoryUtil.createJSONObject();
    json.put("testString", "Ik ben succesvol verstuurd geweest!");
    response.getWriter().write(json.toString());
}

Don't forget your beans:

public class JsonObjCommand {

private String user;
private String password;
private TypeJson type;

public String getUser() {
    return user;
}
public void setUser(String user) {
    this.user = user;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
public TypeJson getType() {
    return type;
}
public void setType(TypeJson type) {
    this.type = type;
}

}

public class TypeJson {

private String testParam;

public String getTestParam() {
    return testParam;
}

public void setTestParam(String testParam) {
    this.testParam = testParam;
}

}


回答2:

@ResponseBody annotation is not supported out of the box in Spring MVC portlet framework, but you can implement @ResponseBody handling yourself.

We do it by implementing custom view type and model and view resolver.

  1. Implement custom model and view resolver (ModelAndViewResolver), let's say JsonModelAndViewResolver.
  2. In resolveModelAndView method, check whether controller method has @ResponseBody annotation (or more specific condition to identify JSON output - e.g. annotation + required supported mime type).
  3. If yes, return your custom View implementation - let's say SingleObjectJson view (extending AbstractView).
  4. Pass your to-be-serialized object to the view instance.
  5. The view will serialize the object to JSON format and write it to the response (by using Jackson, Gson or other framework in renderMergedOutputModel method).
  6. Register the new resolver as AnnotationMethodHandlerAdapter.customModelAndViewResolvers.


回答3:

According to the documentation, @RequestBody is only supported in Servlet environments, not Portlet environments (same for @ResponseBody). So it seems you can't use that functionality.