Tomcat如何禁用session

有时候我们不需要用到session,而session在tomcat中是属于关键功能,它在启动的时候会自动创建,这样就会消耗一定的内存空间,如果访问量大了session就会产生很多。这样也不利于我们进行分布扩展。
 

JSESSIONID的产生机制

tomcat只有在程序中使用了 xxx.getSession() 的时候才会创建session(JSESSIONID是它的标识),其他任何时候都不会主动去创建。

这个时候有人问了,我的程序里明确没有调用 xxx.getSession(),为什么还会创建session?原因是用到了jsp作为渲染机制,你去看一下在tomcat的工作目录中所对应的jsp编译好的.class或者也有.java文件,能够看到:session = pageContext.getSession();这样一段代码。这个session也就是jsp几个内置对象中含有session对象的来源。所以,只要你用到了 jsp,那么就会默认产生session。 

那不用jsp,而用 servlet 的话,会不会主动创建 session 呢?不会的,因为对于Controller或者Action来说,本质上还是servlet。不会的,除非你自己写 xxx.getSession()。

那我也不用jsp,用其他的模板引擎,比如 freemarker 或者 Thymeleaf,会不会主动创建 session 呢?不会的,除非这个模板引擎中也主动调用xxx.getSession,否则不会。

那我既不用jsp,也不用servlet,用的是 spring的Controller或者 struts 的Action,那会不会主动创建 session 呢?不会的,因为对于Controller或者Action来说,本质上还是servlet。

解决办法

通过上面的机制分析,很明显禁用tomcat的session的最好途径就是告诉jsp,不要主动创建session,那么方式是在每个jsp页面中加入:

<%@ page session="false" %>

这种方式需要在每一个jsp页面加入以上代码,或者引用共同的jsp。如果某一个页面忘记引用或者是JAVA部分代码主动的去获取了xxx.getSession(),那么还是会产生session。

所以本人倾向于第二种方式,在tomcat中停止创建session,自定义一个SessionManager

package com.noSession;

import java.io.IOException;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Session;
import org.apache.catalina.session.ManagerBase;

public class SessionManager extends ManagerBase implements Lifecycle {

	@Override
	protected synchronized void startInternal() throws LifecycleException {

		super.startInternal();
		setState(LifecycleState.STARTING);
	}

	@Override
	protected synchronized void stopInternal() throws LifecycleException {

		setState(LifecycleState.STOPPING);
	}

	@Override
	public void load() throws ClassNotFoundException, IOException {
	}

	@Override
	public void unload() throws IOException {
	}

	@Override
	public Session createSession(String sessionId) {

		return null;
	}

	@Override
	public Session createEmptySession() {

		return null;
	}

}

注意,上面这个SessionManager中createSession、createEmptySession方法返回的是null。

在使用jsp的时候会报错Page needs a session and none is available。

有一下两种解决方案:

1.在jsp中加上

<%@ page session="false" %>

2.全局使用同一个session

import java.io.IOException;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Session;
import org.apache.catalina.session.ManagerBase;

public class SessionManager extends ManagerBase implements Lifecycle {

    private Session globalSession;

    @Override
    protected synchronized void startInternal() throws LifecycleException {
        super.startInternal();
        setState(LifecycleState.STARTING);
    }

    @Override
    protected synchronized void stopInternal() throws LifecycleException {
        setState(LifecycleState.STOPPING);
    }

    @Override
    public void load() throws ClassNotFoundException, IOException {
    }

    @Override
    public void unload() throws IOException {
    }

    @Override
    public Session createSession(String sessionId) {
        if(globalSession == null) {
            globalSession = super.createSession(sessionId);
        } else {
            globalSession.setValid(true);
        }

        return globalSession;
    }

    @Override
    public Session createEmptySession() {
        if(globalSession == null) {
            globalSession = super.createSession(sessionId);
        } else {
            globalSession.setValid(true);
        }

        return globalSession;
    }

}

还需要注意这个globalSession需要进行激活,否则在tomcat的session失效后,会将此session标注为失效,那么尽管globalSession还是存在的,但是是失效的状态,还是会报错说session不存在。所以globalSession.setValid(true);这句很重要。

然后,在tomcat的server.xml中进行设置,或者配置host的其他方式

<Context docBase="D:\test" path="/test" reloadable="false" sessionCookieName="yoursessionname">
    <Manager className="xxx.xxx.SessionManager" />
</Context>

上面的sessionCookieName默认是JSESSIONID,其实这个是有点点缺陷的,能够让别人知道你的应用是用java开发的,所以,换个其他的名字会更好一些。

最后,将SessionManager打包为jar包,放到tomcat的lib文件夹下面

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值