Tomcat -> Session Timeout

9 respostas
I

Olá. Estou com dúvida de como avisar ao usuário que a sessão dele expirou. Na verdade meu problema é identificar que isto ocorreu e avisar ao usuário. Quando configura-se o Tomcat para o tempo de timeout de sessão faz-se algo do tipo dentro do web.xml da aplicação:

...
<session-config>
	<session-timeout>5</session-timeout>
</session-config>
...

Pois bem, após 5 minutos de a sessão do usuário estar inativa ela expira e quando o usuário tenta acessar o site ele é “chutado” pro login. Como tratar esta situação e avisar ao usuário que ele foi desligado do site porque o tempo de inatividade dele ultrapassou o limite configurado? Alguma dica? Valeu, T+

9 Respostas

R

É bem fácil, cara.
Imagino que no teu servlet tu devas estar controlando a sessão com algo como

Session sessao = request.getSession(); if (sessao == null) { // redireciona pra página de login }

Então, é só na hora que tu fores redirecionar, tu enviares ou um parâmetro, ou um atributo, pra que quando a página de login for carregada, ela vai procurar pelo parâmetro “tal”, se ele existir, daí é só tu exibires a mensagem de que expirou a sessão, se não, a jsp nem mostra nada.

[]s

I

Olá. Na verdade não faço este tipo de controle não. O próprio tomcat encarrega-se de carregar a página de login que é a index.jsp da minha aplicação. A única coisa que faço é aumentar ou diminuir o valor de sessão. Na verdade estou supondo que quando a sessão do usuário acaba por expirar e ele tentar acessar qualquer coisa dentro do site o meu action não é nem chamado, visto que algum filtro deve fazer a validação e ver que a sessão já acabou. Estuo usando Struts com minha aplicação, não sei até que ponto isto pode afetar.

Entendi o que tu explicou, mas ainda assim creio que meu action não é executado depois que a sessão expira. Então creio que o Tomcat deve redirecionar diretamente para a página inicial da aplicação sem passar por nenhum dos meus servlets. De qualquer forma obrigado pela dica. T+

I

Outra dúvida que me ocorre é que tenho um action de logout, que nada mais faz do que chamar o método invalidate() da sessão e ainda assim atribuo null a referência. Algo como:

//...
HttpsSession session = request.getSession();
session.invalidate();
session = null;
//...

Olhando pelo gerenciador de tarefas do Windows percebo que há muita memória alocada (a açlicação carrega muitos registros mesmo). Também fecho o browser e ao abrir o manager do Tomcat aparece uma sessão aberta. Por que isto ocorre? Como posso resolver isto? Grato, T+

R

Não sei mexer com a autenticação controlada pelo Tomcat. Ainda…

Quanto à sessão, imagino que depende de como ela foi criada, o tipo dela e tal. Tem um capítulo no livro do coreservlets que fala sobre isso. Não to lembrado agora exatamente o que tá escrito. Por acaso quando tu fazes o debug da aplicação, visse se tá passando na parte que invalida a sessão ?
É possível que ela não esteja sendo “morta” hehehe.

Quanto a memória, quanto tás achando que é muita ? Aqui, às vezes, dependendo do tanto de vezes que eu faço hot-deploy, chega a passar de 150 Mb de RAM que ele usa.

[]s

I

Acabei descobrindo que se pode criar um listener implementando HttpSessionListener que define os métodos sessionCreated e sessionDestroyed. Então dá pra controlar a quantidade de acessos e contá-las inclusive. A mesma classe implementa Filter e fico monitorando a memória para criar alarmes. Assim:

package com.common.action.analysis;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.suntech.vigiabrt.common.util.MemoryLogger;

public class MemorySessionFilter implements HttpSessionListener, Filter {
    private FilterConfig filterConfig;
    private int level = 15;
    private static final String MEMORY_LEVEL = "freeMemLevel";
    private static List sessions = new ArrayList();

    private static final Log LOG = LogFactory.getLog(MemorySessionFilter.class);

    public void sessionCreated(HttpSessionEvent se) {        
        HttpSession session = se.getSession();
        String idSession = session.getId();        
        LOG.debug("Creating session: " + idSession);
        MemoryLogger.showMemory();
        sessions.add(idSession);
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        String idSession = session.getId();        
        LOG.debug("Destroying session: " + idSession);
        MemoryLogger.showMemory();
        sessions.remove(idSession);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest sreq = (HttpServletRequest) req;
        final String servletPath = sreq.getServletPath();
        if (!"/reqLogout.do".equals(servletPath)) { 
            LOG.debug("Active Sessions: " + sessions.size());
            
            double max = (int) MemoryLogger.getMax();
            double total = (int) MemoryLogger.getTotal();
            if (total == max && isCritical(total)) {
                LOG.warn("Memory in a critical level");
                MemoryLogger.showMemory();
                HttpSession session = sreq.getSession();
                String sessionId = session.getId();
                //if (!sessions.contains(sessionId)) {
                    LOG.warn("Kicking user..." + sessionId);
                    System.gc();
                    ((HttpServletResponse) res).sendRedirect("reqLogout.do?cause=errors.low.memory");
                    return;
                //}
            }
        }
        chain.doFilter(sreq, res);
    }
    
    private boolean isCritical(double total) {
        String memoryLevel = filterConfig.getInitParameter(MEMORY_LEVEL);
        try {
            level = Integer.parseInt(memoryLevel);
            if (level < 0 || level > 100) throw new NumberFormatException();
            LOG.warn("Checking memory level: " + level);
        } catch (NumberFormatException e) {
            LOG.warn("\"memoryLevelPerc\" should be an integer value. Using 15%");
        }
        return (((100 * MemoryLogger.getFree()) / total) <= level);
    }

    public void destroy() {
        filterConfig = null;
    }

}

A memória nos testes que fiz aqui no Tomcat chega fácil em mais de 500MB (memória física + virtual)

R

Opa!

Essa classe aí resolveu o teu problema, então ?
Quanto a memória, nossa, 500 MB ? Cacilds!

[]s

I

Na verdade está como um paleativo… fica como um alarme quando o nível de consumo começa a ficar crítico. Quanto ao uso de memória há muito consumo sim. São gerados extratos muito longos pelos usuários. Acho que é bem possível que mais adiante tenhamos de partir para um custer mesmo. Valeu T+

H

Mas como deve ficar seu web.xml, o mapeamento desta classe.

Segue o link abaixo doque preciso fazer:

Expirar a Sessão + Operação

Se Puder me ajudar.

B

Ai galera, beleza?

Gostaria que me explicassem a diferença ou semelhança entre filter e listener.

Li alguns post em alguns sites, mas nao entendi.

Obrigado.

Criado 17 de agosto de 2006
Ultima resposta 19 de abr. de 2012
Respostas 9
Participantes 4