欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Cookie,Session解决用户的会话跟踪问题

程序员文章站 2022-03-14 23:48:26
...

一:Servlet细节
01.Servlet的映射细节

1):一个Servlet程序(WEB组件),可以配置多个<utl-patternt>,表示一个Servlet有多个资源名称

2):一个Servlet程序,可以配置多个<servlet-mapping>.

3):<rul-patternt>必须保证唯一性,而且必须使用/打头.

4):Servlet的映射支持通配符映射( * :表示任意字符);

     第一种:  /*,任意的资源都可以访问该Servlet. /system/*:请求的资源必须以/system/打头才可以访问,Servlet中,权限控制:

     第二种:  *.拓展名.比如: *.do,请求的资源必须以.do作为结尾才可以访问该Servlet.

5):在映射Servlet的时候,<servlet-name>元素的文本内容不能是default.

    因为的tomcat中存在一个叫做default的Servlet,专门用于处理请求静态资源(html,css,js,图片等).在Tomcat根/conf/web.xml文件:

6):localhost会默认访问URL为localhost/index.html的静态页面,所以只需要设置web.xml文件中的文件即可:

    <welcome-file-list>
          <welcome-file>hello.html</welcome-file>
    </welcome-file-list>*/

02.Servlet3.0新特性–注解配置

问题:如果Servlet有N个,就得配置10*N行代码,web.xml文件,臃肿,不利于维护,开发效率低,从Tomcat7开始,可以使用注解(WebServlet)来取代XML配置.

使用注意:在Web.xml文件的根元素中,存在属性,表示是否忽略扫描WEB组件注解:

        metadata-complete="true" :  要忽略

        metadata-complete="false"   不忽略

        不要改属性:   缺省情况等价于metadata-complete="false" 

Servlet代码:

@WebServlet(value="/m1",loadOnStartup=1,
        initParams=
        {@WebInitParam(name="encoding",value="UTF-8"),
         @WebInitParam(name="name",value="miao")
                }
)

使用配置,可以使用XML文件也可以使用注解:问题XML和注解各自的优缺点是什么,怎么选择?

XML:优点:XML配置很清晰,很直观,因为和JAVA代码相分离,维护性较高.

    缺点:XML配置导致配置文件臃肿,开发效率较低.

注解:优点:开发效率高,配置文件不臃肿,也方便快速定位.

     缺点:和java代码耦在一起,维护性较低.

抉择:一般的在企业中,现在注解使用的非常之多,而我们做开发,XML文件用于做通用配置.个别配置使用注解来.

学习阶段:先学XML配置,再讲注解配置.

03.服务器启动就初始化Servlet

回顾Servlet生命周期方法的执行流程:

    在启动Tomcat服务器的时候,没有Servlet创建和初始化操作.

    在第一次服务端请求的时候:

        1):创建Servelt对象.

        2):调用init方法做初始化.

        3):调用servlet方法,处理请求.

如果某一天,某一个Servlet(核心Servlet:初始化全局信息)需要在启动服务器的时候就创建出来,怎么办

    web.xml中的<servlet></servlet>的配置信息添加:

        //在启动服务器的时候就加载,值越小越优先加载//
        <load-on-startup>1</load-on-startup>

此时该Servlet,会在服务器启动的时候,创建好对象,并做好初始化操作.

使用注解:上面的注解有说到.

比如:在Strutst中的核心Action其本质就是Servlet,既然核心的Action是用来处理所有请求的,

     就应该在服务器启动的时候,就初始化,而不是第一个请求过来,才初始化

04.Servlet线程不安全问题

    造成的根本原因是:Servlet是单例的,Servlet中的非static的成员变量只有一份,多个客户端好比是多个线程,都访问的是同一个空间.

解决方案:   

        1:让当前的Servlet实现javax.servlet.SingleThreadMode接口.

          包装只有一个线程放Servelt,如果有多个线程就排队,如此的话,性能超低(已过时).

        2:在Servlet中不要使用成员变量,使用局部变量.

          每一个用户,每一个请求都会调用service方法.而局部变量在service方法中,每一次都是新的空间.

Struts1,Spring MVC都是线程不安全的,都是单例的和Servelt类似.

Struts2是线程安全的,每一个线程(请求),都是一个新的Action对象.

二:Http协议无状态带来的问题

05.HTTP协议的无状态连接

一次会话:可以简单的理解:打开浏览器,访问某一个站点,在该网址内部查看信息,点击超链接等相关的操作,最后关闭浏览器的整个过程,称为一次会话.

HTTP协议:

        有一个特点:无状态连接,服务端不知道上一次是哪一个客户端请求了自己.

无状态连接带来的问题:

            再一次会话中,我们可以查看多个资源,每一个资源都会先发送请求,再响应,每次的请求都是客户端

            发出的,但是,HTTP是无状态的,它不知道上次是谁请求了自己

            也就是说,再一次会话中,多个请求之间无共享数据.

![邮箱的会话跟踪图示](https://img-blog.csdn.net/20180217153707769?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

06.使用参数传递机制解决用户会话跟踪

解决方案:

        1)使用参数传递机制,在每一个请求之间使用参数来传递需要共享的数据.

          http://localhost/param/list?username=lucy

          可以解决问题,但是请求需要共享的数据全部都暴露在浏览器的地址栏中,不安全.

          如何解决共享数据不暴露在浏览器的地址栏:为什么会在浏览器的地址栏显示.

          因为:请求的请求行数据:GET/param/list?username=lucy Http/1.1

        如何解决:共享的数据不会在请求头中出现.

          把共享数据存放到请求头中,此时就不会在浏览器地址栏出现了.--->(Cookie)

        2):Cookie

            Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器,当用户使用

            浏览器再去访问服务器中的web资源时,就会带着各自的资源去,这样,web资源处理的就是用户各自

            的数据了.

        3):Session

三:Cookie

07.Cookie的简单运用

Cookie的操作:

    1:创建Cookie对象.

            Cookie cookie = new Cookie(String name,String value);

        参数:

            name: 该当前Cookie取一个唯一的名字.

            value:存储在Cookie的共享数据,只能是String类型.

            Cookie cookie = new Cookie("currentName","will");

    2:把Cookie放入响应中,响应给浏览器,把共享的数据存储到浏览器中.

            resp.addCookie(cookie);

    3:获取Cookie以及获取Cookie中的数据.因为Cookie存在请求头中,所以应该通过request去获取.

            Cookie[] cs = req.getCookies();

    4:Cookie的中文问题.

            在Cookie中属性名和属性值都不能使用中文.

            //编码
            String name = URLEncoder.encode(msg,"UTF-8");
            System.out.println(name);

            //解码
            String str = URLDecoder.decode(name,"UTF-8");
            System.err.println(str);

    5:修改Cookie中指定属性名的属性值.

            需求:修改Cookie cookie = new Cookie("currentName","will");          

            方式1:创建一个同名的新的Cookie.

            Cookie c = new Cookie("currentName","lucy");

            方式2:获取该Cookie对象,通过setValue方法,重新设置新的value值.

            Cookie对象.setValue("新的值");

            注意:别忘了,重新把该Cookie放入响应中:resp.addCookie(c);

    6:Cookie的分类(会话Cookie和持久化Cookie):

            会 话Cookie:关闭浏览器之后,Cookie就销毁了.  缺省情况.

            持久化Cookie:Cookie可以保存指定的时间段(3天,一周,一个月).

            设置Cookie的最大存活时间:cookie对象.setMaxAge(int seconds);

            seconds == 0;   删除Cookie.

            seconds <  0;   会话Cookie.

            seconds >  0;   存储指定的秒数

    7:删除Cookie:  cookie对象.setMaxAge(0);

8.Cookie的路径和Cookie的缺陷

    Cookiedomain:

            1):设置Cookie的path为"/". 列如:cookie.setPath("/");

            2):设置Cookie的domain. 列如:cookie.setDomain(".baidu.com").其中domain中没有指定域名前缀!


    Cookie的缺陷:

            1):多个人使用同一台电脑的时候,可以查看浏览器的Cookie,不安全.

            2):Cookie存储中文比较麻烦(得编码再解码).

            3):Cookie的value是String类型,一个Cookie就只能存储一个数据,如果需要存储多个数据,就得使用NCookie

            4):一个站点对Cookie有限制:

                    Cookie大小限制在4KB之内:

                    一台服务器在一个客户端最多保存20Cookie;

                    一个浏览器最多可以保存300Cookie;

            5):在设计上就有问题,考虑生活中问题.

                    Cookie是浏览器和服务器之间数据交互的凭证.

                    在生活中,我们是把识别数据存储到服务端.

四:Session

9.Session的原理

    Session其本质就是一个会话Cookie(浏览器关闭之后,Session就失效了).

    ![Session的原理图](http://img.blog.csdn.net/2018021720193186?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

10.Session的简单运用

1:创建和获取Session对象.

    HttpSession session = req.getSession(true);

            如果当前请求中存在一个Session对象,就直接返回,如果不存在Session对象,就先创建一个再返回.

    HttpSession session = req.getSession(false);

            如果当前请求中存在一个Session对象,就直接返回,如果不存在Session对象,就返回null.

    HttpSession session = req.getSession();  等价于:  HttpSession session = req.getSession(true);

2:往Session中存储数据

    Session对象.setAttribute(String name,Object value);

3:从Session中取出数据.

    Object value = session对象.getAttribute(String key);

4:删除Session.(用户注销登录)

    1):删除Session中指定属性名的值.

            session对象.removeAttrbute("currentName");

    2):销毁Session对象(Session中所有的属性都不存在).

            session对象.invalidate();

5:Session的超时管理

    在超时时间之内,如果客户端和服务端没有交互(用户的两次操作不能超过该时间),则自动销毁Session.

    session对象.setMaxInactiveInterval(60*10);//超过10分钟,则销毁Session

    Tomcat服务器的默认时间为:30分钟  可以修web.xml文件中的代码

    <service-config>
            <session-timeout>15</session-timeout>
    </session-config>

6:URL重写.

    Session是一种特殊的Cookie,而浏览器可以禁用Cookie.

    此时,需要在每一个资源之后,手动的携带session的ID.

    /session/list;jsessionid=3FB3D48B84806A040F03B070F7DAE56A

    String url = response.encodeURL("/session/list");自动在资源之后拼接;jsessionid=3FB3D48B84806A040F03B070F7DAE56A

    注意:开发中都不会取消接受Cookie的.

11.Session的规范和细节

Session的细节:

        1:一般的,我们存储到Session中的属性名称,要唯一,我们习惯XXX_IN_SESSION;

          session对象.setAttribute("user_in_session","will");

        2:若需要把多个数据存放到Session中,就得调用setAttribute方法N次,可以的.

          一般的我们把需要存储的数据,封装成一个对象,然后存储到Session中.

        3:如果多台服务器之间需要共享Session,此时Session中的对象必须实现java.io.Serializable(才能在网络上传输).

          序 列 化: 把对象信息存储为二进制.

          反序列化:把二进制信息恢复成对象.
相关标签: Servlet