使用 JQuery 和 Java 但 运行 在 Play Framework 中构建自动保存功能进入 400 Bad Request 或 404 Not Found 错误

Building Autosave function in Play Framework using JQuery and Java but running into 400 Bad Request or 404 Not Found error

我正在我的 Play 应用程序中使用模型中的 JQuery 构建自动保存功能,并在控制器中处理请求。

我最初 posted (Post 1) 这个:

Play Framework JQuery AJAX REST Post call returns Bad Request error

但这被标记为可能与此 (Post 2) 重复:

play framework routes trouble (400 bad request)

我的原始 post (Post 1) 没有收到任何答复,所以我被指示重新post 我的问题。

我遵循 Post 2 并删除了我传递的参数,因为它可能是我请求的问题,基于 Post 2。Post 2 中引用的文档是在 Scala 中(对于旧版本的 Play - 我使用的是 2.5)我的应用程序在 Java 中,所以它并没有真正帮助我。我在 Play 文档中找到了这个:

https://www.playframework.com/documentation/2.5.x/JavaJsonActions

我阅读并遵循了该文档并更新了我的代码。

但是,我仍然收到 Bad Request (400) 或 Not Found (404) 错误。我没有收到任何详细的消息,所以我不确定我在哪里犯了错误。

这是 Chrome 控制台返回的内容:

addptp:414 POST http://localhost:9000/autosave 404 (Not Found)
send    @   jquery-3.2.1.min.js:4
ajax    @   jquery-3.2.1.min.js:4
(anonymous) @   addptp:414
each    @   jquery-3.2.1.min.js:2
each    @   jquery-3.2.1.min.js:2
autosave    @   addptp:413
(anonymous) @   addptp:185

这是视图中的 JQuery:

var timer;
var restURL = window.location.protocol + "//" + window.location.hostname + (window.location.port == "" ? "" : (":" + window.location.port));

$(document).ready(function() {
    // JSON REST Autosave...
    timer = setInterval(function() {
        autosave();
    }, 6000);
});

    function autosave() {
        alert("Autosave");
        $('form').each(function() {
            $.ajax({
                type: "POST",
                url: restURL + "/autosave",
                data: $(this).serialize(),
                dataType: "json",
                contentType: "application/x-www-form-urlencoded; charset=utf-8",
                success: function(data) {
                    alert("Success!");
                },
                error: function(data) {
                    alert("Error!");
                }
            });
        });
    }

这是我在 Java 中的控制器代码:

@BodyParser.Of(BodyParser.FormUrlEncoded.class)
public Result restAutosaveAdultPTP() {
    // Let's get the current request in JSON and parse...
    Map<String, String[]> json = request().body().asFormUrlEncoded();
    if (json == null) {
        return badRequest("Expecting Json data");
    } else {
        return ok("json: " + json);
    }
}

这是我的 routes 文件条目:

POST   /autosave   controllers.Application.restAutosaveAdultPTP()

这是请求和响应信息...

一般:

Request URL:http://localhost:9000/autosave
Request Method:POST
Status Code:404 Not Found
Remote Address:[::1]:9000
Referrer Policy:no-referrer-when-downgrade

回应Headers:

HTTP/1.1 404 Not Found
Content-Length: 26917
Content-Type: text/html; charset=utf-8
Date: Thu, 25 Jan 2018 18:34:15 GMT

请求Headers:

POST /autosave HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Content-Length: 2739
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:9000
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:9000/addptp
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: PLAY_SESSION=a37c3087c9d5d3f4129057c964ca9a90eef80fe5-SESSION_ID=kfs7q8vohk3ammlfcnfka0j1p9&email=dzeller44%40gmail.com&userTimeout=1516880046558

有效负载

legacy_Provider_Id=&new_Provider_Id=&provider_Name=&alternate_Name_DBA=&setting_Type=&waivers_Served=&total_Number_Served=&total_Number_on_Waivers=&street_Address=&apartment=&city=&state=&zip=&phone=&email1=&email2=&contact_Person=&updates=&main_PTP_Address=&duplicate_docs=&other_Rights_NonCompliance_Description=&other_Remedy_for_Rights_Description=&details_for_Rights_Action_Plan=&remedy_Rights_Incurred_Cost_Description=&remedy_Rights_One_Time_Costs=&remedy_Rights_Recurring_Annual_Costs=&person_for_Rights_Action_Plan=&status_Rights_Action_Plan=---+Select+Status+---&other_Choice_NonCompliance_Description=&other_Remedy_for_Choice_Description=&detail_for_Choice_Action_Plan=&remedy_Choice_Incurred_Cost_Description=&remedy_Choice_One_Time_Costs=&remedy_Choice_Recurring_Annual_Costs=&person_for_Choice_Action_Plan=&status_of_Choice_Action_Plan=---+Select+Status+---&other_Integration_NonCompliance_Description=&other_Remedy_for_Integration_Description=&detail_for_Integration_Action_Plan=&remedy_Integration_Incurred_Cost_Description=&remedy_Integration_One_Time_Costs=&remedy_Integration_Recurring_Annual_Costs=&person_for_Integration_Action_Plan=&status_for_Integration_Action_Plan=---+Select+Status+---&other_Remedy_for_Institutional_Factors_Description=&detail_for_Institutional_Action_Plan=&remedy_Institutional_Incurred_Cost_Description=&remedy_Institutional_One_Time_Costs=&remedy_Institutional_Recurring_Annual_Costs=&person_for_Institutional_Action_Plan=&status_of_Institutional_Action_Plan=---+Select+Status+---&ptp_Edited_Date=&ptp_Status_Notes=&update_Due=&compliance_Status=---+Select+Status+---&ensures_Rights=---+Select+Status+---&optimizes_Autonomy=---+Select+Status+---&selected_by_Person=---+Select+Status+---&options_in_PC_Plan=---+Select+Status+---&facilitates_Choice=---+Select+Status+---&integrated_in_Community=---+Select+Status+---&enforceable_Lease=---+Select+Status+---&eviction_Protections=---+Select+Status+---&bedroom_Privacy=---+Select+Status+---&bedroom_Locks=---+Select+Status+---&choice_of_Roommates=---+Select+Status+---&freedom_to_Decorate=---+Select+Status+---&free_Schedule_Access_to_Food=---+Select+Status+---&visitors_any_Time=---+Select+Status+---&physically_Accessible=---+Select+Status+---&modifications_PC_Plan=---+Select+Status+---&setting_NonInstitutional=---+Select+Status+---&heightened_Scrutiny_Description=&cdphe_Lead=&site_Visit_Status=---+Select+Status+---&site_Visit_Date=&site_Visit_Team=&documents_Detail=&findings_from_Documents=&summary_of_Findings=&promising_Practices=&additional_Notes=&follow_up_Visit_Status=---+Select+Status+---&additional_Notes_2=&follow_up_Date=&follow_up_Team=&documents_Detail_2=&findings_from_Documents_2=&summary_of_Findings_2=&promising_Practices_2=

如以下评论所述,为什么它在请求 Headers:

中查找 json 而不是 form-url-encoded
Accept: application/json, text/javascript, */*; q=0.01

感谢您提供的任何指导或帮助。

问题是 $(this).serialize() 正在用 URL 编码的符号对数据进行编码,但是控制器中的 @BodyParser.Of(BodyParser.Json.class) 注释和 request().body().asJson() 代码表明你'重新期待 JSON 编码。

serialize 的文档:https://api.jquery.com/serialize/

The .serialize() method creates a text string in standard URL-encoded notation.

而不是使用 JSON 的 serialize 方法,您可能想使用类似 JavaScript 的 stringify 的方法:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

The JSON.stringify() method converts a JavaScript value to a JSON string

或者,您可以更改您的播放代码以期待一个 URL 编码值。请在此处查看有关 FormUrlEncoded 的文档:https://www.playframework.com/documentation/2.6.x/JavaBodyParsers

FormUrlEncoded: Parses the body as a form.

如果您更改播放行为,请记住同时更改您发送的 contentType,使其成为 application/x-www-form-urlencoded 而不是 application/json