POST JSON không thành công với loại phương tiện không được hỗ trợ 415, Spring 3 mvc


171

Tôi đang cố gắng gửi một yêu cầu POST đến một servlet. Yêu cầu được gửi qua jQuery theo cách này:

var productCategory = new Object();
productCategory.idProductCategory = 1;
productCategory.description = "Descrizione2";
newCategory(productCategory);

nơi mới Thể loại

function newCategory(productCategory)
{
  $.postJSON("ajax/newproductcategory", productCategory, function(
      idProductCategory)
  {
    console.debug("Inserted: " + idProductCategory);
  });
}

và postJSON là

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

Với fireorms tôi thấy rằng JSON được gửi chính xác:

{"idProductCategory":1,"description":"Descrizione2"}

Nhưng tôi nhận được loại phương tiện truyền thông không được hỗ trợ. Bộ điều khiển mvc mùa xuân có chữ ký

    @RequestMapping(value = "/ajax/newproductcategory", method = RequestMethod.POST)
public @ResponseBody
Integer newProductCategory(HttpServletRequest request,
        @RequestBody ProductCategory productCategory)

Mấy hôm trước nó làm việc, bây giờ thì không. Tôi sẽ hiển thị thêm mã nếu cần. Cảm ơn


Những gì bạn đã thay đổi từ một số ngày trước? Ngoài ra, sẽ không var productCategory = { idProductCategory: 1, description: "Descrizione2" };ngắn gọn và dễ đọc hơn? Bạn có cần nói với Spring để chấp nhận application/jsoncụ thể không? Nói cách khác, nó có mong đợi dữ liệu đến ở dạng không?
Dave Newton

Rất nhiều thứ kể từ khi tôi làm việc trên một phần khác của dự án này, và hôm nay tôi đã tìm thấy hồi quy này. Trong phần này tôi không thay đổi gì cả. Có, tôi phải sử dụng cách này vì tôi nhận được đầu vào từ một biểu mẫu.
gc5

Không phải bạn, bạn sẽ nhận được nó từ một bài viết JSON Ajax, không giống với dữ liệu được mã hóa biểu mẫu.
Dave Newton

1
Bạn có chắc Jackson vẫn có sẵn trên CLASSPATH của bạn không?
Tomasz Nurkiewicz

1
nếu bạn gửi văn bản / json thay vì ứng dụng / json bạn cũng gặp lỗi tương tự
Blacksonic

Câu trả lời:


249

Tôi đã có điều này xảy ra trước đây với Spring @ResponseBody và đó là vì không có tiêu đề chấp nhận được gửi cùng với yêu cầu. Tiêu đề chấp nhận có thể là một khó khăn để thiết lập với jQuery, nhưng điều này làm việc cho tôi nguồn

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    headers: { 
        'Accept': 'application/json',
        'Content-Type': 'application/json' 
    },
    'type': 'POST',
    'url': url,
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

Tiêu đề Kiểu nội dung được @RequestBody sử dụng để xác định định dạng dữ liệu được gửi từ máy khách trong yêu cầu. Tiêu đề chấp nhận được sử dụng bởi @ResponseBody để xác định định dạng nào để gửi dữ liệu trở lại máy khách trong phản hồi. Đó là lý do tại sao bạn cần cả hai tiêu đề.


1
các tiêu đề: {...} và JSON.opesify (...) luôn làm tôi thất vọng.
Tim Perry

1
Không biết tại sao điều này không được ghi nhận nhiều hơn. Vấn đề này khiến tôi lãng phí rất nhiều thời gian. Cảm ơn rât nhiều!
Hugo Nava Kopp

Tôi dự kiến ​​Spring không hỗ trợ dữ liệu biểu mẫu theo mặc định, nhưng không. Vì vậy, cảm ơn cho giải pháp (bây giờ khá cũ).
RiZKiT

Tôi đã sử dụng một người đưa thư để thực hiện một yêu cầu đặt, chỉ cần thêm loại nội dung: '' application / json ". Cảm ơn bạn
Janatbek Sharsheyev

21

thêm loại nội dung vào yêu cầu như đã application/jsongiải quyết vấn đề


18

Tôi đã gặp một vấn đề tương tự nhưng thấy vấn đề là tôi đã bỏ qua việc cung cấp một hàm tạo mặc định cho DTO được chú thích bằng @RequestBody.


điều tương tự đã xảy ra với tôi Tôi đã có 2 phương thức có cùng tên và nhận được 415. Cảm ơn!
Daniel Vilas-Boas

12

Tôi tin rằng tôi đã chạy chính xác vào cùng một vấn đề. Sau vô số giờ chiến đấu với JSON, JavaScript và Máy chủ, tôi đã tìm ra thủ phạm: Trong trường hợp của tôi, tôi có một đối tượng Date trong DTO, đối tượng Date này đã được chuyển đổi thành Chuỗi để chúng tôi có thể hiển thị nó trong chế độ xem với định dạng: HH: mm.

Khi thông tin JSON được gửi lại, đối tượng Chuỗi ngày này phải được chuyển đổi trở lại thành Đối tượng ngày đầy đủ, do đó chúng ta cũng cần một phương thức để đặt nó trong DTO. BUT lớn là bạn không thể có 2 phương thức có cùng tên (Quá tải) trong DTO ngay cả khi chúng có loại tham số khác nhau (Chuỗi so với Ngày) vì điều này cũng sẽ cung cấp cho bạn lỗi Loại không được hỗ trợ của Phương tiện 415.

Đây là phương pháp điều khiển của tôi

  @RequestMapping(value = "/alarmdownload/update", produces = "application/json", method = RequestMethod.POST)
  public @ResponseBody
  StatusResponse update(@RequestBody AlarmDownloadDTO[] rowList) {
    System.out.println("hola");
    return new StatusResponse();
  }

Đây là ví dụ DTO của tôi (id get / set và preAlarm get Phương thức không được bao gồm cho độ ngắn mã):

@JsonIgnoreProperties(ignoreUnknown = true)
public class AlarmDownloadDTO implements Serializable {

  private static final SimpleDateFormat formatHHmm = new SimpleDateFormat("HH:mm");

  private String id;
  private Date preAlarm;

  public void setPreAlarm(Date date) { 
    this.preAlarm == date;
  }
  public void setPreAlarm(String date) {    
    try {
      this.preAlarm = formatHHmm.parse(date);
    } catch (ParseException e) {
      this.preAlarm = null;
    } catch (NullPointerException e){
      this.preAlarm = null;
    }
  }
}

Để làm mọi thứ hoạt động, bạn cần xóa phương thức với tham số loại Ngày. Lỗi này rất bực bội. Hy vọng điều này có thể tiết kiệm một số giờ gỡ lỗi.


Cảm ơn - hoặc bạn chỉ có thể đổi tên một trong các setters. Tôi đã có cả hai public void setParameters(List<Parameter> parameters)& public void setParameters(Parameter... parameters)phương thức trong một bean, thay đổi cái sau để addParametersgiải quyết vấn đề cho tôi.
Conor Svensson

Không phải vấn đề là cơ thể là this.preAlarm == ngày chứ không phải this.preAlarm = date?
Michael khôi phục Monica Cellio

12

Tôi đã đối mặt với một vấn đề tương tự và đây là cách tôi khắc phục nó,

Vấn đề là do quá trình chuyển đổi từ JSON sang Java, người ta cần phải có các thư viện jackson thời gian chạy đúng để việc chuyển đổi diễn ra chính xác.

Thêm các lọ sau (thông qua phụ thuộc hoặc bằng cách tải xuống và thêm vào đường dẫn lớp.

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

Điều này sẽ khắc phục vấn đề.

Mã hoàn chỉnh:

function() {
  $.ajax({
    type: "POST",
    url: "saveUserDetails.do",
    data: JSON.stringify({
      name: "Gerry",
      ity: "Sydney"
    }),
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    success: function(data) {
      if (data.status == 'OK')
        alert('Person has been added');
      else
        alert('Failed adding person: ' + data.status + ', ' + data.errorMessage);
}

và chữ ký của bộ điều khiển trông như thế này:

@RequestMapping(value = "/saveUserDetails.do", method = RequestMethod.POST)
public @ResponseBody Person addPerson( @RequestBody final  Person person) {

Hi vọng điêu nay co ich


Chỉ jackson-databindđược yêu cầu.
Alex78191

8

Tôi gặp phải vấn đề này khi tôi tích hợp boot mùa xuân với spring mvc. Tôi đã giải quyết nó bằng cách chỉ cần thêm các phụ thuộc này.

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

5

Một lưu ý nhỏ - vấp phải lỗi tương tự trong khi phát triển ứng dụng web. Lỗi chúng tôi đã tìm thấy, bằng cách chơi với dịch vụ với Firefox Poster, là cả trường và giá trị trong Json phải được bao quanh bởi dấu ngoặc kép. Ví dụ..

[ {"idProductCategory" : "1" , "description":"Descrizione1"}, 
  {"idProductCategory" : "2" , "description":"Descrizione2"} ]

Trong trường hợp của chúng tôi, chúng tôi đã điền json thông qua javascript, điều này có thể hơi khó hiểu khi nói đến việc xử lý các trích dẫn đơn / kép, từ những gì tôi đã nghe.

Những gì đã được nói trước đây trong bài viết này và các bài đăng khác, như bao gồm các tiêu đề 'Chấp nhận' và 'Loại nội dung', cũng áp dụng.

Hy vọng giúp đỡ.


3

Tôi quản lý làm thế nào để làm cho nó hoạt động. Hãy nói cho tôi trong trường hợp tôi sai. Tôi chỉ sử dụng một cách để tuần tự hóa / giải tuần tự hóa: Tôi đã xóa tất cả các chú thích liên quan đến điều này ( @JSONSerialize@JSONDeserialize) và các Trình tuần tự hóa và Trình giải mã đã đăng ký trong CustomObjectMapperlớp. Tôi đã không tìm thấy một bài viết giải thích hành vi này nhưng tôi đã giải quyết theo cách này. Hy vọng nó hữu ích.


Xảy ra tương tự với tôi! Bất kỳ lời giải thích tại sao nó xảy ra?
Whimusical

Bạn có thể vui lòng giải thích chi tiết phương pháp của bạn ??
Dipanshu Verma

1

Tôi đã từng gặp vấn đề tương tự. Tôi đã phải làm theo các bước sau để giải quyết vấn đề:

1. Hãy chắc chắn rằng bạn có các phụ thuộc sau:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>

2. Tạo bộ lọc sau:

    public class CORSFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {

            String origin = request.getHeader("origin");
            origin = (origin == null || origin.equals("")) ? "null" : origin;
            response.addHeader("Access-Control-Allow-Origin", origin);
            response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, DELETE, OPTIONS");
            response.addHeader("Access-Control-Allow-Credentials", "true");
            response.addHeader("Access-Control-Allow-Headers",
                    "Authorization, origin, content-type, accept, x-requested-with");

            filterChain.doFilter(request, response);
        }
    }

3. Áp dụng bộ lọc trên cho các yêu cầu trong web.xml

    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>com.your.package.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Tôi hy vọng điều này hữu ích cho ai đó.


jackson-corelà một phụ thuộc của jackson-databind, vì vậy không cần phải thêm nó trực tiếp.
Alex78191

1
Tại sao cần phải thêm bộ lọc CORS?
Alex78191

1

Khởi động mùa xuân + mùa xuân mvn

có vấn đề

@PostMapping("/addDonation")
public String addDonation(@RequestBody DonatorDTO donatorDTO) {

với giải pháp

@RequestMapping(value = "/addDonation", method = RequestMethod.POST)
@ResponseBody
public GenericResponse addDonation(final DonatorDTO donatorDTO, final HttpServletRequest request){

0

Tôi đã giải quyết vấn đề này bằng cách thêm ràng buộc dữ liệu jackson-json vào pom của tôi.

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

0

Trong Lớp Mô hình của bạn thêm chú thích thuộc tính json, cũng có hàm tạo mặc định

@JsonProperty("user_name")
private String userName;

@JsonProperty("first_name")
private String firstName;

@JsonProperty("last_name")
private String lastName;

0

Tôi gặp vấn đề tương tự. thêm

<mvc:annotation-driven />
<mvc:default-servlet-handler />

đến mùa xuân-xml đã giải quyết nó


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.