NETCTOSS代码实现第六版:Session的原理与应用

  • 前言
    • Session的原理与应用
      • 模拟Session应用案例需求分析:Session的运行原理
      • 模拟Session应用案例代码分析:Session的基本用法
      • 模拟Session应用案例代码实现
        • 1.jsp6/src/main/java/web/LoginServlet.java
        • 2.jsp6/src/main/java/web/LoginServlet.java
        • 3.jsp6/src/main/webapp/WEB-INF/web.xml
      • Session在NetCTOSS中的应用1:退出功能时实现销毁Session对象。
      • 小总结:Session的基本用法
      • 模拟Session应用案例:演示Session超时
        • 代码实现:jsp6/src/main/webapp/WEB-INF/web.xml
      • 关于Session的URL重写以及相关的面试想法
      • Session在NetCTOSS中的应用2:登录时记录保存账号并在登录后用以显示
      • Session在NetCTOSS中的应用2之代码实现
        • 1.src/main/java/web/MainServlet.java
        • 2.src/main/webapp/WEB-INF/logo.jsp
  • 写在后面

前言

  • 返回 NETCTOSS

Session的原理与应用

模拟Session应用案例需求分析:Session的运行原理

  • 那现在啊,这个cookie啊,我们就说完了,那下面呢,我们再说一下session,那cookie了解完以后,再去学session,就会很容易了,因为这两者,它们的用途是一样的,还是这个业务场景啊,登录时记帐号,在主页上,在查询时显示账号,还是这个套路,只不过呢,我们用session去存储这个数据,最终session是保存在服务器上,而不是在浏览器上,那么session的用途和cookie一样,但是用法不一样,语法不一样啊,所以我们需要学习一下它的语法,然后呢,我们还是利用之前的登录的案例,去阐述session的使用,那我把这个案例的这个程序的执行过程再画一下啊,另外呢,在这个例子当中呢,我也想讲一下,那这个session它工作,是怎么工作的,也讲一下它背后的一些原理,去体会一下。
  • 那我们还是以这个登录为例,左浏览器右服务器,服务器端呢,我把这个通信组件画出来,讲session的话,画出通信组件,有的事情呢,好解释,要不然,这个不好画,那首先呢,我们还是啊,先访问这个登录功能,访问登录的时候呢,我要输入一个路径,因为咱们是模拟案例,是简化的案例,那么它的路径呢,我写为什么呢,跟刚才的案例一样啊,之前那个jsp4的案例一样,还是啊,/main,然后呢,/login,即/main/login,然后呢,访问时啊,直接传参数啊,/main/login?user=xxx,张三,比如说,然后呢,我们一回车,浏览器呢,向服务器发出了请求,那服务器收到请求以后,这回我们不是创建cookie,而是要创建session,明白吧,然后呢,要把这个user,存到session里面去,当然我们访问的是服务器的谁呢,我们访问的是这个LoginServlet。
  • 然后,那你注意啊,我们要访问的是它啊,LoginServlet,当然了,我们在访问它之前,服务器接收到请求以后,服务器会自动的创建一个request,是这样吧,是吧,服务器会自动的创建request,不单如此,那么session也是由服务器自动创建的,这个session和cookie不一样,cookie我们要自己new,而session由服务器自动创建啊,那服务器什么时候创建呢,当我们首次访问服务器,首次调用session时就会创建,这个一会我们可以看一下啊,这个可以看出来。
  • 总之呢,当我们访问服务器的时候,服务器它会给我们创建一个session对象,自动的,然后呢,这个session我们将怎么获取呢,服务器做的也很巧妙,它把这个session呢,存到了request里,然后呢,它把request在调用Servlet时给了我,通过request传给了这个Servlet,所以在Servlet之内啊,我想取session怎么取呢,通过requset获取明白吧,就这样。
  • 然后呢,由Servlet向浏览器输出响应,请求结束,这是我们登录的模拟案例的执行的过程,大概是这样的,然后你注意啊,这个之前我也说了,每个浏览器访问服务器,都会有一个session,是这样吧,每个人去理发店都会有一个理发卡对吧,是吧,当然你别钻牛角尖,说我去理发店,就从来不带理发卡,你怎么解释,我解释不了,你别这么钻牛角尖,就假设每个人去都有一个理发卡,我们强调的是有,你别老说你没有。好了,每个人去理发店,都有一个理发卡,那个理发卡存在理发店,对吧,那你想啊,你走的时候,理发店既不给你理发卡,也不给你说任何的信息,你的理发卡下回来,还能找着么,找不着了,它肯定得告诉你点啥东西对吧,它一般会让你记住这理发卡的卡号对吧,下次来你报号,是这意思吧,一般卡号就是你的手机号么,对吧,报号就行了。
  • 所以呢,session呢,跟存到理发店的那个理发卡相似,再这个东西,由服务器创建,由理发店创建,而且它要自己留着,那么送这个客户走的时候,你得告诉它点什么对吧,告诉他什么呢,我们需要把这个对象的一个标识,标志告诉他啊,那这个对象,它有什么标志呢,它有id,就是说服务器啊,为了区别每一个客户的session,它给session呢,取了一个id,有id啊,那我们做个假设啊,假设,我所,就是这次啊,创建的这个session,它的id是,就SID吧,假设啊,这个id是SID,这是session的id。
  • 那么在这个响应的时候呢,服务器呢,会自动的,把session发送给浏览器,让浏览器呢,存sessionID,而且呢,浏览器下次再访问服务器时还得出示这个id,这个能理解么,我去理发店,办了个理发卡,走到时候,理发店告诉我,记录你的卡号啊,你得手机号,记住了,下次我来,我得报我的手机号,对吧,报卡号,他要找到那个卡,好用啊,那你想啊,咱们这不是理发店,这是这个浏览器服务器啊,那服务器怎么给浏览器发送一个数据,浏览器才能在下次访问 时,会自动传这个数据,在什么场景下,浏览器会自动传一个数据给服务器,能想出来么,可能大家想的有点过于复杂了,其实很简单,利用cookie,咱们刚刚学了cookie,如果说我把cookie给了浏览器,浏览器会自动存,浏览器再访问我的时候,是不是会再传入cookie啊,传回cookie啊,对吧,就是利用cookie。
  • 所以在响应的时候啊,这个服务器,它会自动的new一个cookie,自动的,然后呢,把这个sessionId就存到这个cookie里,然后呢,它把这个cookie发送给浏览器,那么浏览器呢,就会得到这个cookie,那你想啊,浏览器得到这个cookie以后,它是不是会自动保存啊,对吧,它会自动保存的,然后呢,当浏览器再次访问服务器的其他的功能的时候,比如说,它访问谁呢,访问这个,咱们就一步到位,直接访问查询吧,主页我就不写了,/cost/find,那访问查询的时候,它会自动的把这个cookie呢,传回,那有人说,这应该不会吧,这cookie为什么会传回呢,这俩路径不一样对吧,那你注意,服务器呢,在new这个cookie的时候,它把cookie有效路径,设置为整个项目,听明白了么,就是,它new完cookie以后,它会把这个cookie的有效路径,设置成项目,就是整个项目之下,这个cookie都是适用的,它的范围是挺大的,所以会自动传回的。
  • 那么传回的时候呢,那么这回,因为浏览器传回了sessionId,那么,服务器一看,哎,有SID,我就没有必要创建新的session了,那你像/main/login?user=xxx,这个请求为什么没有,没有传SID,它才创建新的session,明白吧,就是浏览器访问服务器,首次访问时,它没有传任何数据,所以浏览器,只能给它创建一个新的session,那么如果说,某个请求里呢,那么浏览器传回了,数据里带有了sessionId,那么服务器呢,不会创建新的session,那怎么办呢,它去找这个旧的session,明白吧,根据id找旧的,复用,就像你第二次去理发店,你告诉他卡号,他找那个之前的卡,复用就可以了。
  • 所以,这是第二个请求啊,/cost/find,那在这个请求之内啊,这个服务器不会再去创建新的session了,它是找到一个旧的,是寻找,根据id去寻找,那最终呢,那肯定,因为之前存了么对吧,它会呢,找到之前保存的SID,找到以后呢,它就找到这个session了,找到的session,那么,服务器会创建request,然后呢,服务器会把这个,找到的那个旧的session,再放到这个/cost/find请求的request里,然后呢,把这个request给谁呢,给我们本次要访问的Servlet啊,本次我要访问的是,FindCostServlet,这样。然后呢,由FindCostServlet,它做出响应,请求结束,这是第二个请求。
  • 再看啊,再看,咱们再归纳一下啊,就是说,关于session的使用,它不像cookie,session呢,它是不需要我们自己去实例化的,是由服务器自动管理,自动实例化的,然后呢,每个浏览器,服务器都会给它new一个session,就一个,明白吧,没有第二个,就是一个,什么时候new呢,第一次访问时new,然后以后,浏览器再访问的话,不会new新的Session了,而是根据之前的id,找到旧的,明白吧,复用,就是这样。所以呢,我们第一次访问服务器的时候,服务器会一看啊,没有传任何数据,它就new了一个session,有id,然后把session存到request,通过request,把session呢,给了Servlet,所以在这里呢,我们就可以通过request得到这个session,去用它啊,去存数据。
  • 然后呢,响应时浏览器创建cookie,通过cookie,把sessionId呢,传给浏览器,浏览器保存的只是一个SID而已,然后呢,浏览器再访问服务器时啊,它会把这个SID,再传回,然后呢,服务器一看啊,有id了,它就找到对应的session,然后呢,把找到的session,存到request里,把request给了我们这次调用的Servlet啊,FindCostServlet,所以我没在这里,可以得到,可以顺藤摸瓜,找到这个旧的session对吧,得到这个旧的数据,就是这样,那么session呢,它最主要的特点是什么呢,第一个,它由服务器自己管理,不用我们自己去创建,第二点,session它依赖于cookie,是吧,依赖于cookie,所以为什么我们先讲cookie呢,因为不讲cookie的话,这个session没法讲,它们是有依赖关系的。那大概呢,了解一下这个程序执行的这个过程,这块有一个地方,我再标一下,第一个请求/main/login?user=xxx,这个地方是什么呢,是new,new了一个session,实例化啊,session就是个对象,第二个请求,/cost/find,这个地方呢,是找到旧的session,没什么了。

模拟Session应用案例代码分析:Session的基本用法

  • 那下面呢,我们就写这个例子啊,把这个Session的基本的使用方式了解一下,怎么去获取Session,怎么往里存数据,怎么得到旧的Session,怎么取到那个数据,给你演示一下,那这个案例啊,咱们在写的时候呢,咱们再新建一个项目,建一个新的项目,打开你的开发工具啊,eclipse,那按照顺序呢,我们建一个新的项目,叫jsp5,打包方式为war。Generate Deployment Descriptor StubProperties for jsp5/Targeted Runtimes/Apache Tomcat v7.0。当然你建完项目以后啊,还要那个点Generate..,把叉去掉,还要导包啊,你依赖于tomcat自带的包啊。

  • 然后啊,我们就先写这个LoginServlet,然后呢,关键是在这里,我要获取到这个Session,我要往session中呢,存一份数据,存什么,存那个user啊,那我们先写这个LoginServlet啊,那么在src/main/java下,建个包叫web。

  • web之下,创建这个Servlet,LoginServlet。

  • 那么创建完这个Servlet以后啊,我们要重写父类的service方法,然后呢,处理请求,然后我们还是模拟啊,简单处理,重写父类的service方法,那这个方法啊,我们还是模拟的是那个MainServlet当中的login()方法,登录的功能。这个登录功能,首先我们还是获取页面传入的参数user,先取user,String user = req.getParameter("user");,那取到user以后啊,我想把user存入session,那这个session不用我们自己new,我把这件事呢,在这自己再写一下,强化一下这个记忆啊,就是首次调用Session时,那么服务器会自动给当前访问的浏览器创建一个session啊,首次调用session时,服务器,就tomcat啊,它会自动创建一个session,这个session给谁用呢,给当前正在访问的那个浏览器用明白吧,当前谁访问就是给谁的,浏览器里有一些标识啊,它能识别。

  • 那有人说,首次调用,这没调啊,那下面就要调对吧,怎么调呢,通过request去调,req.getSession();,你这一调就有了,它底层就创建了,你不调就没有。说白了,这个getSession方法的底层的大概的逻辑是这样的啊,它判断if,变量session==nullnew Session,明白吧,所以你没调它,这个session还是空的,明白吧,那你一调发现空了,就new了,如果不空的话,就去找明白吧,总之它有这样的一个逻辑。

  • 那我们得到的是什么呢,得到的是HttpSession,这样的一个类型啊,一般我们就简称为session,就可以了,HttpSession session = req.getSession();。这个session这个词,咱们好像挺熟悉啊,以前我们在哪提过这个词,我们在哪提过,隐含对象对吧,哎,jsp的9个隐含对象中有一个就叫session,是这样吧,你看这个session和那个有什么关系呢,我们说的这个session,就是那个隐含对象,那个隐含对象,就是这个东西,明白了吧,就是一个东西,只不过我们以前说没讲,我们说将来再讲么对吧,将来是什么时候,就是现在,明白吧,就是再写一下啊,省的过后你又忘了啊,就是该session是jsp的隐含对象之一啊,就是那个。换句话说啊,我们在jsp上可以直接写session点,明白吧,可以直接访问。

  • 那得到了HttpSession这个对象以后,我要往里存值,存的是user,那怎么存呢,非常的容易啊,那session.setAttribute("user", user);,就行了,那你看,它的方法其实和request差不多是吧,一样是吧,也是 setAttribute(name,value),然后呢,这个第一个参数是数据的名字,第2个参数是值,就变量啊,那么你看啊,setAttribute(name,value),这个方法的声明里,第2个参数,就这个值value,那你看什么类型,Object对吧,

    void javax.servlet.http.HttpSession.setAttribute(String arg0, Object arg1)
    Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could be found.

  • 说明什么呢,我们往这个对象中存值,存什么都行对吧,没有限制,它不像cookie有限制,那为什么它没有限制呢,因为session对象最终存在服务器上,服务器可以识别java的类型对吧,所以没关系,而cookie要发送给浏览器,浏览器无法识别java,所以只能是字符串,这就是差别啊。写一下啊,那么session中可以存任意类型的数据。你看啊,咱们讲cookie也好,讲session也罢,我们老提这样一个话题,就是说,我要往这个对象里存数据,那cookie和session这样的对象,是用来存一些数据的,那有人可能会想,哎,对象中存数据,那这个数据,为什么不存到数据库里呢,你看我们现在是往对象中存一份数据对吧,那我这个数据不是也可以存到数据库里么,对吧。

  • 那数据存到对象里和存到数据库里,这有什么区别么,这个效率高,为啥效率高呢,就是读取的效率高,是吧,因为对象存到内存里,我们从内存中取数,比从数据库里取数,应该更快,为啥呢,其实以前也说过,为什么呢。

  • 我再打开个界面吧,就比如说这个资费查询,之前我也说过,有可能啊,浏览器在北京,服务器在杭州,数据库在上海,明白吧,有可能在不同的地方,那你想啊,咱们服务器上,我们在这里要想取数,我们从对象中取数,我们对象存到服务器的内存里,就在这对吧,就存在杭州对吧,是不是快啊,是这样吧,你看我们在MainServlet里要取内存中的数据,我们存某个对象中的数据,对象存于内存当中,存于服务器的内存里,它就在杭州,快啊。那么,数据库可能装在上海,那我从杭州访问上海,这个是不是有网络开销啊,就有点慢,所以我们从内存中取数要比数据库要快,所以这一点没问题。

  • 但这不是最关键的,还有区别,就是我们把数据存到,那你既然说,要把数据存到对象里,这个更快,那你想一下,那为什么我还有数据库呢,咱们干脆把所有数据,都存到对象里算了啊,更快啊,内存有限,我加大内存啊,我购买内存啊,你又说对了,因为存到内存里的数据,它能永久保存么,什么时候会没呢,不是断电,我服务器一关,还有么,是吧,我服务器一关,是不是内存就释放了啊,对吧,就没了,但存到数据库里的数据,是永久保存的,就哪怕说我当前断电了,这个一启动还有对吧,明白这意思吧,所以数据啊,我们可以存到内存里,可以存到数据库里,区别在于什么呢,数据库中的数据呢,是永久保存的,内存中的数据是临时的,对吧,是临时的,那你想啊,我们像登录时存的账号,这个账号是要永久保存,还是临时的呢,就临时的,我什么时候把电脑一关,没有就算了,对吧,不需要了,我下次再登录,再有呗,对吧,是这样吧,不用永久保存。


@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {String user = req.getParameter("u   ser");//首次调用session时服务器会自动给//当前访问的浏览器创建一个session//该session是jsp的隐含对象之一HttpSession session = req.getSession();//session中可以存任意类型的数据session.setAttribute("user", user);//Cookie c = new Cookie("JSESSIONID",session.getId())//session.getId();//试一下可以点出getId这个方法//c.setPath(request.getContextPath());//response.addCookie(c);
}

  • 所以你要把这个存储的这个关系,搞清楚,那刚才,我们新写的那段代码,很简单,想用session,通过request获取对吧,取到了,取到之后存,这特别简单,这就完了,那存完以后啊,当服务器,向浏览器发出响应的时候,它会自动的去new Cookie,自动的将cookie的路径设置为项目,然后自动的发送cookie,一切都是自动的,但这件事呢,我把它注释里写一下,大家加深印象啊,就是服务器响应时会做出如下处理,

    Cookie c = new Cookie("JSESSIONID",session.getId());
    session.getId();

  • 你可以试一下,session点id,你看能不能点出来,有没有这个方法,有吧,可以得到id啊。所以呢,服务器响应时,它会自动的new一个cookie,然后呢,这个cookie的值,就是session的id,名字,它固定就叫JSESSIONID,为啥叫JSESSIONID,J代表java,因为什么呢,像不同的语言,它都有session明白吧,因为你不管是什么语言,运行在服务器上,都是要解决,处理这个http协议,别管是php啊,dotNet啊,它里面都有session,明白吧,所以为了和其他语言,加以区分,它叫JSESSIONID啊,不但如此啊,它还会自动的设置这个cookie的有效路径,c.setPath(),设置为什么呢,c.setPath(request.getContextPath());,那你看啊,c点setPath的值是request.getContextPath()getContextPath得到的是什么啊,就是项目名对吧,所以把这个路径设置为项目路径啊,然后呢,再发送给这个cookie,就response.addCookie(c);

  • 那么总之啊,服务器响应时会做这样的一个处理,那么,这件事是自动的,那我们把它呢,说的更明确一点,更详细一点,是希望呢,你加深对这件事的理解啊,那么,写完这个类以后啊,我们需要再写另外一个类,再写另外的一个Servlet,就是FindCostServlet,我们在这个类当中呢,要取到旧的session,从中读到那个数据,对吧,是吧,从中读到那个user,所以我们再写一个Servlet,那在web这个包下再写第二个Servlet啊,叫FindCostServlet。

  • 然后在这个FindCostServlet当中啊,我们也需要重写父类的service方法啊,模拟处理这个查询的请求啊,重写service啊,那当然了,这个查询请求(判断和相关的业务逻辑),我们就省略了啊,我主要是呢,想在这里呢,就是取到登录时的那个session,明白吧,取到那个账号的那个数据啊。那么之前也说了,咱们登录时,第一次访问服务器,服务器就创建了session,对吧,并且把SID给了浏览器,浏览器呢,在访问这个查询时,会把sessionID传入过来,给服务器,然后呢,服务器呢,根据id得到,找到那个旧的session,存入request,那所以呢,我们在这FindCostServlet,也可以呢,通过requeset,得到那个session,得到的是旧的明白吧,不是新的啊。

  • 那写一下,那么本次请求中,浏览器会自动传入,事先保存的sessionId,保存的JSESSIONID,然后呢,服务器根据此id找到,那个旧的session啊,那么我们通过request可以得到这个旧的session,HttpSession session = req.getSession();,所以啊,我们调request这个getSession方法,得到的是旧的session啊,那有人说,这个你能证明它是旧的,还是新的么,咱们一会啊,能看出来,一会我们看一下,就知道了啊,别着急啊。

  • 我得到这个session以后啊,我就从里面,去取那个数据,因为是旧的session,之前存了数据啊,我去取那个数据,存数据当时是setAttribute(...),对吧,取数据很显然就是getAttribute(...),按照名字来取,session.getAttribute("user");,那你注意,咱们set的时候,支持的类型是Object,对吧,什么数据都行,那get时也是Object,但我确认我们当时存的是字符串,对吧,可以转型啊,转为字符串啊,String user = (String)session.getAttribute("user");。那我们取到这个账号以后啊,我们把它输出给浏览器,直观的在浏览器能看到它啊,输出一下,res.setContentType("text/html;charset=utf-8");,设置响应消息头的输出类型,PrintWriter w = res.getWriter();,获取输出流,w.println(user);,输出从session中得到的用户名,w.close();,最后闭流。


@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//本次请求中,浏览器会自动传入//事先保存的JSESSIONID,然后//服务器根据此ID找到旧的sessionHttpSession session = req.getSession();String user = (String)session.getAttribute("user");res.setContentType("text/html;charset=utf-8");PrintWriter w = res.getWriter();w.println(user);w.close();
}

  • 那么,写完了以后啊,两个组件,我们需要访问的话,还是需要加以配置啊,所以呢,大家打开这个web.xml配置文件,配置一下啊,那我打开这个配置文件啊,当然这两个组件的配置的方式,和jsp4当中一样是吧,一样,如果你闲烦,也可以把它copy过来啊,当然我还是写一遍吧,因为我怕我忘了,多写两遍。

<servlet><servlet-name>login</servlet-name><servlet-class>web.LoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>login</servlet-name><url-pattern>/main/login</url-pattern>
</servlet-mapping>

  • 这是登录,还有一个,还有查询的,把那个查询呢,也配置一下:

<servlet><servlet-name>findCost</servlet-name><servlet-class>web.FindCostServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>findCost</servlet-name><url-pattern>/cost/find</url-pattern>
</servlet-mapping>

  • 那么,配置完以后呢,咱们可以测试了啊,那我把这个项目呢,部署一下啊,这是一个新的项目,部署以后呢,启动tomcat,当然了为了能够演示出这个session,它是每个浏览器是一个session,我是用两个浏览器分别演示的,我先用chrome演示,这样,我先把chrome先关了,它之前有了cookie,我怕一会观察的时候呢,会乱啊,关了,重新打开chrome啊,打开以后啊,我这个F12,看什么呢,看这个network,看network啊。就是你打开浏览器,然后呢,打开network,然后再去访问登录啊,localhost:8080,项目名是jsp5,然后呢,路径是/main,然后是,/login对吧,带上参数啊,user等于,这就别zhangsan了,换个人吧,换成caocao啊,uesr=caocao啊,随便写一个啊,localhost:8080/jsp5/mian/login?user=caocao
  • 然后呢,我会车啊,回车,回车以后,浏览器什么都看不到,对吧,因为登录时,我们没有写响应信息对吧,空的,然后呢,你看network当中呢,我们能看到这个,这个路径对吧,这个请求,我点到这个请求里去详细观察,那你会发现啊,这个network里是不是,多了一个图标,多了一个选项对吧,是吧,叫Cookies,就是说如果本次请求有cookie产生的话,我们能看到这个cookie。那我点一下Cookies,看一下啊,你看有Request CookiesResponse Cookies,请求时,没有是吧,请求时没有,为啥请求时没有呢,因为请求时,咱们没有传入,没有任何数据从cookie中传过来对吧,什么都没有啊,响应时,是不是通过cookie传了sessionId啊,响应时有,你看是不是这样,响应时是不是有JSESSIONID啊,是吧,有JSESSIONID,有了,能看到,能看出来啊。
  • 那我再去访问谁呢,再去访问这个查询啊,然后呢,就是localhost:8080/jsp5/cost/find,我就看到了caocao,看到了吧,同理,我换个浏览器,再试一下,也是这样的结论啊,我换个浏览器,还得用360,没办法啊,用吧,我换个人登录啊,比如说,以张飞的身份来登录,看一下,localhost:8080/jsp5/main/login?user=zhangfei,访问了。
  • 访问之后呢,再去访问查询,localhost:8080/jsp5/cost/find,zhangfei。
  • 那么,它对chrome有影响么,我刷新chrome浏览器,还是coacao对吧,没有影响。经过呢,这个案例的演示呢,就是说,我们基本上了解了session的使用方式,它在使用上呢,比cookie还要简单啊,因为不用我们自己去new,拿来就用,存什么都行啊,没有限制啊,然后呢,这个你看啊,我们使用session,是在登录时,请求里存数据,在查询里取数据,两个请求共用一份数据对吧,就两个请求可以共用session中的数据,另外呢,登录,查询,是两个组件,两个组件也可以共用session中的数据啊,再者呢,每个浏览器都有一个session,因为我们刚才用了两个浏览器,互不影响,对吧,每个浏览器是一个session,然后id不同,可以输出看一下,互不影响啊。
  • 总之呢,session,它也满足那3点。那么,关于这个session的语法,书上也有介绍,我们再看一下啊,首先,如何获取session:

如何获取Session:
HttpSession s = request.getSession(boolean flag);
1.HttpSession是个接口,后面返回的是符合接口规范的对象
2.当flag为true时:先查看请求中有没有SessionId,如果没有SessionId,服务器创建一个Session对象;如果有SessionId,依据SessionId查找对应Session对象,找到则返回,找不到则创建一个新的Session对象,所以flag为true时,一定能得到一个Session对象
3.当flag为false时,没有SessionId及有SessionId但没有找到Session对象,均返回null;找到则返回
4.HttpSession s = request.getSessioin(); 等价于 request.getSession(true); 提供该方法是为了代码书写更方便一些,大部分情况下是不管找没找到都需要返回一个Session对象。

  • 这个request.getSession(boolean flag),这个方法是重载的,可以有参数,可以没有,书上说可以有个参数叫布尔值,那这个布尔值啊,true和false啥意思呢,如果说呢,你传入的是true,那它一定会给你返回一个session,如果是false,有可能没有session,那什么情况下,可能会没有session呢,是这样啊,这个session,我后面会讲,它会有一个超时时间的,服务器存session,压力很大,它不会永久保存,一直存,你像这个淘宝啊,京东啊,这个服务器,它是很长时间都不会重启明白吧,基本上都不会关的,常年不关的,所以,它老是存着session的话,它压力大,怎么办呢,它通常是30分钟,你这人30分钟,没有什么任何操作,它就把你这个session给销毁了,删除了啊,所以session呢,会自动被销毁的,30分钟以后。
  • 那比如说啊,我去登录啊,然后,服务器给我创建了一个session,存了用户,但是呢,我出去了,过了一个小时回来了,那个session,我那个session早被销毁了,明白吧,早没了,我再去点一下这个网页的某个功能,那服务器一看啊,session没了,你访问它的某个功能,要获取session的话,一看session没了,就看你这个参数,如果呢,你在getSession()时,这个参数是false,它一看啊,session已经过期没了,会给你返回null,明白吧,你就没有了,如果你写true的话呢,它一看啊,session销毁了,没了,它会new一个新的session给你,明白吧,这个意思。
  • 总之啊,getSession方法中的参数,如果是true的话,无论如何,一定会给你一个session啊,没有就new一个新的,有就用以前的,但如果是false的话,可能会没有,我们一般的话都是true啊,那你像咱们刚才写的那个getSession(),没有写参数,那没有写参数的话默认为true,明白么,它底层的参数默认为true,所以,一般我们就不写参数,就可以了,这是获取参数的方式,然后呢,我们要往session当中存值啊,setAttribute,刚才演示了啊,要取值,getAttribute,演示了对吧。

如和使用Session绑定对象
绑定对象:void Session.setAttribute(String name, Object obj);
获取绑定对象:Object Session.getAttribute(String name);
移除绑定对象:void Session.removeAttribute(String name);
注:getAttribute方法的返回值是Object类型,在去取数据时要对其进行数据类型转换,且必须与我们存入的数据的数据类型一致
如何删除Session对象:立刻删除Session对象:Session.invalidate();

  • 如果你既不存,也不取啊,你要删除一个值,remove啊,这个我就不演示了,因为你存和取会的话,删除自己试一试,很容易。session对象啊,有些时候,是需要销毁的啊,那想一想啊,咱们通常是登录时,创建一个session,往里存东西对吧,什么时候,这个session要销毁,哎,在退出的时候,登录时创建,退出时把它销毁对吧,是这样吧,退出时销毁,那我们这个电信计费项目呢,也有退出功能啊,那要做退出的话,那就需要用到这个方法,把session销毁,那session一销毁,它里面数据自然就释放了,对吧,就会把这个内存,就是释放出来,那这样啊,这个我说一下,咱们这个退出的逻辑啊,说下退出的逻辑,非常简单。

模拟Session应用案例代码实现

1.jsp6/src/main/java/web/LoginServlet.java

package web;import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {String user = req.getParameter("user");//首次调用session时服务器会自动给//当前访问的浏览器创建一个session//该session是jsp的隐含对象之一HttpSession session = req.getSession();//session中可以存任意类型的数据session.setAttribute("user", user);//服务器响应时会作出如下处理://Cookie c = new Cookie("JSESSIONID",session.getId())
//      session.getId();//试一下可以点出getId这个方法//c.setPath(request.getContextPath());//response.addCookie(c);        }
}

2.jsp6/src/main/java/web/LoginServlet.java

package web;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class FindCostServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//本次请求中,浏览器会自动传入//事先保存的JSESSIONID,然后//服务器根据此ID找到旧的sessionHttpSession session = req.getSession();String user = (String)session.getAttribute("user");res.setContentType("text/html;charset=utf-8");PrintWriter w = res.getWriter();w.println(user);w.close();   }
}

3.jsp6/src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"><display-name>jsp5</display-name><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list><servlet><servlet-name>login</servlet-name><servlet-class>web.LoginServlet</servlet-class></servlet><servlet-mapping><servlet-name>login</servlet-name><url-pattern>/main/login</url-pattern></servlet-mapping><servlet><servlet-name>findCost</servlet-name><servlet-class>web.FindCostServlet</servlet-class></servlet><servlet-mapping><servlet-name>findCost</servlet-name><url-pattern>/cost/find</url-pattern></servlet-mapping>
</web-app>

Session在NetCTOSS中的应用1:退出功能时实现销毁Session对象。

  • 目前呢,我们做的这个功能当中啊,像什么资费查询,资费增加,资费修改的页面上,都有退出对吧,而且呢,我们把退出也提取到那个logo.jsp里,共用了对吧,是吧,共用了,然后那个退出呢,它是一个超链接啊,是个超链接,那我们一点退出的话呢,就是,是需要访问服务器的,为什么呢,服务器一看,你要退出,你要退出怎么办呢,我把你的session销毁明白吧,好释放这个资源,释放这个内存,所以要访问服务器。
  • 当然了,我们这个项目呢,是基于MVC模式,所以你访问服务器,还是访问Servlet啊,而在我们这个项目之内,只有一个Servlet,就是MainServlet,然后呢,我们加一个方法来处理呢,退出的这个业务,那这个方法呢,可以叫logout()吧,这个登录login,退出logout,那么这个路径啊,访问路径,我们可以就叫做/logout.do,这样,点这个退出超链接的时候,我们就访问这,/logout.do这,那这个方法里做什么呢,只做一件事,将session销毁,好释放呢,这个资源啊,那么你想啊,将session销毁就一句话啊,这句话这样写session.invalidate();,当你一调这句话,session就会被销毁啊,所以这个方法里呢,就这么一句话,就完了,没有别的逻辑了。
  • 那销毁完session以后,那然后去哪,咱们一般退出以后会去哪啊,会回到登录页面对吧,那你回到登录页面,怎么回到登录页面呢,怎么回去啊,显然是重定向,因为这个是退出,那个是打开登录页面,两个事对吧,重定向,那么打开登录页面呢,那个方法叫toLogin对吧,MainServlet.toLogin(),咱们之前都写完了,然后呢,MainServlet.toLogin(),它是做了转发,它转发到这个login.jsp了,这是以前就完成的内容啊,访问它MainServlet.toLogin(),它转发,然后呢,输出结果,这样。就整个退出啊,有两个请求啊,访问退出功能,然后呢,重定向,然后呢,在MainServlet.logout()这啊,重定向,到/toLogin.do,其中呢,第二个请求这些内容,这是我们已经完成的内容啊,它不再是我们这个功能关注的重点,所以,这个功能就很简单了,就是加一个logout方法对吧,里面就是写一句话,然后重定向特别简单,所以,这么简单的功能呢,就不给你写了啊,自己写一下,参考这个思路啊,就一句话,自己写一下。这个图啊,我存一下。

小总结:Session的基本用法

  • 当然这个Session呢,它是否销毁,咱们直观上看不到,如果你想看的话,你只能去观察那个Network明白吧,看一看那个cookie的变化,因为这个session的id,用cookie来传对吧,所以session有变化,从cookie中能看出来,可以看那个啊,这是我们讲的关于session的话题。然后呢,第一个小的话题,就是它的基本用法,那关于session的基本用法啊,第一个就是说,如何获取session,是request,如何获session,是request.getSession(),然后呢,第二个是存入,存数据啊,怎么往session中存数据,非常简单,存数据,session.setAttribute(),对吧,那如何取数据,session.getAttribute(),那还有如何删一条数据,session.removeAttribute(),那还有如何销毁,是session.invalidate(),就是把它的这些基本的语法罗列一下啊,再巩固一下。那这些都很简单啊,那关于session也是一样,除了基本语法之外啊,还要了解它的扩展的这些个知识点,我们把它的扩展的知识点讲完以后啊,我们就去完善我们那个电信计费项目,然后呢,用这个session解决一些问题。

Session的基本用法:
1.获取session:request.getSession()
2.存数据:session.setAttribute()
3.取数据:session.getAttribute()
4.删数据:session.removeAttribute()
5.销毁:session.invalidate()

模拟Session应用案例:演示Session超时

  • 那再往下看啊,这个session验证,我们后面会验证netctoss里的一些功能,这个后面再说啊,先别着急。

Session验证:用户访问需要保护的资源时,可以使用Session验证的方式来保证其安全性,比如要求登录后才能访问的资源。实现Session验证,遵循以下步骤
1、使用Session.setAttribute()先绑定数据
2、使用Session.getAttribute()方式来读取绑定值,如果没有,则跳转回登录页面

  • 那下一个小的话题啊,是这个Session的超时。就是session和cookie也一样,都有时长,它不可能永远都存着,明白吧,是有时长的,尤其是session,它存到服务器上,服务器压力很大对吧,在某些情况下是要把session销毁的,那服务器呢,是这样的,就是服务器呢,默认会保持session呢,30分钟。

什么是Session超时:Web服务器会将空闲时间过长的Session对象删除掉,以节省服务器内存空间资源;web服务器缺省的超时时间限制:一般是30分钟。

  • 当然了,如果说用户一直在活跃,一直在访问服务器,这个session不会销毁,但是如果说呢,用户中间空闲时间超过30分钟,它的session将会销毁,你比如说,我现在访问淘宝,一访问淘宝,一登录,它会给我创建一个session,保存我的一些数据,比如说账号,那如果说呢,我用淘宝,用了一下以后,我就出去了,我出去了30多分钟,回来以后,我的session就被淘宝销毁了,明白吧,空闲时间超过30分钟,就被销毁,这样。那这个空闲时间呢,可以改,如果你觉的不好可以改,你可以改短,也可以改长,不过一般我们工作时呢,也不用改,这个30分钟是比较,还算比较合理的,就可以了,那如果你想改的话呢,有两种方式啊,一种方式呢是,修改配置文件,写这么一段话:

如何修改Session的缺省时间限制:通过修改tomcat中conf/web.xml文件的设置。
<session-config><session-timeout>30</session-timeout>
</session-config>

  • 第2种方式呢,是我们在获取session以后,调它的方法啊,去设置一个时间。

如何修改Session的缺省时间限制(续):通过编程的方式来修改。
void session.setMaxInactiveInterval(int seconds)

  • 咱们一般呢,能配置就不会写代码,明白吧,一般呢,还是写配置文件啊,所以,我们演示一下这个配置,那你注意啊,我们演示配置的时候呢,我不可能把它改为10分钟,或者是比较长的时间,因为那样的话,我得等10分钟对吧,等得太久了啊,所以呢,我们把这个时间呢,修改为一个非常小的数,最小一分钟,明白吧,不能再小了,改成一分钟试试看,但是呢,其实你改一分钟的话,你就等1分钟也不行,为啥呢,因为呢,你这设置时间是空闲时间,那么tomcat,它里面有一个线程,专门检查这个事,像巡逻队一样,它这个检查的时间,巡逻的时间是2分钟,可能2分钟多一些,反正所以说你想啊,它检查的时间间隔,大于一分钟,明白吧,所以你刚好到1分钟的话,可能没检查到,所以最好呢,我们多等一会,超过两分钟,明白吧,才能看到效果。
  • 所以想看这件事呢,还得等一会。那这样,我们先写,写完之后呢,我们就等一会,看一下,还是那个项目jsp5,打开jsp5当中的配置文件web.xml啊,因为我们需要修改配置啊,打开配置文件,然后呢,在配置文件里最后面,我们加上一段话,主要是声明session的超时时间,单位呢,是分钟。

// 声明session的超时时间(分钟)
<session-config><session-timeout>1</session-timeout>
</session-config>

  • 那么这段配置啊,就是两层标签,外层呢,叫session-config,session的配置,内层叫session-timeout,超时时间一分钟。那写完以后啊,要把这个项目呢,重新部署啊,部署以后呢,启动tomcat, 启动以后,我打开浏览器,我去访问这个登录的功能,localhost:8080/jsp5/main/login?user=caocao,jsp5,main,login,传入账号user等于caocao,登录以后呢,我去访问资费查询啊,localhost:8080/jsp5/cost/find,看到了caocao,哎,到这别动了,计时。

  • 然后呢,等啊,大概两分钟以后,你再看,别动啊,你动的话,就不是空闲了,你别动,才是空闲。那么tomcat底层呢,有一个线程, 专门来检查这件事,它每隔一段时间检查一下,哎,这个浏览器是不是超时了呢,它检查的周期,大于一分钟啊,所以说呢,我们需要多等一会,等个大概两分钟多一点,差不多啊。好了,两分钟的时间已经到了啊,咱们可以试一下,试一下,就是说,如果说呢,它已经超时了,session就已经被销毁了对吧,那如果session已经被销毁了,我再一刷新这个查询页面,是不是我们从session中就取不到这个caocao呀,那我一刷新,如果我看不到这个数据,就说明什么呢,session被销毁了,如果还能看到,没销毁是吧,那试一下啊,我刷新了,注意看,我刷了啊,null对吧,哎,说明session中数据没了,自动销毁了,我没动它。
  • 那当然了,咱们一般呢,工作时这个session的超时时间,不可能设置这么短,一分钟明白吧,我刚登录淘宝,哎,我突然想上厕所,我上个厕所回来就销毁了,对吧,这太快了,或者我刚登录淘宝,又打个电话,又销毁了对吧,太不易用了啊,一般的话,一般这个session呢,怎么也得10分钟以上啊,不会太短,所以我们只是演示一下,这个归纳一下啊,就是说,关于session呢,第2个小话题是,超时时间啊,然后呢,我们可以在,就是默认是30分钟,可以在配置文件中修改此时间,那修改方式,刚才所演示的。当然了,还有一种方式就是,你得到session,调这个方法,setMaxInactiveInternal(int seconds),指定一个时间,这种我们一般很少这么用啊,所以,就了解一下就得了。

代码实现:jsp6/src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"><display-name>jsp5</display-name><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list><servlet><servlet-name>login</servlet-name><servlet-class>web.LoginServlet</servlet-class></servlet><servlet-mapping><servlet-name>login</servlet-name><url-pattern>/main/login</url-pattern></servlet-mapping><servlet><servlet-name>findCost</servlet-name><servlet-class>web.FindCostServlet</servlet-class></servlet><servlet-mapping><servlet-name>findCost</servlet-name><url-pattern>/cost/find</url-pattern></servlet-mapping><!-- 声明session的超时时间(分钟) --><session-config><session-timeout>1</session-timeout></session-config>
</web-app>

关于Session的URL重写以及相关的面试想法

  • 那么关于session呢,还有一个话题,咱们之前也讲了说,Session在使用时要依赖于cookie对吧,

浏览器禁用Cookie的后果:
1.如果浏览器禁用Cookie,Session还能用吗?
2.答案:不能,但有其他的解决方案
3.服务器在默认情况下,会使用Cookie的方式将SessionId发送给浏览器,如果用户禁止Cookie,则SessionId不会被浏览器保存,此时,服务器可以使用如URL重写这样的方式来发送SessionId。

  • 那你想啊,如果用户把cookie禁用了,这个session还能用么,就不能了,那如果你想能用怎么办呢,其实也有办法啊,如果cookie被禁用了,我们还一定要用Session的话,那么有一种方式,这个方式的名字叫URL重写。

什么是URL重写:浏览器在访问服务器上地址时,不再使用原来的那个地址,而是使用经过改写的地址(即,在原来的地址后面加上了SessionId)。

  • 至于呢,是怎么重写我就不演示了,为啥呢,没有必要,因为呢,还是那句话,我们认为呢,正常的用户,普通的用户,它绝对是不会禁用cookie的,对吧,他也不知道什么是cookie,一般没有这种情况,而对于个别用户,他要禁用cookie,我们就不认为他是我们的目标客户,不管它就完了,但是呢,这件事你要知道,因为有的时候啊,会有一道笔试题,就这道笔试题呢,没什么价值啊,就是说,很多公司面试啊,它的笔试题都是从百度搜出来的,什么java面试100题是吧,就那种,里面就有一道这样的题,他这心血来潮给你写出来了,那你也得知道,要不然得不到分啊,对吧。所以呢,把这个,你就把这事记住啊,URL重写。
  • 那如果面试官万一面试时问你说,Cookie禁用了Session怎么办,URL重写,怎么重写呢,哎呀,那个不太常用,我忘了,工作时,我一查那手册马上就知道,你放心吧,是吧,你给他这种感觉就可以了,有人说这行么,行,为啥呢,就是说,这个面试啊,它跟这个考试真不一样,考试的话,我那个这个客观题,那abcd,我答对了,那我答80分,就是80分,对吧,除非就老师他不想给我分,他非得那个瞎弄,正常来讲客观的话,就这个分,是比较明确的,但面试不一样,面试的话,这怎么说呢,只要是你达到了那个笔试的那个入围的那个分就可以了。
  • 比如说,它笔试题,我要筛选人,因为我要面试的话,来了100人,我要筛选一下,我不能都面试,我面试不来,出道题,比如说,我就想面试50个人,我就取前50个人,明白吧,你别管后50个分多少,都pass掉了,就这样,它不是说呢,固定一个分,哪个分够了就留下,他是反正就想筛选人,前50人,还是60人,看分啊,看啊,前60个,进来了,进来以后面的话,那个问答的环节就不一样了,问答的环节是什么呢,只要你聊的开心了,聊的ok了,感觉你这个靠谱了,那就行,就即便是说感觉,你这人问答上,感觉你的知识面不如那个人,感觉你这个某些技术点不如那个人,也可能会要你。
  • 你像以前我们也是,这个要招人,要面试,遇到一个挺好的,挺不错的,然后的话,我就问部门经理,我说这个,这个人不错,要他么,部门经理说,这人不能要,为啥呢,太聪明了,因为当时我们开发的时候,用的是自己框架,然后呢,用的是自己呢,封装的东西,和这个外面的任何企业都不一样,这样人来了的话,几天把这东西,搞的差不多了,感觉没劲他就走了,我们好不容易培养几个月,培养出一个人来就走了,还得再折腾一遍,这样的人不要,还得要一个不是那么,那么强的人,能力还得是一般,听话的人,我们要的是听话靠谱的人,所以你这个问答环节啊,这个,看面试官的心情啊。
  • 还有可能是什么呢,面试官最近工作就遇到了一个困惑啊,就想问问这个困惑,看谁能解答出来啊,就前十个人,前几十个人,都没说出这个答案来,都没说的好,就后面那个人,别的不如别人,就这一点说的好对吧,那也会要你,所以这个东西不一定啊,因此啊,就是说,面试时,你只要把这句话说出来,然后的话,他想问,他想要细问说,那你这个东西到底是怎么做的,我忘了,翻翻书就可以了,这个,这个地方也有这句话啊。

如何实现URL重写:如果是链接地址和表单提交,使用response.encodeURL(String url) 生成重写后的URL;如果是重定向,使用response.encodeRedirectURL(String url); 生成重写后的URL。

  • 然后呢,归纳一下啊,这个第3个话题啊,就是cookie禁用时session怎么办,那cookie禁用时,session就不能用,如果你想用,就是解决方案叫做URL重写,事实上啊,就是说你不能用cookie传id了,我们就把这个id,附加在这个路径上来回传,明白吧,发响应时,在路径上带个id,发请求时再带个id,每次响应请求都要带这个id,自己带,但自己带太麻烦了,怎么办呢,URL重写就是写一句话,它帮你带,大概就这个意思啊,总之呢,还是很麻烦啊,一般我们还是,还是得用cookie啊,不用的话,太麻烦了。所以关于Session的URL重写,这个就了解。
  • 然后呢,我们再看呢,这个就了解,再看session的优缺点。

Session的优缺点:
1.优点:安全(将状态保存在服务器端);Session能够保存的数据类型更丰富,Cookie只能保存字符串;Session能够保存更多的数据,Cookie大约保存4k。
2.缺点:Session将状态保存在服务器端,占用服务器的内存,如果用户量过大,会严重影响服务器的性能。

  • 其实咱们之前也说了,session的优点是安全对吧,缺点是呢,耗内存啊。那关于session的这个知识点,其实就这么3点,基本用法,很容易理解,很容易掌握,超时时间,那句话如果出现的话,你能看懂就行了,再一个如果说,你想改的话,就你忘了,也没关系,你百度session的超时时间怎么配,马上就有很多这个帖子,一看就知道,这个简单。然后呢URL重写这事,知道这个词就行啊,那么了解了session的基本用法以后啊,那下面呢,我们得用它解决项目中的问题,我们还是利用它呢,解决这个经典问题啊,就是登录时存账号,登录以后显示账号,我们用session来做一下。

Session在NetCTOSS中的应用2:登录时记录保存账号并在登录后用以显示

  • 那么打开这个开发工具啊,然后呢,我们还是打开呢,之前的netctoss项目,打开以后啊,我们找到那个登录的方法,这个方法呢,它就在MainServlet当中啊,我们找到这个方法,那么,在一个类当中有很多方法,快速找到一个方法,之前也说过对吧,用的是大纲对吧,大纲的快捷键是ctrl+o啊,找一下login方法,找到以后啊,之前我们用cookie做了,在什么时候做的呢,在验证通过的时候对吧,60多行,验证通过的时候,我之前呢,是把这个账号存入了这个cookie,那现在呢,我再把账号存入session,那这个cookie这个,我还留着,不删,可以吧,就留着啊,就是再写一句啊,将账号存入session。

//将账号存入session
HttpSession session = req.getSession();
session.setAttribute("user", adminCode);

  • 那么你要把账号存入session,首先我们得得到session,对吧,获取session的方式是getAttribute(...),那你看啊,我们在这,在验证通过时,是把这个账号存到了session里,这存了,那我们在查询,增加等页面上要调用对吧,要显示啊,所以我们再打开那个页面,当然那些页面的这个,显示账号的那一部分,被我提取出来了啊,那个页面呢,变成了logo.jsp,所以呢,我们打开我们所写的logo.jsp,打开以后啊,你看啊,我们这句话,<span>${cookie.user.value }</span>,是从cookie中取的参数对吧,现在想改一下,改成session中获取,那我把这句话<span>${cookie.user.value }</span>,注释掉,好吧,注掉,别删,留着你以后复习用,哎,注释你注意啊,这段注释,不能用html注释,必须用jsp特有的注释,得这样写,<%-- <span>${cookie.user.value }</span> --%>,想一想为什么这必须得用jsp注释,因为中间有el表达式,而el的本质,其实就是java对吧,是吧,因为它是java,你这个html注释对java无效,对吧,所以这里得写这样的注释啊。
  • 然后呢,我另起一行,再写一个span,我在span里呢,再写一个el,这回从session中取到这个值。那大家看一下啊,我想从session中取到user,这句话,我得怎么写,这个表达式,session点user,然后呢,点value,是这样么,还试,哎哟我的天呢,我也无语了啊,你看看啊。

<!-- EL默认从4个隐含对象中取值:page,request,session,application它也有能力从cookie中取值,语法:cookie.name.value -->

  • 这句话就在这摆着,el表达式默认从4个隐含对象中取值,session是其中一个,我们从默认对象中取值的时候,需要写前缀么,需要写点value么,是这样吧,再一个啊,如果你非得,一定要从session中取值,不从其他地方取值,你得写sessionScope点什么什么,是这样吧,是吧,这个cookie是特殊的,只有cookie取值这么写,cookie.user.value,其他对象不这么写,哎,你看,又受这影响了,你怎么老是受别的地方的影响,只要学会一个新东西,马上,就这事能记住,其他的容易忘,这就是问题啊,这眼瞅在这摆着呢,那怎么写呢,就user就可以了,<span>${user }</span>
  • 那如果你还是忘了,还是搞不清楚,你回顾一下,咱们之前呢,讲那个el表达式时那个案例,我们向浏览器传的是student对吧,我们,当然是从request传的,我们这个取值,我们写的是student点什么什么对吧,上来就写,没有前缀,没有什么value啊,那写完以后测一下啊,把项目呢,重新部署一下,重启tomcat,启动以后呢,我们打开浏览器,这个登录一下,localhost:8080/netctoss/toLogin.do,这回换个人啊,之前caocao,这回换个人,张飞啊,我换成zhangfei登录啊,登录,登录以后看资费管理,zhangfei,增加(页面),也是 zhangfei啊,没错。
  • 那这是session呢,在项目中的应用,就是这样。

Session在NetCTOSS中的应用2之代码实现

1.src/main/java/web/MainServlet.java

package web;import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import dao.AdminDao;
import dao.CostDao;
import entity.Admin;
import entity.Cost;
import util.ImageUtil;public class MainServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//获取访问路径String path = req.getServletPath();//根据规范(图)处理路径if("/findCost.do".equals(path)) {findCost(req,res);} else if("/toAddCost.do".equals(path)) {toAddCost(req,res);} else if("/addCost.do".equals(path)){addCost(req,res);} else if("/toLogin.do".equals(path)){toLogin(req,res);} else if("/toIndex.do".equals(path)){toIndex(req,res);} else if("/login.do".equals(path)){login(req,res);} else {throw new RuntimeException("没有这个页面");}}//登录protected void login(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//接收参数String adminCode = req.getParameter("adminCode");String password = req.getParameter("password");//验证 AdminDao dao = new AdminDao();Admin a = dao.findByCode(adminCode);if(a == null) {//帐号错误 req.setAttribute("error", "账号错误");req.getRequestDispatcher("WEB-INF/main/login.jsp").forward(req, res);} else if(!a.getPassword().equals(password)) {System.out.println(password);System.out.println(adminCode);//密码错误req.setAttribute("error", "密码错误");req.getRequestDispatcher("WEB-INF/main/login.jsp").forward(req, res);} else {//将账号存入cookieCookie cookie = new Cookie("user", adminCode);res.addCookie(cookie);//将账号存入session
//          HttpSession session = req.getSession();session.setAttribute("user", adminCode);//验证通过res.sendRedirect("toIndex.do");}}//打开登录页面protected void toLogin(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {req.getRequestDispatcher("WEB-INF/main/login.jsp").forward(req, res);}//打开主页protected void toIndex(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {req.getRequestDispatcher("WEB-INF/main/index.jsp").forward(req, res);}//查询资费protected void findCost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//查询所有的资费CostDao dao = new CostDao();List<Cost> list = dao.findAll();//将请求转发到jspreq.setAttribute("costs", list);//当前:/netctoss/findCost.do//目标:/netctoss/WEB-INF/cost/find.jspreq.getRequestDispatcher("WEB-INF/cost/find.jsp").forward(req, res);}//打开增加资费protected void toAddCost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {req.getRequestDispatcher("WEB-INF/cost/add.jsp").forward(req, res);}//增加资费数据protected void addCost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//接收传入的参数req.setCharacterEncoding("utf-8");String name = req.getParameter("name");String costType = req.getParameter("costType");String baseDuration = req.getParameter("baseDuration");String baseCost = req.getParameter("baseCost");String unitCost = req.getParameter("unitCost");String descr = req.getParameter("descr");//保存该数据Cost c = new Cost();c.setName(name);c.setCostType(costType);if(baseDuration != null && baseDuration.length()>0){c.setBaseDuration(Integer.valueOf(baseDuration));}if(baseCost != null && baseCost.length()>0) {c.setBaseCost(Double.valueOf(baseCost));}if(unitCost != null && unitCost.length()>0) {c.setUnitCost(Double.valueOf(unitCost));}c.setDescr(descr);CostDao dao = new CostDao();dao.save(c);//重定向到查询//当前:/netctoss/addCost.do//目标:/netctoss/findCost.dores.sendRedirect("findCost.do");  }
}

2.src/main/webapp/WEB-INF/logo.jsp

<%@page pageEncoding="utf-8" %>
<img src="data:images/logo.png" alt="logo" class="left"/>
<!-- EL默认从4个隐含对象中取值:page,request,session,application它也有能力从cookie中取值,语法:cookie.name.value -->
<%-- <span>${cookie.user.value }</span> --%><!-- 不能用html注释,必须用jsp特有的注释 -->
<span>${user }</span>
<a href="#">[退出]</a>

写在后面

NETCTOSS代码实现第六版相关推荐

  1. NETCTOSS代码实现第五版

    NETCTOSS代码实现第五版:Cookie的使用场景与使用方式 前言 Cookie的使用场景与使用方式 模拟Cookie的使用场景 Cookie的创建,存储,获取与修改 Cookie的生存时间 小总 ...

  2. NETCTOSS代码实现第八版

    NETCTOSS代码实现第八版:过滤器之登录检查功能与监听器 前言 模拟案例jsp6:演示过滤器的使用 过滤器模拟案例需求分析与设计以及代码分析 模拟资费增加和资费查询功能组件:AddCostServ ...

  3. java单选框的讲课ppt6_Joho Lewis《Java Software Solutions》第六版课件第十....ppt

    <Joho Lewis<Java Software Solutions>第六版课件第十....ppt>由会员分享,可在线阅读,更多相关<Joho Lewis<Jav ...

  4. 数据库系统概念第六版 第五章练习题 2 4

    数据库系统概念第六版 第五章练习题 2 4 5.2 写一个使用JDBC元数据特性的JAVA函数,该函数用ResultSet作为输入参数,并把结果输出为用合适的名字作为列名的表格形式. (对JAVA不太 ...

  5. 深夜里学妹竟然问我会不会C?我直接把这篇文章甩她脸上(C Primer Plus 第六版基础整合)

    C Primer Plus 第六版 前言 第一章 初识C语言 一.C语言的起源 二.C语言的应用 三.C语言的特点 四.编译的过程 五.编码机制 1.简述 2.完成机制 六.在UNIX系统上使用C 七 ...

  6. [Python] 爬取 材料力学Ⅰ第六版刘鸿文-指导与例题习题解答

    [Python] 爬取 材料力学Ⅰ第六版刘鸿文-指导与例题习题解答 下载 书<材料力学Ⅰ 第六版刘鸿文-指导与例题习题解答>的全部图片 下载的图片保存在./cailiaolixue里,全部 ...

  7. pmp访谈法和焦点小组区别_访谈和书评:《简而言之的Java》,第六版

    pmp访谈法和焦点小组区别 本杰明·J·埃文斯(Benjamin J. Evans)和戴维·弗拉纳根(David Flanagan) 撰写的第六版Java in Nutshell是对Nutshell系 ...

  8. C prime plus 第六版 课后编程练习 第7章

    C prime plus 第六版 课后编程练习 第7章 7.12.1 编写一个程序读取输入,读到#字符停止,然后报告读取的空格数.换行符数和所有其他字符的数量. 7.12.2.编写一个程序读取输入,读 ...

  9. PMBOK(第六版) PMP笔记——《三》第三章 项目经理的角色

    PMBOK(第六版) PMP笔记--<三>第三章 项目经理的角色 1 .项目经理是由执行组织委派,领导团队实现项目目标的个人. 就像是交响乐队的指挥,他不需要掌握每种乐器,但应具备音乐知识 ...

最新文章

  1. codeforce843B Interactive LowerBound
  2. 线性表的存储结构总结
  3. 小试牛刀之Django
  4. python数字处理技巧(1): 精度舍入、精确运算、格式化、进制数、大数打包解包、复数、NaN、分数
  5. Scala教程之:深入理解协变和逆变
  6. python面向对象编程138讲_Python面向对象编程简单讲解
  7. leetcode 实现 strStr()
  8. 理解 invokedynamic
  9. 《Scikit-Learn与TensorFlow机器学习实用指南》第7章 集成学习和随机森林
  10. c语言从文件查找字符串,C语言文件中字符串的查找与替换?
  11. 2020考研初期作息时间表
  12. 如何做一个优秀的管理者
  13. LeetCode 第35题 搜索插入位置 做题记录
  14. #自动化测试框架的4种有效分类与使用选择
  15. 锡育英语背单词软件v2019.04绿色版
  16. 学生学籍管理系统~~登录界面(Java、SQL)
  17. E10下64位浏览器与32位浏览器切换教程
  18. php 验证 繁体,验证码上中文字是繁体
  19. obs无法录屏或无法保存视频的解决方法
  20. ImportError: (‘You must install pydot (`pip install pydot`) and install grap

热门文章

  1. 无心剑英译余秀华《我曾经那么爱过他 — 写给海子 》
  2. 《Java面试十八式》----第二式,简历投递
  3. 谷歌地球使用手册_如何使用手册页:比Google搜索更快
  4. Paddle实现食物图片分类
  5. 在线二叉树哈夫曼生成工具
  6. Mybatis特殊字符处理
  7. CCAI 讲师专访 | 机器学习奠基人Thomas Dietterich:人类将如何受到AI威胁
  8. 应用相机权限改变导致崩溃的解决办法
  9. jsp编写猜数字游戏
  10. 入坑大法_input不可以前端编辑但是可以后台传值