servlet笔记

一 : 引入servlet?和jsp?。
    1,html属于静态页面
        动态页面:数据的动态
     form action="服务器地址"
      html页面的数据发送到服务器表单
      key value
      input name="key" value="value"

    2,html显示显示固定(动态页面->.jsp)
       servlet : 接受数据
             和数据库交互(对数据操作)
             把数据交给页面进行显示
       .jsp    : 显示servlet传过来的数据

    3,不能和数据库结合
    4,java代码和html怎么联系

二 : 三层架构:
    2.1:原因:区分层次的目的即为了“高内聚低耦合”的思想
    2.2:web层:接受数据和传输数据
    2.3:service:负责处理数据(业务逻辑)
    2.4:dao:负责和数据库交互
    优点:
        1,开发人员可以只关注整个结构中的其中某一层
        2,可以降低层与层之间的依赖
        3,可以很容易的用新的实现来替换原有层次的实现

三:软件架构
    3.1 : C/S模式软件: 客户端/服务器
    3.2 : B/S模式软件: 浏览器/服务器
    3.3 : 架构原则:客户端操作服务器端
      
    3.4:浏览器:各大公司生产的软件,可以在地址栏输入对应的服务器进行访问,内置解析器去处理html页面效果和css样式
    3.5:软件实质:一堆数据的操作
    3.6:web项目的实质:连个软件之间的信息交互操作.
    3.7:web项目访问的过程:
        浏览器发送请求-->服务器接受请求-->处理--->---
                            |
        浏览器接受响应--<------服务器返回响应----<---

        web项目中数据的交互都是基于http协议.

    3.8:web项目的开发
        3.8.1:使用servlet和jsp技术
        基于服务器:
          servlet 和 jsp 不能直接运行
          供服务器调用
        java代码:特殊的功能
        java+html
        3.8.2:servlet和jsp需要部署在服务器上才能运行
        3.8.3:servlet和jsp不需要写main方法运行
        3.8.4:利用servlet和jsp编写有功能的代码
        3.8.5:把代码部署到服务器上(tomcat)
        3.8.6:启动服务器
    补充:
        1,web项目不要写main方法,使用服务器运行代码
        2,对象的创建和销毁调用等都由服务器控制
    
    请求 交给 servlet 处理
    多个不同的请求-->交给多个不同的servelt处理

    url --> servlet


四 : servlet特点
    1,Servlet是一个供其他java程序(Servlet引擎)调用的java类,它不能独立运行

    2,Servlet引擎是一种容器程序,它负责管理和维护所有Servlet对象的生命周期,因此也被称之为Servlet容器或Web容器。

    3,Servlet引擎负责将客户端的请求信息转发给Servlet和将Servlet生成的响应信息返回给客户端。
    4,基于HTTP协议
    5,每次访问都会启动一个线程
    6,使用java开发


五 : j2ee:企业级应用程序开发,能够帮助我们开发和部署可移植、健壮、可伸缩且安全的服务器端项目 Web Project Java应用程序。
      接下来我们学习的j2ee开发都是基于B/S架构

六 : tomcat:介绍
    Tomcat是 Apache的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。
    Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器.
    在中小型系统和并发访问用户不是很多的场合下被普遍使用.
    是开发和调试JSP 程序的首选.
    用来响应请求
        
    servelt 响应 给 servlet引擎
    .jsp--->html--->页面显示


七 : 了解tomcat:
    1,解压后目录的含义:
        1, bin    目录:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat6.exe、tomcat6w.exe,
                前者是在控制台下启动Tomcat,后者是弹出GUI窗口启动Tomcat;如果是解压版,那么会有startup.bat和shutdown.bat文件,startup.bat用来启动Tomcat,但需要先配置JAVA_HOME环境变量才能启动,shutdawn.bat用来停止Tomcat;

        2, conf    目录:tomcat的配置文件.这是一个非常非常重要的目录,这个目录下有四个最为重要的文件:

        3, lib    目录:Tomcat的类库,里面是一大堆jar文件。如果需要添加Tomcat依赖的jar文件,可以把它放到这个目录中,当然也可以把应用依赖的jar文件放到这个目录中,这个目录中的jar所有项目都可以共享之,但这样你的应用放到其他Tomcat下时就不能再共享这个目录下的Jar包了,所以建议只把Tomcat需要的Jar包放到这个目录下;
                 写web项目不要直接把jar包build path依赖到项目中,这样依赖到项目中的jar包tomcat会找不到jar包的路径,就相当于项目在tomcat上运行,没有这个jar包...

        4, logs    目录:记录tomcat日常运行的情况或者错误信息。

        5, temp    目录:存放Tomcat的临时文件,这个目录下的东西可以在停止Tomcat后删除!

        6, webapps目录:存放web项目的目录,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的。项目。其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。http://localhost:8080/examples,进入示例项目。其中examples就是项目名,即文件夹的名字。

        7, work    目录:运行时生成的.class文件,最终运行的文件都在这里。通过webapps中的项目生成的!可以把这个目录下的内容删除,再次运行时会生再次生成work目录。当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。
               
        8, LICENSE:许可证。  (不用理它)

        9, NOTICE: 说明文件。(不用理它)
    2,目录下文件的含义
        bin:
            startup.bat:    Wind启动tomcat服务器
            startup.sh:    ubuntu启动tomcat服务器
            shutdown.bat:    wind关闭tomcat服务器
            shutdown.sh:    ubuntu关闭tomcat
        conf:
            context.xml:配置数据源,对所有应用的统一配置,通常我们不会去配置它。

            server.xml:配置整个服务器信息。例如修改端口号,添加虚拟主机等
                    第64行的<Connector>中可以修改的属性:URIEncoding='UTF-8' port='8080' redirectPort="8443"从定向的端口号

            tomcatusers.xml:存储tomcat用户的文件,这里保存的是tomcat的用户名及密码,以及用户的角色信息。
                    可以按着该文件中的注释信息添加tomcat用户,然后就可以在Tomcat主页中进入Tomcat Manager页面了;

            web.xml:部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间说明文档类型的,
                如用户请求一个html网页,那么服务器还会告诉客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型。
                客户端浏览器通过这个MIME类型就知道如何处理它了。当然是在浏览器中显示这个html文件了。
                但如果服务器响应的是一个exe文件,那么浏览器就不可能显示它,而是应该弹出下载窗口才对。
                MIME就是用来说明文档的内容是什么类型的!

    3,怎么样把项目部署到tomcat服务器上

        1,先把tomcat集成到Eclipse中
            步骤:window-->preferences-->Server->Runtime Environments-->add-->apache-->Apache Tomcatv7.0-->next>Browse->文件系统中选择tomcat解压的文件夹--->finish

        2,选择javaEE视图
        3,点击servers选项卡,点击new server wizard... --->finish--->这样就完成了tomcat依赖到Eclipse

        4,双击Tomcat v7.0 Server at Localhost[Stopped,Republish]--->跳出选项卡--->必须操作:1,Server Locations 下点选第二个 Use Tomcat installation(takes control of Tomcat installation)选择项目安装位置--->在下面Deploy path:的input框中删除掉wtpwebapps中的wtp。2,在Ports部分 第二个HTTP/1.1  后面的端口号改成8099

        5,右键new一个 Dynamic Web Project 动态web项目--->项目名(访问项目时需要用到)--->next--->next-->勾选Generate web.xml deployment descriptor-->finish---->到此tomcat服务器准备好了 javaee项目也准备好了

        6,把项目部署到tomcat服务器上:点击servers选项卡,单击Tomcat服务器右键选择add and Remove--->选中项目Add>---->finish

        7,在Eclipse中启动Tomcat服务器,点击servers选项卡,单击Tomcat服务器右键选着start。tomcat就整在启动,点击Console控制台看看有没有报错,没有报错就可以去浏览器访问该项目 localhost:8099/项目名/资源...   改资源必须存在项目下

        8,在Eclipse中关闭Tomcat服务器,点击Console选项卡中的红点,tomcat关闭了 随之项目就访问不到。
        注:创建Dynamic web Project 项目的时候要注意版本Dynamic web module version 的版本 如果是tomcat7.0-->3.0   tomcat6.0--->2.5  tomcat8.0--->3.5
            jdk版本为1.7最好选择Tomcat7.0 如果是1.8也可以选择tomcat7.0

八 : 了解servelt
    8.1 : 用Java编写的服务器端程序。
    8.2 : 主要功能在于交互式地浏览和修改数据,生成动态Web内容。
    8.3 : 狭义的Servlet是指Java语言实现的一个接口,
    8.4 : 广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
    8.5 : Servlet运行于支持Java的应用服务器中。
    8.6 : Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

九 : servlet实例编写

----------------------------- day1 end--------------------------------
    


一.什么是servlet
      1,狭义的Servlet是指Java语言编写的一个接口
      2,广义的Servlet是指任何实现了这个Servlet接口的类
      3,从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
      总结:servlet是java中一个有特殊意义的类.
      
二.servlet的作用
      可以让浏览器直接通过一个地址(URL)去访问。(一般的java类是做不到这一点的)

三.怎么写一个类,能成为一个servlet
      
      1,实现一个接口:javax.servlet.Servlet
    1.1:service(ServletRequestreq,ServletResponse res); 处理请求的方法
    1.2:destroy()在正常关闭web容器或者自动部署服务器的时候调用
    1.3:getServletConfig()返回一个包含了该Servlet的初始化和启动了的参数的ServletConfig 对象
    1.4:getServletInfo()方法返回这个Servlet对象的信息例如作者,版本和版权
    1.5:init(ServletConfig config)创建完servlet后调用init进行初始化操作

      2.继承一个抽象类:javax.servlet.GenericServlet
        2.1,有两个init方法, init(); 本类特有;  init(..)父接口实现;

      3.继承一个抽象类javax.servlet.http.HttpServlet 这种是之后一直要用的方法.
        3.1,有两个service方法;
            service(ServletRequest...) 父类继承
        service(HttpServletRequest...)本类特有
    3.2,一系列的doXxx方法,在本类特有的service方法中 根据请求方式不同调用了不同的doXxx方法
    3.3,默认的doXxx方法没有做任何处理.可以自己重写,得到具有自己项目特色的方法,用来处理请求
   
      4,Servlet接口中的service方法.
         因为无论我们使用哪一种方式去写出来的一个servlet类的中,
         一定会有一个方法叫做service,这个方法是Servlet接口中的定义的,
         tomcat服务器接收到客户端请求后,帮我们调用servlet中的方法的时候,
         它只会调用这一个service方法.
         注意这个service方法中参数的类型:
         service(ServletRequest req,ServletResponse res)

      5.GenericServlet中的俩个init方法
    带参数的init(ServletConfig config)方法是从Servlet接口中实现的,
    还有一个是这个类直接定义的,无参的init()方法.
    tomcat服务器创建servlet对象的时候,会帮我们去调用
    init(ServletConfig config)进行servlet类中的初始化工作,
    所以如果我们想在servlet类中初始化自己的一些相关数据的话,
    需要去重写这个init方法。有参数的init方法中调用了无参的init方法,
    所以将来我们只需要重写这个无参的init方法就可以了。
    这样我们就不需要再专门对这个init(ServletConfig config)方法中的参数进行
    处理了。

      6.HttpServlet中的俩个service方法
    
    ??特有的service 和  Service接口中提供service方法怎么联系

    这个是从Servlet接口中实现的方法.
    service(ServletRequest req, ServletResponse res){
        //强转参数类型
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;

        //调用新定义的service方法
        service(request,response);
     }


     HttpServlet中新定义的方法
     service(HttpServletRequest req, HttpServletResponse resp){
       //拿到当前请求的类型 get/post
       String method = req.getMethod();

       //判断请求的方法 然后去调用doXxx方法
           if(method.equals("GET")){
        doGet(req,resp);
       }
       if(method.equals("POST")){
        doPost(req,resp);
       }
       ...
       ..
     }

      7,Servlet的细节
        7.1 :多个url对应一个servlet
        一个<servlet>可以对应多个<serlvet-mapping>,从而一个Servlet可以有多个路径来访问
        7.2 : url-partten 的路径写法 必须写 /

          7.2.1: /*   通配所有url  推荐不写 , 最好写在最下面
          7.2.2: /a/b 匹配localhost:8099/项目/a/b
          7.2.3: /    缺省的servlet配置,当其他所有都匹配
          
          不上的时候 匹配
    
四 . servlet的生命周期
     servlet的对象是单例:
    在web项目整个运行期间,每一个servlet类只会有一个对象存在.
     1,创建
    默认情况:servlet第一次被访问的时候创建
    设置web.xml提高servl创建的时间,<load-on-startup>1</> (数字越小越先创建): 服务器启动创建
     2,初始化:创建以后立刻初始化,调用init(ServletConfig config)
     3,执行 : 每次被访问的时候都会调用service(ServletRequest req,ServletResponse res);
     4,销毁 :正常关闭服务器,服务器自动重新部署,手动重新部署服务器的时候会调用destroy()进行销毁.
/3/13
五 . servlet的线程安全问题

    问题产生的原因:
        1.servlet是单例,一个servlet类只有一个对象在项目运行期间。
        2.web项目项目本身就有多线程的特点,虽然我们在代码中没有写和线程相关的东西,但是这个多线程的特点是由服务器给我们提供出来的,一个客户端发送了一 个请求,服务器接收到请求后就会建一个线程去处理这个请求。所以就有可能出现这样的情况:俩个线程同时去访问同一个servlet对象.

    如何解决/防止
        1.加锁synchronized 如果一定要用成员变量则用锁来防止线程安全问题,但是要注意锁住内容应该是造成线程安全问题的核心代码,尽量的少锁主内容,减少等待时间提高servlet的响应速度
        2.尽量少的定义成员变量 因为只有成员变量才会产生线程安全的问题(在多个线程访问同一个对象的时 候),方法中的局部变量是没有这样的问题的.
        3.其他(实现一些安全性的接口)

六.客户端向服务器发请求并且传参(get/post) 客户端向服务器发送请求可以是get方式也可以是post方式.所以传参也分为get方式下传参和post方式下传参.

    1.哪些方式的请求属于get/post方式
        get方式:
            a.浏览器中输入地址(URL)然后回车
            b.超链接 <a href="param?name=haha&age=20"></a>
            c.页面中引入的css样式文件
            d.页面中引入的js的文件(javascript)
            e.<img src="image/a.jpg" />
            e.<img src="register" />
            f.form表单中method="get"
            g.ajax中可以设置异步提交请求的方式为get

        post方式:
            a.form表单中method="post"
            b.ajax中可以设置异步提交请求的方式为post

    2.get和post的特点及其区别 它们各自的特点及其区别主要是体现在所传递的参数上面。

        a.get方式参数 参数是直接放在要请求url后面的 例如: url?参数名=参数值&参数名=参数值 要请求的url为:http://ip:port/WebTest/firstServlet 传参: .../firstServlet?name=tom.../firstServlet?name=tom&age=20
                这种方式传参的特点:
        1.参数直接放在url后面
        2.从浏览器的地址栏里面可以直接看到所传的参数
                3.参数的长度有限制,不能把一个很长的数据通过get方式传参.(与浏览器种类有关)

        b.post方式传参 参数是放在请求的体部的。 (浏览器发送的请求可以大致的分为请求头+请求体)
        这种方式传参的特点:
        1.参数放在请求的体部而不是url后面.
        2.浏览器的地址栏中看不到所传的参数.
        3.因为参数不用出现在地址栏里面,所有参数长度是没有限制的.



7.servlet中接收客户端传过来的参数。
    客户端都是以这样的形式传参的: 参数名字=参数值
    所有在servlet中我们需要用参数名字来拿到参数值:
    1,String value = request.getParameter("key");
    其中key就是参数名字,value是参数值,不管传的值本身是什么类型,servlet中接收到以后只能是字符串类型或者字符串类型数组.
    2,如果客户端用的多选框,这个时候传过来的参数就要用一个字符串类型数组来接收:String[] like = req.getParameterValues("like");
    3,在表单中
        参数值就是用户所填写的内容或者是所选的选项的value属性值
        参数名字就是每一个input或者其他输入元素中的name属性的值.
        例如:
        <input type="text" name="username" value="这个是参数的值">
        参数名字就是name属性的值:username
        参数的值就是将来用户所填内容.

    4,在servlet中,不管是get方式提交的时候还是post方式提交的时候,来到servlet里面以后,都是用相同的方式来取得数据。
        request.getParameter("key");
        request.getParameterValues("key");


        请求-->浏览器-->tomcat--->web.xml--->Servlet.java-->代码设置编码


        响应-->相反


        tomcat:servers.xml: 65: URIEncoding="utf-8"
        代码编码: req.setCharacterEncoding("UTF-8");
        响应编码: res.setCharacterEncoding("utf-8");
    

8.中文乱码
    a.get方式提交数据
        servlet拿到后乱码 需要修改tomcat中的配置文件(server.xml的64行),然后重新启动tomcat服务器.

        修改方法: server.xml:64行在这个文件中找到修改端口号的那个标签,然后加入一个新的属性URIEncoding="UTF-8",或者是写GBK、GB2312
        例如: <Connector  connectionTimeout="20000" port="8002" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="GBK"/>

    b.post方式提交数据
        servlet拿到后乱码在代码中,我们去接收数据之前,也就是调用getParameter方法之前,需要先转换一下接收数据的编码:
        req.setCharacterEncoding("GBK"); 里面的值可以是GBK、UTF-8、GB2312

        注意:其实不管是get方式或者是post方式提交数据,我们最后是在Eclipse中打印了出来,所以我们最后还要看看工具中是用
        什么编码显示的我们的数据的.点击一个文件或者项目名字后右键,properties选项中可以看到这个编码.

    c.servlet向浏览器返回数据,浏览器显示乱码.
        在代码中,获得输出流之前,我们要先设置输出流是用什么编码把数据写回去的:
        resp.setCharacterEncoding("UTF-8");
        同时我们还可以通知浏览器我们向它传输的数据是用的什么样的编码:
        resp.setContentType("text/html;charset=UTF-8");


        注意:在我们使用的浏览器中,也是可以调整编码的设置的,就是我们可以自己选择一种编码来显示当前页面的内容,同时浏览器也会有自己一个默认的显示编码.当浏览器不知道服务器传过来的的数据是用什么编码的时候,浏览器会用默认的编码来显示.

9.servlet中的 跳转 .
a.服务器内部跳转
    跳转步骤:
        1,路径: String page = "页面/servlet";
        2,获得分发器 : RequestDispatcher rd =req.getRequestDispatcher(page);
        3,跳转 : rd.forward(req,resp);
             rd.include(req,resp);

    forward跳转特点:会把前一个servlet的东西清除掉(刷新掉)
    

    include跳转特点不会把前一个servlet的东西刷新掉

    a. include(req,resp)
        ServletA写在输出流的内容不会清空,继续保留,ServletB将内容追加的输出流中
        如果ServletA  out.flush(),-----(都显示,close,只显示A)
    b. forward(req,resp)
        ServletA写在输出流的内容会清空,
        如果  out.flush()  抛异常
    
    特点:
    1.不管servlet服务器内部跳转多少次,浏览器地址栏中显示的地址都是第一次访问到的servlet的地址
        ..可以有效的隐藏服务器内部的静态资源
        
    2.服务器内部跳转其实就是把request和response对象进行转发,转发到另外一个服务器内部的一个资源中,如果转发的对象是一个页面,那么就把这个页面返回给浏览器,如果转发的对象是另外一个servlet,那么会调用到这个servlet里面的service方法,然后把之前那个request和response当做传送传进来.


    3.在服务器内部跳转的过程中,每一个环节中所用到的request和response对象都是同一个request和response对象.
    
b.客户端重定向
    1.跳转到一个页面
    2.跳转到另外一个servlet
    String page = "页面/servlet";
    resp.sendRedirect(page);

    特点:
    1.跳转之后,浏览器中显示的是跳转到的那个资源(页面/servlet)的地址,而不是第一次访问的servlet地址.
    2.客服端重定向,其实就是让客户端浏览器重新再发一次新的请求到要跳转的资源。所以在客户端重定向中我们使用的对象是response,因为response这个对象的作用就是向客户端传递数据传递消息用的。
    3.在客户端重定向的过程中,每个环节中所用到的request,response对象都是浏览器新发出的。


10.web项目中的路径问题
    10.1:相对路径 : 最左边没有斜杠
        相对路径是相对于当前路径下的资源
        eg: <img src="a.jpg">

        servlet : url --> /A/B/C
        当前路径: /A/B
        页面:webContent/html/a.html
        当前路径:/html/

        规则:最终访问的资源位置 =  当前路径 + 相对资源名
        eg:
        WebContext/package/abc.html
                  /images/a.jpg
        在abc.html中编写代码 <img src="images/a.jpg">
        解释:src="路径" 由于路径的最左侧没有斜杠 所以按照相对路径进行查找
        规则eg:
        abc.html的当前路径: WebContext/a
        访问的资源为images/a.jpg
        所以 最终访问的资源为 WebContext/a/images/a.jpg --> 该路径没有图片 页面不显示图片
        注 : 所有左侧没有斜杠的资源访问都是相对路径访问资源
    
    10.2,绝对路径 : 路径最左侧是斜杠
        eg: <img src="/a.jpg">

         绝对路径中 / 的含义:
        前台跳转 / 代表服务器路径
            前台跳转有 : html页面的各种资源请求 + 客户端重定向
        后台跳转 / 代表项目路径
            服务器内部跳转
            url-pattern  / 项目
            

11.servlet的三大容器 : request session application
    11.1:容器的作用 : 在多个servlet中进行数据的传递

    11.2:容器 request : 类型  HttpServletRequest
        11.2.1:作用范围 : 作用于一次请求
        11.2.2:向容器中添加数据  request.setAttribute("key",obj);
        11.2.3:从容器中取数据    Object o = request.getAttribute("key");
    
    11.3:容器 session : 类型 HttpSession
        11.3.1:获取: request.getSession(); 标示 一次会话 cookie
        11.3.2:作用范围: 一次会话 (一次会话可以包含多次请求和响应,即多次会话共享)
        11.3.3:向容器中添加数据  session.setAttribute("key",obj);
        11.3.4:从容器中取数据  Object o = session.getAttribute("key");
       
        11.3.5:session的生命周期 *
        1,创建 : 调用getSession();
        2,销毁 : 正常销毁, 存在服务器30分钟 就会正常死亡.
                 设置销毁时间:<session-config>
                    <session-timeout>1</session-timeout>  
                      </session-config>    
             手动销毁 : session.invalidate();
             钝化:当服务器正常关闭,但是没有到session的正常死亡的时间,就会把session序列化到work目录下.
                session对象 写到文件中
             活化:服务器启动,会加载work下的.sess文件,将文件中的所有session对象反序列化到服务器容器中
                把文件中的session对对象加载到服务器中

    11.4:容器 application: 类型 ServletContext
        11.4.1:获取: session.getServletContext();
           获取: this.getServletContext();
           获取: this.getServletConfig().getServletContext();
        11.4.2:作用范围: 当前整个引用都可以使用
        11.4.3:向容器中添加数据 application.setAttribute("key",obj);
        11.4.4:从容器中取数据 Object o = application.getAttribute("key");
        
    11.5:作用范围比较:  request < session < application

12.会话追踪技术 session cookie
    12.1:http协议的访问是无状态的访问(http协议的访问是不会帮我们保存访问的记录/痕迹).
         所以我们就有了会话追踪技术来解决这个访问无状态的问题
    
        当前的请求,不知道上一次请求是什么

    12.2:session和cookie
        1,session是保存在服务器端的一个对象.客户端没有session.

        2,cookie在客户端和服务器端都会有。但是存在的形式不一样.在客户端cookie是以本地文件(浏览器管理的文件)的形式存在的,在服务器端是以java对象的形式存在.
    
        保存数据,上一次请求的状态

    12.3:cookie的作用:保存用户访问的信息数据的。
        区别:
        session是把数据保存在服务器端的内存里面,
        cookie是把数据保存在客户端的文件里面.
    12.4:Cookie 代码编写
        1>服务器端把cookie写回给浏览器
           1,创建cookie对象:
            Cookie c1 = new Cookie("name","tom");
            Cookie c2 = new Cookie("msg","hello");
           2,设置cookie的有效时间
            c1.setMaxAge(60*60*24*365);
            c2.setMaxAge(60*60*24*365*10);
           3,把cookie放到response里面
            resp.addCookie(c1);
            resp.addCookie(c2);
        2>服务端接受请求中携带的cookie
           1,获取请求中的cookie :  Cookie[] cookies = req.getCookies();
           2,获得cookie的Key    :  String key = c.getName();
           3,获得cookie的value  :  String value = c.getValue();
        注:
           1,如果没有设置cookie生效的时间,那么这个cookie就是会话cookie,当会话结束(关闭浏览器)的时候cookie就是失效了。
           2,如果请求中没有任何cookie 那么获得的cookie数组就是null
           3,如果浏览禁用了Cookie,那么服务器没办法把Cookie写回服务器.
    12.4:session流程:
        1:客户端访问服务器
        2,服务器端调用了getSession()方法
        2:服务器判断请求中是否包含key为JSESSIONID的Cookie
            有 : 利用JSESSIONID找到服务器内部对应的Session
            无 : 3
        3:服务器会给这个客户端创建一个会话,也就是一个session对象
        4:服务器为该Session创建id
        5:服务器写回给浏览器一个 key 为JSESSIONID  value 为sessionId值  的Cookie
        
        注: 1,每次发送请求的时候都会携带当前浏览器中该ip所有的cookie
            2,服务器端的内存里面同时可能有好多个session对象,分别对应的不同的客户端,
            3,每一个session对象都有一个唯一的id值,叫做JSESSIONID。
            4,当关闭浏览器的时候会删除名字为JSESSIONID的cookie
    
    12.5:效果:这样以来,最后就能到达一个效果,我们客户端的每一次访问,在服务器端都能够拿到相同的一个session对象,从而实现不同请求之间通过相同的session对象进行数据的共享.


14.URL重写 也属于会话追踪技术的一种.
    
    14.1:URL重写解决的问题:
        禁用cookie以后服务器不能写回Cookie从而找不到对应的Session

    14.2:把JSESSIONID从客户端传给服务器,有俩种方式:
        1.JSESSIONID保存在cookie文件中,浏览器发送请求的时候把这个cookie文件中的数据带给服务器(cookie).
        2.通过传参的方式,把JSESSIONID的值通过要访问的URL传给服务器.(URL重写)

    14.3:如何实现URL重写
        1,String url = resp.encodeURL("想要访问的url");
        2,跳转页面/servlet
        原则:发送请求的时候携带url;jsesionid=值


        例如:在一个超链接中,本来要访问的URL是:<a href="abc">
        重写后: <a href="abc;jsessionid=5480EF9016295A73DC56731A2F123246">

15.Filter(过滤器) : 拦截请求
    15.1:用途:
       1,编码的转换
       2,信息的过滤
       3,权限的判断
       4,登录的验证
    
    15.2:编写filter:
        1,写一个java类,然后实现javax.Servlet.Filter接口
             这个接口中有三个方法: init  destroy  doFilter
            init:这个过滤器类被服务器创建对象的时候会调用到这个方法。
            destroy:过滤器对象被销毁的时候会调用这个方法。
            doFilter:当过滤器拦截到请求的时候,会调用这个doFilter.

        2,重写doFilter(...FilterChain chain)
          FilterChain:过滤器链,可以用来放过请求

        3,在web.xml中进行配置
            <filter>
                <filter-name>encodingFilter</filter-name>
                <filter-class>com.briup.filter.EncodingFilter</filter-class>
            </filter>
            <filter-mapping>
                <filter-name>encodingFilter</filter-name>
                <url-pattern>/*</url-pattern>
            </filter-mapping>
        注意:同一个url配置了多个过滤器,从上到下进行过滤。
    

16,监听器(Listener)
    作用:监听web中的一些事件的发生,如果某些事件一旦发生了,那么这个监听器就会调用某些方法进行处理.

    比如:在web中可以监听request对象的创建和销毁.

    如何去写一个监听器:
        1.写一个类,实现一个特点的接口。
        2.在web.xml文件中进行配置。
        <listener>
            <listener-class>com.briup.listener.RequestListener</listener-class>
        </listener>

     Servlet API中定义了8个监听器接口,可以用于监听ServletContext,HttpSession,ServletRequest对象的生命周期事件。
            ServletContextListener        监听Servlet上下文对象初始化或者被销毁
            ServletContextAttributeListener    监听Servlet上下文中的属性列表的变化

            HttpSessionListener            监听Session生命周期
            HttpSessionActionListener        监听session被钝化或者激活(活化)
            HttpSessionAttributeListener    监听Session属性列表发生的变化
            HttpSessionBindingListener        监听Session中是否有对象绑定或者删除,该对象要实现这个接口//只有这个是该对象实现,其他的都是先写监听器的实现类


            ServletRequestListener        监听ServletRequest对象声明周期
            ServletRequestAttributeListener    监听ServletRequest属性列表发生的变化


    1) ServletContextListener        监听ServletContext的启动或者销毁
    contextInitialized(ServletContextEvent sce)
      当web应用程序初始化进程正开始时,web容器调用这个方法,该方法将在所有的
    过滤器和Servlet初始化之前被调用。
    contextDestroyed(ServletContextEvent sce)
      当Servlet上下文将要关闭时,Web容器调用这个方法,该方法在所有Servlet和
    和过滤器销毁之后被调用。


    2) HttpSessionBindingListener,(无序配置)
    如果一个对象实现了HttpSessionBindingListener接口,当这个对象被绑定的Session
    或者从Session中被删除时,Servlet容器就会通知这个对象。
        valueBound(HttpSessionBindingEvent event)
            当对象正在被绑定到Session中,Servlet容器调用这个方法通知该对象
        valueUnBound(HttpSessionBindingEvent event)
            当从Session中删除对象时,Servlet容器调用这个方法通知该对象

    应用实例: 购物车对象实现该接口,当顾客选购商品时,web应用程序创建购物车对象
        保存到Session中。当Session超时时,Servlet容器会通知购物车,它要从Session
        中被删除了。购物车对象在得到通知后,可以把顾客选购的商品信息保存到数据库
        中。

原文地址:https://www.cnblogs.com/shenhaha520/p/8572603.html