java - working - Como os servlets funcionam? Instanciação, sessões, variáveis compartilhadas e multithreading




threads java ee (5)

ServletContext

Quando o contêiner do servlet (como o Apache Tomcat ) é inicializado, ele implementará e carregará todos os seus aplicativos da web. Quando um aplicativo da Web é carregado, o contêiner do servlet cria o ServletContext uma vez e o mantém na memória do servidor. O arquivo web.xml do aplicativo da web é analisado e cada <servlet> , <filter> e <listener> encontrado (ou cada classe anotada com @WebServlet , @WebFilter e @WebListener respectivamente) é instanciado uma vez e mantido na memória do servidor como bem. Para cada filtro instanciado, seu método init() é invocado com um novo FilterConfig .

Quando o contêiner do servlet é desligado, ele descarrega todos os aplicativos da Web, chama o método destroy() de todos os servlets e filtros inicializados e todas as ocorrências de ServletContext , Servlet , Filter e Listener são descartadas.

Quando um Servlet tem um valor <servlet><load-on-startup> ou @WebServlet(loadOnStartup) maior que 0 , seu método init() também é chamado durante a inicialização com um novo ServletConfig . Esses servlets são inicializados na mesma ordem especificada por esse valor (1 -> 1st, 2 -> 2nd, etc). Se o mesmo valor for especificado para mais de um servlet, cada um desses servlets será carregado na ordem em que aparecem no @WebServlet classe web.xml ou @WebServlet . Caso o valor "load-on-startup" esteja ausente, o método init() será invocado sempre que a solicitação HTTP atingir esse servlet pela primeira vez.

HttpServletRequest e HttpServletResponse

O contêiner do servlet é conectado a um servidor da Web que atende a solicitações HTTP em um determinado número de porta (a porta 8080 é geralmente usada durante o desenvolvimento e a porta 80 em produção). Quando um cliente (usuário com um navegador da Web) envia uma solicitação HTTP, o contêiner de servlet cria novos objetos HttpServletResponse e HttpServletResponse e os transmite por meio de qualquer cadeia de Filter definida e, eventualmente, a instância do Servlet .

No caso de filters , o método doFilter() é invocado. Quando seu código chama chain.doFilter(request, response) , a solicitação e a resposta continuam no próximo filtro ou atingem o servlet se não houver filtros restantes.

No caso de servlets , o método service() é chamado. Por padrão, esse método determina qual dos métodos doXxx() a invocar baseado fora de request.getMethod() . Se o método determinado estiver ausente do servlet, um erro HTTP 405 será retornado na resposta.

O objeto request fornece acesso a todas as informações sobre a solicitação HTTP, como seus cabeçalhos e corpo. O objeto de resposta fornece a capacidade de controlar e enviar a resposta HTTP da maneira desejada, por exemplo, permitindo que você defina os cabeçalhos e o corpo (geralmente com conteúdo HTML gerado a partir de um arquivo JSP). Quando a resposta HTTP é confirmada e concluída, os objetos de solicitação e resposta são reciclados e feitos para reutilização.

HttpSession

Quando um cliente visita o webapp pela primeira vez e / ou o HttpSession é obtido pela primeira vez via request.getSession() , o contêiner do servlet cria um novo objeto HttpSession , gera um ID longo e único (que você pode obter por session.getId() ) e armazene-o na memória do servidor. O contêiner do servlet também define um Cookie no cabeçalho Set-Cookie da resposta HTTP com JSESSIONID como seu nome e o ID da sessão exclusiva como seu valor.

De acordo com a especificação do cookie HTTP (um contrato que um navegador da web decente e um servidor da web têm de aderir), o cliente (o navegador da web) é obrigado a enviar esse cookie de volta em solicitações subsequentes no cabeçalho Cookie enquanto o cookie for válido (ou seja, o ID exclusivo deve se referir a uma sessão não expirada e o domínio e o caminho estão corretos). Usando o monitor de tráfego HTTP embutido do seu navegador, você pode verificar se o cookie é válido (pressione F12 no Chrome / Firefox 23+ / IE9 + e verifique a guia Rede / Rede ). O contêiner do servlet verificará o cabeçalho Cookie de cada solicitação HTTP recebida quanto à presença do cookie com o nome JSESSIONID e usará seu valor (o ID da sessão) para obter o HttpSession associado da memória do servidor.

O HttpSession permanece ativo até que não tenha sido usado por mais do que o valor de tempo limite especificado em <session-timeout> , uma configuração no web.xml . O valor do tempo limite é padronizado para 30 minutos. Portanto, quando o cliente não visita o aplicativo da web por mais tempo do que o especificado, o contêiner do servlet recolhe a sessão. Toda solicitação subseqüente, mesmo com o cookie especificado, não terá mais acesso à mesma sessão; o contêiner do servlet criará uma nova sessão.

No lado do cliente, o cookie de sessão permanece ativo enquanto a instância do navegador estiver em execução. Portanto, se o cliente fechar a instância do navegador (todas as guias / janelas), a sessão será descartada no lado do cliente. Em uma nova instância do navegador, o cookie associado à sessão não existiria e, portanto, não seria mais enviado. Isso faz com que uma sessão de HTTPSession inteiramente nova seja criada, com um cookie de sessão inteiramente novo sendo usado.

Em poucas palavras

  • O ServletContext vive enquanto o aplicativo da web vive. É compartilhado entre todas as solicitações em todas as sessões.
  • O HttpSession vive enquanto o cliente estiver interagindo com o aplicativo da Web com a mesma instância do navegador e a sessão não expirou no servidor. É compartilhado entre todas as solicitações na mesma sessão.
  • O HttpServletRequest e o HttpServletResponse residem no momento em que o servlet recebe uma solicitação HTTP do cliente, até que a resposta completa (a página da web) tenha chegado. Não é compartilhado em outro lugar.
  • Todas as instâncias de Servlet , Filter e Listener estão ativas enquanto o aplicativo da web estiver ativo. Eles são compartilhados entre todas as solicitações em todas as sessões.
  • Qualquer attribute definido em ServletContext , HttpServletRequest e HttpSession HttpServletRequest HttpSession enquanto o objeto em questão existir. O objeto em si representa o "escopo" em estruturas de gerenciamento de beans, como JSF, CDI, Spring, etc. Essas estruturas armazenam seus beans com escopo definido como um attribute de seu escopo correspondente mais próximo.

Segurança de Roscas

Dito isto, a sua maior preocupação é possivelmente a segurança dos fios . Agora você deve saber que os servlets e filtros são compartilhados entre todas as solicitações. Essa é a coisa legal do Java, ele é multissegmentado e threads diferentes (leia-se: solicitações HTTP) podem fazer uso da mesma instância. Caso contrário, seria muito caro recriar, init() e destroy() para cada solicitação.

Você também deve perceber que nunca deve atribuir dados de escopo de solicitação ou sessão como uma variável de instância de um servlet ou filtro. Ele será compartilhado entre todas as outras solicitações em outras sessões. Isso não é thread-safe! O exemplo abaixo ilustra isso:

public class ExampleServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

Veja também:

Suponha que eu tenha um servidor que contém vários servlets. Para informações transmitidas entre esses servlets, estou configurando variáveis ​​de sessão e instância.

Agora, se dois ou mais usuários enviarem solicitação para esse servidor, o que acontece com as variáveis ​​da sessão? Serão todos comuns para todos os usuários ou serão diferentes para cada usuário? Se eles são diferentes, como o servidor foi capaz de diferenciar usuários diferentes?

Mais uma pergunta semelhante, se houver n usuários acessando um determinado servlet, esse servlet será instanciado apenas na primeira vez que o primeiro usuário o acessou ou será instanciado para todos os usuários separadamente? Em outras palavras, o que acontece com as variáveis ​​de instância?


Sessões

Resumindo: o servidor web emite um identificador único para cada visitante em sua primeira visita. O visitante deve trazer de volta esse documento para que ele seja reconhecido na próxima vez. Esse identificador também permite que o servidor segregar corretamente objetos pertencentes a uma sessão em relação a outra.

Instanciação de servlet

Se o carregamento no arranque for falso :

Se o carregamento na inicialização for verdadeiro :

Quando estiver no modo de serviço e na ranhura, o mesmo servlet funcionará nas solicitações de todos os outros clientes.

Por que não é uma boa ideia ter uma instância por cliente? Pense sobre isso: você vai contratar um cara de pizza para cada pedido que veio? Faça isso e você estará fora do negócio em nenhum momento.

Ele vem com um pequeno risco embora. Lembre-se: esse cara solteiro possui todas as informações do pedido em seu bolso: portanto, se você não for cauteloso sobre segurança de thread em servlets , ele pode acabar dando a ordem errada a um determinado cliente.


A sessão em servlets Java é igual à sessão em outras linguagens, como o PHP. É exclusivo para o usuário. O servidor pode rastreá-lo de maneiras diferentes, como cookies, reescrita de url, etc. Este artigo doc Java explica isso no contexto de servlets Java e indica que exatamente como a sessão é mantida é um detalhe de implementação deixado para os projetistas do servidor. A especificação apenas estipula que ela deve ser mantida como exclusiva para um usuário em várias conexões com o servidor. Confira este artigo da Oracle para mais informações sobre as duas perguntas.

Edit Há um excelente tutorial here sobre como trabalhar com a sessão dentro de servlets. E here está um capítulo da Sun sobre Java Servlets, o que eles são e como usá-los. Entre esses dois artigos, você deve poder responder a todas as suas perguntas.


Quando o contêiner de servlet (como o Apache Tomcat) é inicializado, ele lê o arquivo web.xml (somente um por aplicativo) se algo der errado ou exibe um erro no console do contêiner, caso contrário, ele implantará e carregará todos os arquivos da web. aplicativos usando web.xml (assim chamado como descritor de implementação).

Durante a fase de instanciação do servlet, a instância do servlet está pronta, mas não pode atender à solicitação do cliente porque está faltando duas informações:
1: informação contextual
2: informações iniciais de configuração

O mecanismo de servlet cria o objeto de interface servletConfig encapsulando as informações ausentes acima no mecanismo de servlet, chama init () do servlet fornecendo referências de objeto servletConfig como um argumento. Uma vez que o init () é completamente executado, o servlet está pronto para atender a requisição do cliente.

Q) No tempo de vida do servlet quantas instanciações e inicializações acontecem ??

A) apenas uma vez (para cada solicitação do cliente um novo segmento é criado) apenas uma instância do servlet serve qualquer número do pedido do cliente, ou seja, depois de servir um servidor de pedidos do cliente não morre. Ele espera por outras solicitações do cliente, ou seja, qual CGI (para cada solicitação do cliente, um novo processo é criado), a limitação é superada com o servlet (o mecanismo de servlet internamente cria o encadeamento).

Q) Como funciona o conceito de sessão?

A) sempre que getSession () é chamado no objeto HttpServletRequest

Etapa 1 : o objeto de solicitação é avaliado para ID de sessão recebida.

Etapa 2 : se o ID não estiver disponível, um novo objeto HttpSession é criado e seu ID de sessão correspondente é gerado (por exemplo, de HashTable) O ID de sessão é armazenado no objeto de resposta httpservlet e a referência do objeto HttpSession é retornada ao servlet (doGet / doPost) .

Etapa 3 : se ID disponível novo objeto de sessão não for criado, o ID de sessão é selecionado a partir da pesquisa de objeto de solicitação na coleção de sessões usando a ID de sessão como a chave.

Depois que a pesquisa é bem-sucedida, a ID da sessão é armazenada em HttpServletResponse e as referências de objetos de sessão existentes são retornadas para o doGet () ou doPost () do UserDefineservlet.

Nota:

1) quando o controle sai do código do servlet para o cliente, não esqueça que o objeto da sessão está sendo mantido pelo contêiner do servlet, isto é, o mecanismo do servlet

2) multithreading é deixado para servlet desenvolvedores pessoas para implementar ou seja, lidar com os vários pedidos de cliente nada se preocupar com código multithread

Forma Inshort:

Um servlet é criado quando o aplicativo é iniciado (implementado no contêiner do servlet) ou quando é acessado pela primeira vez (dependendo da configuração de carregamento na inicialização) quando o servlet é instanciado, o método init () do servlet é chamado em seguida, o servlet (sua única instância) manipula todas as solicitações (seu método service () é chamado por vários encadeamentos). É por isso que não é aconselhável ter qualquer sincronização nele e você deve evitar variáveis ​​de instância do servlet quando o aplicativo é removido (o contêiner de servlet para), o método destroy () é chamado.


Sessões - o que Chris Thompson disse.

Instanciação - um servlet é instanciado quando o contêiner recebe a primeira solicitação mapeada para o servlet (a menos que o servlet esteja configurado para carregar na inicialização com o elemento <load-on-startup> no web.xml ). A mesma instância é usada para atender a solicitações subsequentes.





instance-variables