Eu tenho um método que é anotado da seguinte maneira:
/**
* Provide a list of all accounts.
*/
// TODO 02: Complete this method. Add annotations to respond
// to GET /accounts and return a List<Account> to be converted.
// Save your work and restart the server. You should get JSON results when accessing
// http://localhost:8080/rest-ws/app/accounts
@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
return accountManager.getAllAccounts();
}
Então eu sei que por esta anotação:
@RequestMapping(value="/orders", method=RequestMethod.GET)
este método manipula solicitações GET HTTP feitas ao recurso representado pela URL / pedidos .
Este método chama um objeto DAO que retorna uma Lista .
onde Conta representa um usuário no sistema e tem alguns campos que representam esse usuário, como:
public class Account {
@Id
@Column(name = "ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long entityId;
@Column(name = "NUMBER")
private String number;
@Column(name = "NAME")
private String name;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name = "ACCOUNT_ID")
private Set<Beneficiary> beneficiaries = new HashSet<Beneficiary>();
...............................
...............................
...............................
}
Minha pergunta é: como exatamente funciona a @ResponseBody
anotação?
Ele está situado antes do List<Account>
objeto retornado, então acho que se refere a esta Lista. A documentação do curso afirma que esta anotação tem a função de:
certifique-se de que o resultado será gravado na resposta HTTP por um conversor de mensagem HTTP (em vez de uma visualização MVC).
E também lendo sobre a documentação oficial do Spring: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html
parece que pega o List<Account>
objeto e o coloca no Http Response
. Isso é correto ou estou entendendo mal?
Escrito no comentário do accountSummary()
método anterior , há:
Você deve obter resultados JSON ao acessar http: // localhost: 8080 / rest-ws / app / accounts
Então, o que exatamente isso significa? Isso significa que o List<Account>
objeto retornado pelo accountSummary()
método é automaticamente convertido para o JSON
formato e, em seguida, colocado no Http Response
? Ou o que?
Se esta afirmação for verdadeira, onde é especificado que o objeto será convertido automaticamente para o JSON
formato? O formato padrão é adotado quando a @ResponseBody
anotação é usada ou é especificado em outro lugar?
A primeira coisa básica a entender é a diferença nas arquiteturas.
De um lado, você tem a arquitetura MVC, que é baseada em seu aplicativo da web normal, usando páginas da web, e o navegador faz uma solicitação de uma página:
O navegador faz uma solicitação, o controlador (@Controller) obtém o modelo (@Entity) e cria a visualização (JSP) a partir do modelo e a visualização é retornada ao cliente. Esta é a arquitetura básica do aplicativo da web.
Por outro lado, você tem uma arquitetura RESTful. Nesse caso, não há Visualização. O Controlador apenas envia de volta o modelo (ou representação de recurso, em termos mais RESTful). O cliente pode ser um aplicativo JavaScript, um aplicativo de servidor Java, qualquer aplicativo ao qual expomos nossa API REST. Com essa arquitetura, o cliente decide o que fazer com este modelo. Tomemos, por exemplo, o Twitter. Twitter como a API da Web (REST), que permite que nossos aplicativos usem sua API para obter coisas como atualizações de status, para que possamos usá-la para colocar esses dados em nosso aplicativo. Esses dados virão em algum formato como JSON.
Dito isso, ao trabalhar com Spring MVC, ele foi construído primeiro para lidar com a arquitetura básica do aplicativo da web. Existem muitos sabores de assinatura de método diferentes que permitem que uma visualização seja produzida a partir de nossos métodos. O método pode retornar um
ModelAndView
onde nós o criamos explicitamente, ou existem maneiras implícitas onde podemos retornar algum objeto arbitrário que é definido nos atributos do modelo. Mas de qualquer maneira, em algum lugar ao longo do ciclo de solicitação-resposta, haverá uma visualização produzida.Mas quando usamos
@ResponseBody
, estamos dizendo que não queremos uma visualização produzida. Queremos apenas enviar o objeto de retorno como o corpo, em qualquer formato que especificarmos. Não queremos que seja um objeto Java serializado (embora possível). Então, sim, ele precisa ser convertido para algum outro tipo comum (esse tipo normalmente é tratado por meio da negociação de conteúdo - veja o link abaixo). Honestamente, não trabalho muito com o Spring, embora me divirta com ele aqui e ali. Normalmente, eu usopara definir o tipo de conteúdo, mas talvez JSON seja o padrão. Não me cite, mas se você está recebendo JSON e não especificou o
produces
, então talvez seja o padrão. JSON não é o único formato. Por exemplo, o texto acima pode ser facilmente enviado em XML, mas você precisa ter oproduces
paraMediaType.APPLICATION_XML_VALUE
e eu acredito que você precisa configurar oHttpMessageConverter
para JAXB. Quanto ao JSONMappingJacksonHttpMessageConverter
configurado, quando temos Jackson no classpath.Eu levaria algum tempo para aprender sobre negociação de conteúdo . É uma parte muito importante do REST. Isso o ajudará a aprender sobre os diferentes formatos de resposta e como mapeá-los para seus métodos.
fonte
@Controller/@RestController
. Eu descobri que preciso omitir de alguma forma a camada de resolução de visualizações Não é tão simples porque a classe AbstractController fornece um método que deve retornar o nome da visão. Eu fiz uma pergunta sobre isso: stackoverflow.com/questions/41016018/… , se você tiver algumas idéias sobre como posso resolver meu problema, por favor poste um comentário.Além disso, o tipo de retorno é determinado por
O que a solicitação HTTP diz que deseja - em seu cabeçalho Aceitar. Tente examinar a solicitação inicial para ver como Aceitar está definido.
O que HttpMessageConverters Spring configura. Spring MVC irá configurar conversores para XML (usando JAXB) e JSON se as bibliotecas Jackson estiverem no classpath.
Se houver uma opção, ele escolhe uma - neste exemplo, é JSON.
Isso é abordado nas notas do curso. Procure as notas sobre Conversores de mensagens e negociação de conteúdo.
fonte