Basicamente o client solicita o recurso e informa em qual formato deseja receber a representação, ou seja, ele negocia o conteúdo com o servidor. Para isso o client fará uma requisição GET e colocará no request header o atributo Accept com o valor desejado: application/xml, application/json e etc...
Nosso recurso irá fornecer a representação de um funcionário e além dos formatos como xml e json, neste post também faremos uma implementação que representa o funcionário através de uma imagem.
Caso o cliente consiga trabalhar com mais de um media type, ele pode informar a ordem de prioridade, colocando o media type preferido primeiro, precedido dos menos importantes, separados por vírgula
Ex: Accept: application/xml, application/json
Cabe esclarecer que caso o client solicite o recurso em um media type que o servidor não fornece, deverá ser retornada uma resposta com o código 406 Not Acceptable.
@Path("/funcionarios") public class FuncionarioResource { @GET @Path("{id}") @Produces({ "application/xml", "application/json" }) public Funcionario getFuncionario(@PathParam("id") Integer id) { Funcionario funcionario = repository.get(id); return funcionario; } }
Serei breve nas explicações das anotações básicas tendo em vista que existem excelentes materiais na web e focarei no necessário para a negociação de conteúdo.
A anotação @Path("/funcionarios") informa a url da nossa RootResource.
Em seguida anotamos nosso método getFuncionario com a anotação @GET que informa que este método aceita apenas requisições feitas pelo método GET do http, isso quer dizer que nosso método é idempotente, não importa quantas vezes a requisição seja feita, ela não alterará o estado do recurso.
Também anotamos o método com @Path("{id}"), informando que devemos passar o id do funcionário na URI. Para que consigamos acessar o recurso devemos usar o caminho funcionarios/1 por exemplo.
Como parâmetro o método espera o id do funcionário. Anotamos esse parâmetro com @PathParam("id") para que seja injetado na nossa variável id o valor passado pela URI conforme indicado na anotação @Path("{id}").
Para o assunto tratado a mais importante é a anotação @Produces({"application/xml", "application/json"}), ela informa que este método retorna o nosso recurso tanto em XML quanto JSON dependendo apenas da solicitação do cliente. A implementação JERSEY se responsabiliza em parsear o recurso para estes formatos então precisamos apenas retornar nosso recurso: Funcionario funcionario = repository.get(id);
Agora vamos expor nosso recurso como uma imagem. Para isso, precisamos fazer nossa própria implementação, que é transformar nosso recurso em uma imagem. Neste caso vamos usar o atributo caminhoFoto para buscar a foto e retorná-la como um array de bytes.
Note que são usadas as mesmas anotações no método getFuncionario e no getFoto, inclusive o @Path é o mesmo. A única diferença é que o método getFoto retorna media types do tipo "image/jpeg" ou "image/jpg".
Como o valor da anotação @Path é o mesmo, oque determina qual método atenderá a requisição é justamente o tipo de media type aceito pelo client.
Caso ele envie uma requisição com Accept: application/xml ou application/json o método getFuncionario será invocado, ou então, caso a requisição possua Accept: image/jpeg ou image/jpg, o método getFoto será invocado.
No meu github tem a implementação completa do projeto que pode ser publicado em qualquer servlet container, desenvolvido com maven.
Espero que o post possa ser útil.
Abrasssss
A anotação @Path("/funcionarios") informa a url da nossa RootResource.
Em seguida anotamos nosso método getFuncionario com a anotação @GET que informa que este método aceita apenas requisições feitas pelo método GET do http, isso quer dizer que nosso método é idempotente, não importa quantas vezes a requisição seja feita, ela não alterará o estado do recurso.
Também anotamos o método com @Path("{id}"), informando que devemos passar o id do funcionário na URI. Para que consigamos acessar o recurso devemos usar o caminho funcionarios/1 por exemplo.
Como parâmetro o método espera o id do funcionário. Anotamos esse parâmetro com @PathParam("id") para que seja injetado na nossa variável id o valor passado pela URI conforme indicado na anotação @Path("{id}").
Para o assunto tratado a mais importante é a anotação @Produces({"application/xml", "application/json"}), ela informa que este método retorna o nosso recurso tanto em XML quanto JSON dependendo apenas da solicitação do cliente. A implementação JERSEY se responsabiliza em parsear o recurso para estes formatos então precisamos apenas retornar nosso recurso: Funcionario funcionario = repository.get(id);
Agora vamos expor nosso recurso como uma imagem. Para isso, precisamos fazer nossa própria implementação, que é transformar nosso recurso em uma imagem. Neste caso vamos usar o atributo caminhoFoto para buscar a foto e retorná-la como um array de bytes.
@GET @Path("{id}") @Produces({ "image/jpeg", "image/jpg" }) public byte[] getPhoto(@PathParam("id") Integer id) { Funcionario funcionario = repository.get(1); try { InputStream is = this.getClass().getResourceAsStream(funcionario.getCaminhoFoto()); BufferedImage img = ImageIO.read(is); ByteArrayOutputStream bao = new ByteArrayOutputStream(); ImageIO.write(img, "jpg", bao); return bao.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } }
Note que são usadas as mesmas anotações no método getFuncionario e no getFoto, inclusive o @Path é o mesmo. A única diferença é que o método getFoto retorna media types do tipo "image/jpeg" ou "image/jpg".
Como o valor da anotação @Path é o mesmo, oque determina qual método atenderá a requisição é justamente o tipo de media type aceito pelo client.
Caso ele envie uma requisição com Accept: application/xml ou application/json o método getFuncionario será invocado, ou então, caso a requisição possua Accept: image/jpeg ou image/jpg, o método getFoto será invocado.
No meu github tem a implementação completa do projeto que pode ser publicado em qualquer servlet container, desenvolvido com maven.
Espero que o post possa ser útil.
Abrasssss