2015-12-23 52 views
3

在我問我的問題之前,我不得不說我已經閱讀了20多個關於這個問題的問題和文章,他們都不能解決它。用java作爲服務器和jquery作爲客戶端的簡單的JSON POST

我的問題是我在Java這樣一個寧靜的服務器:

@RequestMapping (value = "/downloadByCode", method = RequestMethod.POST) 
@ResponseBody 
public void downloadByCode(@RequestBody final String stringRequest, final HttpServletResponse response) 
{ 
    try 
    { 
     final ObjectMapper objectMapper = new ObjectMapper(); 
     final JsonNode jsonRequest = objectMapper.readValue(stringRequest, JsonNode.class); 

     // ... 
     // some processings here to create the result 
     // .... 

     final ServletOutputStream outputStream = response.getOutputStream(); 
     outputStream.write(result); 
     // Flush the result 
     outputStream.flush(); 
    } 
    catch (final Exception exception) 
    { 
     LOG.debug("Exception Thrown [downloadByCode]", exception); 
    } 
} 

我嘗試了多種不同的方式爲JSON發送到該服務器使用jQuery(但他們都創造錯誤):

$.ajax({ 
    url:"/downloadByCode", 
    type:"POST", 
    data: JSON.stringify({"name":"value"}) }); 

415 "errors message" : "Content type 'application/x-www-form urlencoded;charset=UTF-8' not supported", "type" : "HttpMediaTypeNotSupportedError"

所以,我想加入的contentType來解決它:

$.ajax({ 
    url:"/downloadByCode", 
    contentType:"application/json", 
    type:"POST", 
    data: JSON.stringify({"name":"value"}) }); 

400 "errors message" : "Could not instantiate JAXBContext for class [class java.lang.String]: null; nested exception is javax.xml.bind.JAXBException\n - with linked exception:\n[java.lang.NullPointerException", "type" :"HttpMessageConversionError"

我試着直接發送json對象而不是JSON.stringify,它給出了相同的400錯誤。

我試圖給@requestMapping添加不同的消耗,但仍然沒有運氣。

我試圖定義我自己的類而不是JsonNode,但它不會改變任何東西。

任何想法?

+0

您是否嘗試將您的@RequestBody參數類型更改爲Map 或使用單個「name」屬性創建一個類並將其用作類型(由Vinh Vo建議)? – NTyler

+0

@NTyler,我從來沒有嘗試過Map ,我現在就試試它。感謝您的建議 – Arashsoft

+0

Vinh Vo方法創建以下錯誤:'無法爲類[$ InputData]實例化JAXBContext:\ r \ n異常說明:$ InputData需要一個零參數構造函數或指定的工廠方法。請注意,非靜態內部類不具有零參數構造函數,並且不受支持。' – Arashsoft

回答

0

最終的答案是一個數字的答案的組合/在這個問題上的意見,我要在這裏總結一下他們:

1 - 你必須確保你有適當的JSON轉換器的Spring配置如MappingJacksonHttpMessageConverter(學分@java安託)

2 - 你必須創建具有相同結構的POJO類作爲您的JSON對象(見@Vinh VO答案)

3-你的POJO類不能一個內聯類,除非它是一個靜態類。這意味着它應該有它自己的Java文件,或者它應該是靜態的。 (學分@NTyler),如果在你的對象映射適當設置(見@Aman Tuladhar答案)

4-你的POJO類可以錯過JSON對象的部分

5-你的Ajax調用需要contentType:"application/json",你應該用JSON.stringify

這裏發送您的數據是工作的最終代碼完美:

public static class InputData 
{ 
    private String name 

    public String getName() 
    { 
     return name; 
    } 

    public void setName(final String name 
    { 
     this.name = name; 
    } 
} 

@RequestMapping(value = "/downloadByCode", method = RequestMethod.POST) 

@ResponseBody 
public void downloadByCode(@RequestBody final InputData request, final HttpServletResponse response) 
{ 
    try 
    { 
     String codes = request.getName(); 

     // ... 
     // some processings here to create the result 
     // .... 

     final ServletOutputStream outputStream = response.getOutputStream(); 
     outputStream.write(result); 
     // Flush the result 
     outputStream.flush(); 
    } 
    catch (final Exception exception) 
    { 
     LOG.debug("Exception Thrown [downloadByCode]", exception); 
    } 
} 

它是jQuery的Ajax請求:

$.ajax({ 
    url:"/downloadByCode", 
    contentType:"application/json", 
    type:"POST", 
    data: JSON.stringify({"name":"value"}) }); 
1

嘗試@RequestBody final Map<String, String> stringRequest

你也將需要consumes = "application/json"的@RequestMapping,因爲你必須在你的AJAX調用

您將獲得400如果春天不喜歡,你把你的AJAX的格式 - 過去我遇到過這麼多麻煩,除非需要忽略標題類型和內容類型,似乎更好。

+0

謝謝你的回答。我已經改變了我的請求正文: 'public void downloadOrdersByCode(@RequestBody final Map requestMap,final HttpServletResponse response)' 但是,我仍然得到與上面相同的400錯誤 – Arashsoft

+0

您還需要消耗部分我的答案(或只是把它從你的ajax調用) - 這是否工作? –

+0

不,它不起作用。 – Arashsoft

1

您可以嘗試將響應作爲ResponseEntity發回,而不是直接使用HttpServletResponse。我的直覺是第二個參數,HttpServletRequest參數,是導致問題的原因。我從來沒有用過。我總是使用spring mvc api發回我的回覆。

+0

謝謝你的迴應,問題是它永遠不會到達響應階段。我的意思是當它試圖接收json作爲輸入時會產生錯誤。我的回覆是一個CVS文件,我認爲當前的代碼應該沒問題,因爲它可以很好地與GET方法配合使用。 – Arashsoft

1

隨着新澤西API,您可以嘗試只: @POST 公共無效downloadByCode(字符串stringRequest)

,我想你會發現在stringRequest您的文章的身體。

+0

謝謝,如果我不能在沒有額外API的情況下解決問題,也許我會試試它。 – Arashsoft

0

刪除@ResponseBodydownloadByCode方法

+0

沒有什麼改變,我認爲這個問題與獲取json作爲輸入有關。輸出部分看起來很好。 – Arashsoft

0

改變你的方法downloadByCode()的返回類型爲字符串,然後返回字符串

響應體將返回的字符串自動轉換成JSON,然後適當地使用數據

+0

它永遠不會到達響應階段。它在嘗試加載json作爲輸入時會產生錯誤。 – Arashsoft

0

我不是很熟悉java,但我知道你的java代碼必須是這樣的。

public class downloadByCode{ 
    @GET 
    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") 
    public Response downloadByCode(@QueryParam("paramater1") final String parameter 1, @Context HttpServletRequest httpRequest) { 

如果這沒有幫助,你可以讓你的代碼在某個地方並分享它。

+0

我覺得這段代碼是基於GET方法的,我想用POST方法獲取JSON對象(或JSON字符串)。 – Arashsoft

1

你可以請求體作爲字符串的org.springframework.http.HttpEntity<String>用法請求類型,我這裏是你的代碼爲基礎:

@RequestMapping (value = "/downloadByCode", method = RequestMethod.POST) 
@ResponseBody 
public void downloadByCode(final HttpEntity<String> request, final HttpServletResponse response) 
{ 
    try 
    { 
     final ObjectMapper objectMapper = new ObjectMapper(); 
     final JsonNode jsonRequest = objectMapper.readValue(request.getBody(), JsonNode.class); 

     // ... 
     // some processings here to create the result 
     // .... 

     final ServletOutputStream outputStream = response.getOutputStream(); 
     outputStream.write(result); 
     // Flush the result 
     outputStream.flush(); 
    } 
    catch (final Exception exception) 
    { 
     LOG.debug("Exception Thrown [downloadByCode]", exception); 
    } 
} 

但也許會更好還使用String作爲回報類型,如果你打算返回結果爲字符串值,就像這樣:

@RequestMapping (value = "/downloadByCode", method = RequestMethod.POST) 
@ResponseBody 
public String downloadByCode(HttpEntity<String> request) { 
    String requestBody = request.getBody(); 
    String result; 

    // ... 
    // some processings here to create the result text 
    // .... 

    return result; 
} 

我使用Spring Boot進行了簡單的應用,使用了使用HttpEntity的建議解決方案,以及使用POJO的附加示例,運行應用程序需要有Maven和JDK> = 1.7。

#clonning repository with sample 
git clone [email protected]:mind-blowing/samples.git 

#change current folder to sample application root 
cd samples/spring-boot/rest-handler-for-plain-text 

#running application using maven spring-boot plugin 
mvn spring-boot:run 

後的應用程序將被啓動,你可以打開http://localhost:8080,你會看到HTML頁面使用jQuery的簡單的使用發送POST請求,請求和響應的HTML頁面上會看到的文本,在控制器我加了兩個處理器,首先使用HttpEntity,然後使用POJO。

控制器:SampleRestController.java

HTML頁面:index.html

項目:https://github.com/mind-blowing/samples/tree/master/spring-boot/rest-handler-for-plain-text

+0

我要試一試!謝謝:) – Arashsoft

+0

我得到這個錯誤:'內容類型'application/x-www-form-urlencoded; charset = UTF-8'不支持' – Arashsoft

+0

我使用這個jquery ajax:'$ .ajax({url:「/ downloadByCode 「,請輸入:」POST「,data:JSON.stringify({」name「:」value「})});' – Arashsoft

3

請嘗試創建新類:

public class InputData{ 
    private String name; 
    public String getName(){ 
     return name; 
    } 
    public void setName(String name){ 
     this.name = name; 
    } 
} 

然後

public void downloadByCode(@RequestBody InputData stringRequest, final HttpServletResponse response) 

而且

$.ajax({ 
    url:"/downloadByCode", 
    contentType:"application/json", 
    type:"POST", 
    data: JSON.stringify({"name":"value"}) }); 
+0

謝謝你的建議,但我得到這個錯誤:'無法爲類[$ InputData]實例化JAXBContext:\ r \ n異常描述:$ InputData需要一個零參數構造函數或指定的工廠方法。請注意,非靜態內部類沒有零參數構造函數,並且不支持。' – Arashsoft

1

看你的錯誤,很明顯,你已經配置了「Jaxb2RootElementHttpMessageConverter」或在Spring配置類似的XML轉換器。而且,由於您已經註冊了一個XML轉換器,所以@RequestBody和@ResponseBody基於註冊的消息轉換器工作。

因此,要解決您的問題,請使用JSON消息轉換器,如「MappingJacksonHttpMessageConverter」。一旦您註冊一個JSON消息變換,創建一個bean類來保存您的JSON數據,並與RequestBody使用如下:

// It has to meet the json structure you are mapping it with 
public class YourInputData { 
    //properties with getters and setters 
} 

更新1:

既然你已經定義了多個消息轉換器,彈簧嘗試使用默認情況下可用的第一個。爲了使用特定的消息轉換器(在這種情況下,傑克遜轉換器),你應該指定「接受」頭從客戶端象下面這樣:

$.ajax({  
      headers: {   
       "Accept" : "application/json; charset=utf-8",   
       "Content-Type": "application/json; charset=utf-8" 
    }  
    data: "data",  
    success : function(response) { 
     ... 
    } }) 
+0

感謝您的回覆,我已經有json轉換器: '' – Arashsoft

+0

我創建了與我的json'{」name「,」value「}具有相同結構的bean類,但是出現此錯誤:'無法爲類[$ InputData]實例化JAXBContext:\ r \ n異常描述:$ InputData需要一個零參數構造函數或一個指定的工廠方法。注意,非靜態內部類沒有零參數構造函數,並且不支持' – Arashsoft

+0

實際的問題是它試圖在應用時使用JAXB轉換器使用Jackson轉換器 – James

1

首先如果你正在使用maven,你應該添加依賴傑克遜

<dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-databind</artifactId> 
     <version>2.4.1</version> 
    </dependency> 

,或者你可以下載JAR並把它放在我們的項目類路徑(也可以使用其他映射器以及)

,那麼你應該創建一個模型或DTO類,你可以映射你的JSON

public class Data{ 
    private String name; 

    pubilc Data(){} 

    //getter and setter 

} 

那麼你控制器

@RequestMapping (value = "/downloadByCode", method = RequestMethod.POST) 
@ResponseBody 
public Data downloadByCode(@RequestBody final Data data, final HttpServletResponse response) 
{ 
//your code 
    return data; 
} 

AJAX調用

$.ajax({ 
    url:"/downloadByCode", 
    contentType:"application/json", 
    type:"POST", 
    data: JSON.stringify({"name":"value"}) }); 

(可選),你可以告訴對象映射器沒有失敗的定義豆如下缺少的屬性重寫的行爲:

@Bean 
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { 
     MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); 
     converter.setObjectMapper(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)); 
     return converter; 
    } 

http://websystique.com/springmvc/spring-mvc-requestbody-responsebody-example/

+0

謝謝你的幫助。這個答案是一切應該如何「理想」的工作!但是,它會在我的環境中產生錯誤。 – Arashsoft

相關問題