415不支持的媒体类型(org.springframework.web.client.HttpClientErrorException)

5
我对WebServices还不熟悉。我正在开发一个应用程序,客户端使用AnhularJs1.x将数据发送到Spring Rest Controller。
该应用程序的架构是基于微服务的。我能够从Angular接收数据到前端Rest控制器,它们在同一个war中。
从这个控制器中,我调用了一个服务,该服务内部调用了另一个与数据库交互的微服务。
当我将前端控制器中收到的数据发送到另一个微服务时,我收到了"415 Unsupported Media Type (org.springframework.web.client.HttpClientErrorException)"的错误。
以下是我的前端控制器,它与AngularJS在同一个war中:
@RequestMapping(value = "/servicearticles",  method = RequestMethod.POST,        produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ServiceArticle> saveData(@RequestBody      List<ServiceArticle> serviceArticleList){
    System.out.println("In savedata");
    System.out.println(serviceArticleList.toString());


    try {
        if(null != serviceArticleList && serviceArticleList.size() >0){
            serviceArticleAdminService.insertData(serviceArticleList);
        }else{
            logger.error("File is empty. No data to save");
        }

我能够在这个控制器中获取数据:

[ServiceArticle [articleId=17070, productCode=1000, productName=Business Parcel zone , zone=1], ServiceArticle [articleId=17071, productCode=1001, productName=Business Parcel zone , zone=4], ServiceArticle [articleId=17070, productCode=1012, productName=Business Parcel zone , zone=5], ServiceArticle [articleId=17070, productCode=1000, productName=Business Parcel zone , zone=1], ServiceArticle [articleId=17070, productCode=1000, productName=Business Parcel zone , zone=2]]

当我从我的serviceImpl类调用不同的微服务时,我会收到“不支持的媒体类型”错误。

serviceImpl类的代码:

private final String URI = "http://localhost:8082/admin/import/servicearticles";

@Override
public void insertData(List<ServiceArticle> serviceArticles) {
    logger.error("Inside insertData() in service");

    RestTemplate restTemplate = new RestTemplate();

    try {
            restTemplate.postForObject(URI, serviceArticles, ServiceArticle.class);
    } catch (ResourceAccessException e) {
        logger.error("ServiceArticleAdmin Service Unavailable.");

以下是不同微服务中映射到此调用的控制器代码
@RequestMapping(value = "/import/servicearticles", method =    RequestMethod.POST, consumes= MediaType.APPLICATION_JSON_VALUE , produces = MediaType.APPLICATION_JSON_VALUE)
 public ResponseEntity<ServiceArticle> addAll(@RequestBody List<ServiceArticle> serviceArticles) {

    List<ServiceArticle> serviceArticlesAdded = serviceArticleAdminService.addAll(serviceArticles);

    return new ResponseEntity(serviceArticlesAdded, HttpStatus.OK);
}

我已经在我的pom.xml文件中添加了以下依赖项

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

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.8.6</version>
    </dependency>

我在servlet-context.xml中有以下的bean定义:

<bean
    class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <ref bean="jsonMessageConverter" />
        </list>
    </property>
</bean>

<!-- To convert JSON to Object and vice versa -->
<bean id="jsonMessageConverter"
    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>

请帮我找出我的错误所在。 当我调用restTemplate.postForObject方法时,是否有办法将响应类型设置为application/json? 我使用REST客户端插件进行验证,它在那里可以工作,但在我的Java代码中不行。请帮忙。
4个回答

22

看起来缺少 Content-Type: application/json 请求头。 同时你的方法返回的是一组文章而不是单篇文章,因此在 postForObject 方法中的第三个参数不正确。

以下代码应该可以解决问题:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<List<ServiceArticle>> request = new HttpEntity<>(serviceArticles, headers);

ResponseEntity<List<ServiceArticle>> response = 
    restTemplate.exchange(URI, HttpMethod.POST, request,
        new ParameterizedTypeReference<List<ServiceArticle>>() { });

感谢@Eien的回答,我尝试了这段代码,但是出现了org.springframework.web.client.HttpServerErrorException: 500服务器错误。 - AkashSharma
堆栈跟踪: 在org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94)处 在org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)处 在org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)处 在org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)处 在org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)处 在no.bring.priceengine.servicearticle.service.impl.ServiceArticleAdminServiceImpl.insertData(ServiceArticleAdminServiceImpl.java:65)处 - AkashSharma
检查您从代码调用的微服务日志。看起来错误是从那里引起的。 - Eien
控制永远不会进入该微服务代码。这是应该在restTemplate.exchange()上调用的方法:@RequestMapping(value = "/import/servicearticles", method = RequestMethod.POST, consumes= MediaType.APPLICATION_JSON_VALUE , produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity addAll(@RequestBody List serviceArticles) { List serviceArticlesAdded = serviceArticleAdminService.addAll(serviceArticles); return new ResponseEntity(serviceArticlesAdded, HttpStatus.OK); } - AkashSharma
是的 @Eien,我明白你想告诉我的,但微服务没有打印任何日志。 - AkashSharma
显示剩余3条评论

2
@RestController
@RequestMapping("/db")
public class EmployeeDataServerResource {

    @Autowired
    EmployeeInterface ei;

    @PostMapping("/add")
    public EmployeeTable addEmployee(@Valid @RequestBody EmployeeTable      employeeTable) {

         ei.save(employeeTable);
         return employeeTable;
    }
}

这是我的restController方法。
public String onSave() {    
    try {
    EmployeeTable et = new EmployeeTable();
    et.setFirstName(firstName.getValue());
    et.setLastName(lastName.getValue());
    et.setEmail(email.getValue());
    et.setBirthdate(birthDate.getValue());
    et.setNumber(number.getValue());
    et.setPassword(pswd.getValue());
    et.setGender(rgroup.getValue());
    et.setCountry(select.getValue());
    et.setHobbiesLst(hobbies);

    String uri = "http://localhost:8090/db/add"; 
              
    HttpHeaders headers=new HttpHeaders();
    headers.set("Content-Type", "application/json");
    HttpEntity requestEntity=new HttpEntity(et, headers);

    ResponseEntity<EmployeeTable> addedRes = restTemplate.exchange(uri, HttpMethod.POST,requestEntity,EmployeeTable.class);
    return ""+addedRes.getStatusCodeValue();
      
    }catch (Exception e) {
        System.out.println(""+e.toString());
        return e.toString();
    }   
}

这是使用restController添加新员工到数据库的方法。对我来说很有效...谢谢


1
这段代码可能解决你的两个问题:
@RequestMapping(value = "/postnotewithclient",method = RequestMethod.POST)
public String postNote(@RequestBody  Note notes)
{
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    HttpEntity<Note> entity = new  HttpEntity<Note>(notes,headers);
    return restTemplate.exchange("http://localhost:8080/api/notes", HttpMethod.POST, entity, String.class).getBody();

}

0

在我的情况下,所有的POST请求都没问题,但是仍然报告了不支持的异常。经过对代码的一些调整,真正的问题浮出水面,那就是我为其中一个字段拥有的自定义反序列化器

调试提示: 为了确保您的REST API正常运行,请先尝试将请求作为字符串接收,然后使用对象映射器将该字符串转换为所需的对象。

无论如何,上述提示都不应用于生产就绪代码。希望这能帮助到某些人。

干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接