通过RestTemplate发送POST和PUT到Spring Data Rest Api

时间:2017-02-20 22:21:50

标签: json spring-data-rest resttemplate spring-hateoas

我一直在开发一个云应用程序,以便与Spring Cloud等有点混乱。现在,我试图使用RestTemplate API向Spring Data Rest后端发送POST或PUT请求,但我尝试的所有内容都以错误结束:HttpMessageNotReadableException:无法从START_OBJECT令牌中反序列化java.lang.String的实例,HttpMessageNotReadableException:无法读取文档:无法从START_ARRAY令牌中取消序列化java.lang.String的实例,...来自内容类型为application / xml的请求; charset = UTF-8 !,错误400 null ...你说出来。经过研究,我发现使用RestTemplate消耗HAL JSON实际上非常困难(如果我没记错的话,可以使用3级JSON超媒体),但我想知道它是否可行。

我希望看到RestTemplate向Spring Data Rest后端发送POST和PUT的一些工作(如果可能的话详细)。

编辑:我尝试了postForEntity,postForLocation,exchange,它只是以不同类型的错误结束。这些是我尝试过的一些片段(更重要的是,它只是我处理它们)。

我的实体:

@Entity
public class Account implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@NotNull
@NotEmpty
private String username;

@NotNull
@NotEmpty
private String authorities;

@NotNull
@NotEmpty
private String password;

//Constructor, getter and setter

一些restTemplate尝试:

    public Account create(Account account) {
    //Doesnt work :S
    MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
    map.add("name", account.getName());
    map.add("username", account.getUsername());
    map.add("password", account.getPassword());
    map.add("authorities", account.getAuthorities());

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    final HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(map,
            headers);

    return restTemplate.exchange(serviceUrl + "/accounts", HttpMethod.POST, entity, Account.class).getBody();
}

//Also tried with a AccountResource which extends from ResourceSupport and doesn't work either. This one gives me a error saying it cannot deserialize Account["name"].

也尝试了这样,并得到关于标题为application / xml的错误:RestTemplate POSTing entity with associations to Spring Data REST server

其他人只是重复其中一个错误。

1 个答案:

答案 0 :(得分:4)

您需要配置RestTemplate,以便它可以使用 application / hal + json 内容类型。

其他一些帖子(例如this onethat one)以及一些博客帖子(例如here)已经解决了这个问题。 以下解决方案适用于Spring Boot项目:

首先,使用bean配置RestTemplate:

// other import directives omitted for the sake of brevity
import static org.springframework.hateoas.MediaTypes.HAL_JSON;

@Configuration
public class RestTemplateConfiguration {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     *
     * @return a {@link RestTemplate} with a HAL converter
     */
    @Bean
    public RestTemplate restTemplate() {

        // converter
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(Arrays.asList(HAL_JSON));
        converter.setObjectMapper(objectMapper);

        RestTemplate restTemplate = new RestTemplate(Collections.singletonList(converter));

        return restTemplate;
    }

}

然后,让Spring注入需要使用REST后端的RestTemplate,并使用RestTemplate #exchange的众多变体之一:

@Autowired
public RestTemplate restTemplate;

...
// for a single ressource

// GET
Account newAccount = restTemplate.getForObject(url, Account.class);

// POST
Account newAccount = restTemplate.exchange(serviceUrl + "/accounts", HttpMethod.POST, entity, Account.class).getBody();
// or any of the specialized POST methods...
Account newAccount = restTemplate.postForObject(serviceUrl + "/accounts", entity, Account.class);

对于集合,您将操纵PagedResources

// for a collection
ParameterizedTypeReference<PagedResources<Account>> responseType =
        new ParameterizedTypeReference<PagedResources<Account>>() {};

// GET
PagedResources<Account> accounts =
        restTemplate.exchange(url, HttpMethod.GET, null, responseType).getBody();

//