servlet&&jsp

来源:互联网 发布:大数据知识框架 编辑:程序博客网 时间:2024/06/04 19:27
servlet&jsp经典总结 
    如今,通用的浏览器取代了个性化的客户端,HTTP协议取代了个性化的协议,通用的ServerApp(Web服务器)简化了服务器端的开发。
1、软件的三种架构(了解)
(1)主机、终端
    a,特点:主机负责处理所有的业务逻辑,终端只提供操作界面。
    b,优点:可靠、I/O处理能力强。
c,缺点:过于昂贵,而且维护困难。
(2) client/server
   1)二层的c/s
     a,特点:一般将大部分业务逻辑使用特定的数据库语言来进行编写,客户端负责提供界面以及处理少量的业务逻辑。
b,缺点:如果数据库发生改变(比如,从sqlserver换成oracle),需要重写业务逻辑。还有,需要客户端跟数据库之间保持一个数据库连接,所以,不适合大型的应用。
   2)三层的c/s
    a,特点:数据库只负责管理数据,所有的业务逻辑写在应用服务器上面(一般使用java
                语言),客户端只负责提供操作界面。
  b,优点:维护性好(换数据库,不用重写业务逻辑,换应用服务器所在的操作系统或
        者硬件平台,也不影响)
  c,缺点:客户端需要单独安装和调试,另外,开发复杂(需要自定义协议和通讯处理模块)。
   3)browser/server
    a,特点:客户端使用标准的浏览器(不需要去开发了,浏览器里面包含了一个通讯处理模块,使用标准的通讯协议http与服务器进行通讯),服务器使 用标准的web服务器(不需要开发了,里面也包含了一个通讯模块)。
     b,优点:客户端不用再去安装了,不需要自定协议和开发相应的通讯模块了。
 
2、什么是servlet?
 Servlet是sun公司制订的一种用来扩展web服务器功能的组件(也叫组件规范)。
 1)扩展web服务器功能:
  早期的web服务器(apache提供的webserver,微软的iis)只能够处理静态资源的请求(即需要事先将html文件写好),不能够处理动态资源的请求(即需要计算,然后生成相应的页面)。所以需要扩展web服务器的功能。
 可以使用cgi程序来扩展。cgi程序可以使用perl,c等语言来开发,但是,cgi程序开发复杂,还有可移植性差,并且,一个请求会启动一个进程,系统开销会非常大。
 servlet也可以扩展web服务器功能。servlet需要依据servlet容器才能运行,容器负责为servlet提供一些基础服务(比如,容器在收到请求之后,会对请求数据包进行解析,将数据提取出来,交给servlet来处理,这样,在编写servlet时,就不用考虑http协议相关的问题,也不用考虑网络相关的问题)。
2)组件(规范)
a,所谓组件,其实就是一个符合一定规范,实现部分功能,并且可以部署在相应的容器上运行的软件模块。当于汽车上的轮胎,轮胎就是一个符合一定规范,实现了部分功能(跑),并且可以安装在各种汽车上的功能模块,轮胎不挑汽车。 
b,组件跟容器的关系: 容器(APP Server),(如Tomcat、JBoss、Apache Web Servser)也是一个程序,要符合相应的规范,并且提供组件的运行环境,提供相应的基础服务(servlet不依赖于特定的容器)。
 Web容器(也即Web Server):给处于其中的应用程序组件(JSP、Servlet)提供一个环境,使JSP、Servlet直接与容器中的环境变量接口交互,不必关注其他系统问题。主要由Web服务器来实现,如:Tomcat、JBoss、WebLogic等。该容器提供的接口严格遵守J2EE规范中的Web Application标准。我们把遵守以上标准的Web服务器就叫做J2EE中的web容器。
3、如何写一个servlet?
step1,写一个java类,实现Servlet接口或者继承HttpServlet抽象类。
step2,编译。
step3,打包。即创建一个具有如下结构的文件夹:appname
WEB-INF
classes(.class文件)
lib(可选,放.jar文件)
web.xml(部署描述文件)
step4, 部署。将step3创建的文件夹拷贝到servlet容器特定的文件夹下面(比如,tomcat对应的是webapps文件夹)。或者,也可以将step3生成的文件夹压缩(使用jar命令压缩成.war文件),然后再拷贝。
step5,启动servlet容器,访问http://ip:port/appname/servlet-url
4、tomcat的安装与简单的使用
tomcat是一个servlet容器,使用java语言开发出来的。
tomcat不仅仅是一个容器,也可以充当一个web服务器来使用。
1)安装
step1,将/opt下面的压缩文件解压到 /home/soft01
step2,配置环境变量(可以先不做)
cd /home/soft01
vi .bash_profile
添加:
JAVA_HOME:jdk的安装路径
CATALINA_HOME:tomcat安装路径
PATH:tomcat安装路径/bin
step3,启动tomcat
cd /home/soft01/apache-tomcat/bin
sh startup.sh (或者 sh catalina.sh run)
step4, 在浏览器地址栏输入
http://localhost:8080
2)简单使用
a,启动容器
cd /home/soft01/apache-tomcat5.5/bin
sh startup.sh( linux)
startup.bat(windows)
b,关闭容器
cd /home/soft01/apache-tomcat5.5/bin
sh shutdown.sh (linux)
shutdown.bat(windows)
c, tomcat安装之后,几个主要的文件夹的作用:
bin: 可执行文件,比如启动和关闭容器。
common: 可以被所有的程序共享的一些文件。
conf:服务器的配置文件。
5、第一个servlet:  HelloServlet
6、使用myeclipse来开发一个简单的servlet
step1,先启动myeclipse,让myeclipse来管理tomcat
step2,创建一个web工程
servlet是如何运行的?
http://localhost:8080/web01/greeting?name=zs
其中web01/greeting为请求资源路径;
?name=zs为请求参数
step1,浏览器依据ip,port 和服务器(比如tomcat)建立连接,。
step2,浏览器打包(将请求数据按照http协议的要求创建一个数据包),并且将请求数据包发送给服务器。
step3,服务器拆包,服务器创建两个对象:请求对象(Request)和响应对象(Response)服务器解析请求数据包,将解析之后的数据存放到请求对象里面,方便servlet读取请求数据(因为servlet不用解析请求数据包,如果要解析,需要理解http协议)。请求对象是HttpServletRequest接口的一个实现。响应对象是HttpServletResponse接口的一个实现,响应对象存放servlet处理的结果。
step4, 服务器依据请求资源路径(/web01/greeting)找到相应的servlet配置,通过反射创建servlet(准确的说是someServlet)实例。然后调用其service()方法。在调用service()方法时,会将事先创建好的请求对象(request)和响应对象(response)作为参数进行传递。
step5,在servlet的service方法里面,可以通过request对象获得请求参数,也可以在处理请求之后,将处理结果写到response对象上面。
step6, 服务器读取response对象上的数据,然后打包,发送给浏览器。
step7, 浏览器会拆包,生成相应的界面。
8、常见错误的处理
1)404  404是一个状态码(由w3c定义,是一个三位数字,表示不同的含义,服务器通过状态码向客户端传递是否正常地处理了客户端的请求)。
404: 服务器依据请求资源路径,找不到对应的资源。
错误原因:请求资源路径写错。
解决方式:按照 http://ip:port/appname/url-pattern
检查你的请求地址。
     一般为在地址栏中appname或者url-pattern拼写错误
2)500
  500: 服务器处理出错
错误原因:程序在运行过程当中发生了不正常。
解决方式:检查程序代码和相应的配置文件(web.xml)。
     一般为appname.xml文件中的<servlet-class>appname.classname</servlet-class>
     中的appname或者classname元素拼写错误。
3)405
405: 找不到对应的方法来处理请求
解决方式:仔细检查service方法的签名。
     一般为service方法名拼写错误
  如果想了解详细的http状态吗说明,请查看:http://blog.csdn.net/zhu_xun/article/details/16843861
http://ip:port/appname/servlet的url-pattern配置。
其中:appname缺省情况下为工程名。
9、http协议(了解)
(1)什么是http协议?
由w3c制订的一种应用层协议,定义了浏览器(或者是其它客户端)与web服务器之间通讯的过程与数据的格式。
(2)通讯的过程:
step1,浏览器建立与web服务器之间的连接
step2,浏览器将请求数据打包,然后发送请求给web服务器。
step3,服务器将处理结果打包,发送响应给浏览器。
step4,服务器关闭连接。如果浏览器要再发请求,必须重新建立新的连接。
特点: 一次请求,一次连接。
优点:web服务器可以利用有限的连接为尽可能多的客户端服务。
     一次会话及一次交互,包括一次请求和一次想应。
(3)数据包的结果
1)请求数据包
a,请求行: 请求方式 请求资源路径协议类型和版本
b,消息头(若干):消息头是一些键值对,一般由浏览器或者服务器自动生成,表示一些特定的含义,比如,浏览器可以向服务器传递user-agent消息头,告诉服务器浏览器的类型和版本。
  c,实体内容:只有当发送post请求时,才会将请求参数放在实体内容里面,如果是get请求,请求参数会放在请求行。
2)响应数据包
a,状态行: 协议的类型和版本 状态码 状态描述状态码是一个三位数字,常见的有:
  404:依据请求资源路径,找不到对应的资源。
500:系统出错。
200:正常。
b,消息头(若干):比如,服务器可以发送一个content-type消息头,告诉浏览器,返回的数据类型及编码。
c,实体内容:放的是程序处理的结果。
浏览器发送的数据包实例:
GET方式:
浏览器发送的数据包:GET /web01/greeting?name=zhu HTTP/1.1
  Host: localhost:8888
  Connection: keep-alive
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko)  Chrome/26.0.1410.64 Safari/537.31
  Accept-Encoding: gzip,deflate,sdch
  Accept-Language: zh-CN,zh;q=0.8
  Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
 
服务器发送的数据包:HTTP/1.1 200 OK
             Server: Apache-Coyote/1.1
    Content-Type: text/html;charset=utf-8
  Content-Length: 18
  Date: Thu, 09 May 2013 03:27:25 GMT
POST方式:
浏览器发送的数据包:
  POST /web01/greeting HTTP/1.1
  Host: localhost:8888
  Connection: keep-alive
  Content-Length: 8
  Cache-Control: max-age=0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Origin: http://localhost:9009
  User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko)  Chrome/26.0.1410.64 Safari/537.31
  Content-Type: application/x-www-form-urlencoded
  Referer: http://localhost:9009/web01/greeting_form.html
  Accept-Encoding: gzip,deflate,sdch
  Accept-Language: zh-CN,zh;q=0.8
  Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
  name=zhu
服务器发送的数据包:
  HTTP/1.1 200 OK
  Server: Apache-Coyote/1.1
  Accept-Ranges: bytes
  ETag: W/"181-1368069665007"
  Last-Modified: Thu, 09 May 2013 03:21:05 GMT
  Content-Type: text/html;charset=utf-8
    Content-Length: 181
  Date: Thu, 09 May 2013 03:21:44 GMT
注:对于服务器发送的响应数据包,如果,在.java文件中没有设置
response.setContentType("text/html;charset=utf-8");或者在.jsp文件中没有设置:
<%@ page contentType="text/html;charset=utf-8"%>(其实两者的设置是等价的),那么服务器发送的数据包便不会包含Content-Type: text/html;charset=utf-8
10、get方式与post方式
(1)哪一些是get方式
a,在浏览器地址栏输入某个地址。
b,点击链接
c,表单默认提交
(2)哪一些是post方式
设置表单的method="post"时。
(3)get方式的特点
a,get方式会将请求参数添加到请求行(请求资源路径的后面),只能提交少量的数据给服务器。
b,get方式会将请求参数显示在浏览器地址栏,不安全。
(4)post方式的特点
a,post方式会将请求参数添加到实体内容里面,可以提交大量的数据给服务器。
b,post方式不会将请求参数显示在浏览器地址栏,相对安全。 
11、编码知识:
编码:由一种字节数组转换为另外一种字节数组
1)java语言在内存当中,保存的任何的字符都是使用unicode编码格式。 
2)什么是编码?
对于java程序来说,将unicode编码格式对应的字节数组转换成某种本地编码格式(gbk,utf-8)对 应的字节数组。
3)什么是解码?
对于java程序来说,将本地编码格式对应的字节数组转换成unicode编码格式对应的字节数组。
12、表单的处理
1)如何获得请求参数值
方法一:
String request.getParameter(String paraName);
注意:如果参数名称不正确,会获得null。
方法二:
String[] request.getParameterValues(String paraName);
注意:如果有多个请求参数的名称相同。
  ?city=bj&city=wh&city=cs
  方法三:
            request.getParameter()获得所有请求参数的名字
       方法四:
            request.getParameterMap()获得所有请求参数的键值对。
  2)如何处理中文参数值
  当表单提交时,浏览器会对表单中的中文参数值进行编码(使用哪种编码 格式,要看打开表单所在的页面的编码格式)。
  服务器(确切地说是servlet)在默认情况下,会使用iso-8859-1去解码。这样,就出现了乱码问题。
  解决方式:
  方式一:
  step1,确保表单所在的页面,按照指定的编码格式打开,以及向服务器提交表单。
  在html文件当中,添加:<meta http-equiv="content-type" content="text/html;charset=utf-8">
  step2,在服务器端,告诉服务器按照指定的编码格式去解码。
  //只对post方法请求有效
  request.setCharacterEncoding("utf-8");
  方式二:
  step1,同上。
  step2, 
            //对get和post方法请求均有效
            String name2 = new String(name.getBytes("iso-8859-1"),"utf-8");
13、访问数据库
1)mysql数据库的使用
  a,登录
    mysql -uroot;
  b,查看有哪些数据库实例
   show databases;
c, 创建一个数据库实例(使用utf8字符集)
  create database  jd1302db default 
  character set utf8;
  d,使用某一个数据库实例 
  use jd1302db;
  e,查看当前数据库有哪些表
  show tables;
  f, create table t_emp(
   id int primary key auto_increment,
   name varchar(50),
   salary double,
   age int
    );
   auto_increment:自增长列,插入记录时,由数据库自动赋值。
   insert into t_emp(name,salary,age) values('tom',20000,22);
  2)使用jdbc访问数据库
  step1,将jdbc驱动(比如 mysqldriver.jar)拷贝到WEB-INF\lib下。
  step2, 在servlet类里面,编写jdbc代码,要注意异常的处理。
14、重定向:
1、重定向
  (1)什么是重定向?
  服务器向浏览器发送一个302状态码和一个Location消息头(包含了一个地址,称之为重定向地址),浏览器收到之后,会立即向重定向地址发请求。
  (2)如何重定向?
  response.sendRedirect(String url);
  (3)需要注意的问题
  a, 重定向之前,不要调用out.close()。
  b,重定向之前,会先清空response中缓存的数据。
       c,重定向不等同于return,之后的代码仍然会得到执行。
       eg:response.sendRedirect(“main.jsp”);
            System.out.println(“Hello”);
            重定向之后,服务器端仍然会输出Hello
  (4)特点
  a,重定向的地址是任意的。
  b,重定向之后,浏览器的地址会变成重定向地址。
  服务器发送给浏览器的信息内容:
  HTTP/1.1 302 Moved Temporarily
  Server: Apache-Coyote/1.1
  Location: http://localhost:8888/web01/list
  (或者是Location: http://http://tts6.tarena.com.cn)
  Content-Type: text/html;charset=utf-8
  Content-Length: 0
  Date: Fri, 10 May 2013 02:29:20 GMT
15、dao(data access object)
(1)dao是什么?
  封装了数据访问逻辑的模块。
  (2)如何写一个dao?
  step1,实体类
  为了方便对数据库中的记录进行操作而设计的一个简单的java类,一般与数据库的表对应。
  step2, dao接口
  在dao接口当中,声明一系列的数据访问方法。不要涉及任何具体的实现技术。
  比如:
  public ResultSet findAll();  error!
  public List<Employee> findAll throws SQLException;  error!
  public List<Employee> findAll throws Exception;  ok
  step3, dao实现
  使用具体的数据库访问技术实现dao接口
  step4, 工厂类
  工厂设计模式:工厂将对象的创建过程
  对外屏蔽,为调用者提供符合接口要求的对象。
  将中文数据插入到数据库:
  step1:要保证数据库正确设置了字符集。
  eg:create database jsd1302 default character set utf-8;
  step2:因为某些mysql的jdbc驱动不能够正确地进行编码和解码(默认会按iso-8859-1进行编码和解码),所以需要添加两    个参数:
  DriverManager.getConnection("jdbc:mysql://localhost:3306/jsd1302db?userUnicode=true&&characterEncoding=utf-8","root","zhuxun");
16、容器如何处理请求资源路径?
http://ip:port/web04/abc.html
浏览器会将"/web04/abc.html"作为请求资源路径发送给容器。
step1,容器依据应用名("/web04")找到应用所在的文件夹。
  step2,容器先假设要访问的是一个servlet,接下来,要使用web.xml中的配置来查找对应的servlet配置。
  容器匹配过程:
  精确匹配:
  比如,要求<url-pattern>的配置必须是"/abc.html"。
  通配符匹配:
  使用"*"来匹配任意0,1,或者多个字符,比如
  <url-pattern>/*</url-pattern>
  /abc.html
            使用通配符时,如果请求资源路径中有abc.html/abc.jsp等静态页
            面时,也会被xml匹配,也就相当于找到了匹配项,就会执行servlet
            对应的代码,而无法访问abc.html页面本身。
  后缀匹配:
  使用"*."开头,后接任意的一个或者多个字符。比如
  <url-pattern>*.do</url-pattern>
  会匹配所有以".do"结尾的请求。
  step3,如果找不到对应的Servlet配置,容器会认为这是一个静态资源,然后依据请求资源路径查找这个静态资源,找到了,则返回;找
              不到,返回404。
17、如何让一个servlet处理多种不同的请求。
step1,使用后缀匹配模式,比如
  <url-pattern>*.do</url-pattern>
  step2,分析请求资源路径,依据请求资源路径的不同,调用不同的分支来处理。
  String request.getRequestURI();
18、servlet的生命周期
(1)什么是servlet的生命周期?
  所谓生命周期,指的是servlet容器如何创建servlet实例、分配其资源、调用其方法、并销毁其实例的整个过程。
  (2)servlet生命周期的四个阶段
  1)实例化(调用构造器创建servlet对象):
  a,有以下两种情况:
  a, 当请求到达容器时,容器检查找该servlet对象是否存在,如果不存在,才会创建实例。(不管有多少个请求,容器只会创建一个servlet对象,也就是说,容器收到请求之后,会先看对应的servlet对象是否存在,如果存在,则不再创建了,否则会创建)。
                  注意:如果让servlet实现SingleThreadModel接口,容器会为每一个实现了该接口的servlet创建多个实例
  b, 容器在启动时,或者新部署了某个应用时,会检查web.xml
           当中,servlet是否有 load-on-startup配置。如果有,则会创建该servlet实例。load-on-startup参数值越小,优先级越高(最小值为0,优先级最高)。
  2)初始化(分配其资源):
  a1,容器调用servlet对象的init方法,该方法只会执行一次。
  a2,一般情况下,不需要写自己的init方法,因为GenericServlet已经提供了init方法的实现:
    init(ServletConfig config)方法需要ServletConfig对象作为参数,该对象可以用来访问servlet的初始化参数(通过
                   getInitParameter方法)。
  a3,初始化参数的使用:
    step1, 在web.xml文件当中,使用<init-param>来配置,初始化参数必须放在<servlet><servlet>之间
  step2,使用String ServletConfig.getInitParameter(String paraName);
   eg:<servlet>
   ..........
        <init-param>
    <param-name>company</param-name>
    <param-value>tarena</param-value>
         </init-param>
        ............
     </servlet>
      String company = config.getInitParameter("company");
      System.out.println("company:" + company);//tarena
  a4,如果要实现自己的初始化处理,建议override init()方法。
  3)就绪(调用其方法处理请求):
  a1, 容器会调用servlet对象的service方法来处理请求。
  a2, HttpServlet的service()方法,会依据请求方式来调用doGet()或者doPost()方法。但是,这两个do方法默认情况
                   下,会抛出异常,需要子类去override。
  a3,可以将处理逻辑写在service方法或者doGet/doPost方法里面。
  4)销毁(销毁servlet对象):
  在删除之前,会调用servlet对象的destroy()方法。
  destroy()方法用于释放资源。
  在servlet的整个生命周期当中,init,destroy只会执行一次,而service方法会执行多次。
  (3) servlet生命周期相关的几个接口与类
  a,Servlet接口:
  主要声明了三个方法
  init(ServletConfig config):初始化
  destroy():销毁
  service(ServletRequest req,ServletResponse res):就绪
  b,GenericServlet抽象类(实现Servlet)
  实现了Servlet接口中的init,destroy方法。
  c,HttpServlet抽象类(继承于GenericSerlet)
   继承了GenericServlet,实现了service方法。    
          d,ServletConfig接口
  String getInitParameter(String paraName);
  e, ServletRequest,ServletResponse接口分别是
  HttpServletRequest,HttpServletResponse接口的父接口。
someServlet—>GenericServlet->HttpServlet—>Servlet(interface)
19、jsp
(1)jsp是什么?
java server page:java服务器端页面技术
  sun公司制订的一种服务器端动态页面生成技术规范,主要负责显示逻辑。因为直接使用servlet虽然也可以生成动态页面,但是,过于繁琐(需要使用out.println),并且难以维护(如果页面要修改,需要修改java源代码)。所以,sun制订了jsp规范。
 
jsp就是在HTML中嵌入Java代码,所以在本质上Jsp程序就是Java程序。
 
jsp其实是一个以".jsp"为后缀的文件,该文件的内容大部分是html(css,js),少部分是一些java代码。该文件不需要开发人员去编译,容器会自动将.jsp文件转换成一个.java文件(其实就是一个servlet类),接下来,容器会调用这个servlet来处理请求。
  (2)如何去开发一个jsp?
  step1,先写一个以.jsp为后缀的文件。
  step2,在jsp文件里面,可以添加如下的内容:
  1)html(css,js): 直接写。
  2)java代码:
  a, java代码段:<% java代码  %>
  b, jsp表达式<%= java表达式%>
                      <%=new Date() %>  等于out.println(new Date());
                  c,java声明:<%!变量(属性)、方法%>,在.jsp文件中声明的变量,会转换为.java文件中对应的属性
  3)隐含对象:
  a,什么是隐含对象 ?
  在.jsp文件当中,不用声明和创建,就可以
  直接使用的对象,比如 out。
  b,隐含对象的本质?
  容器会在对应的servlet类当中,自动添加声明和创建这些对象的代码。
  c,常见的隐含对象:
  out,request,response,session
  4)指令
  a,什么是指令?
  通知容器,在将.jsp文件转换成.java文件时,做一些额外的处理(比如,导包,设置编码格式,插入文件等)
  b,指令的语法
  <%@ָ令的名称 属性名称=属性值 %>
  c,page指令
  import属性:导包,比如
  <%@page import="java.util.*"%>
  <%@page import="java.util.*,java.text.*"%>
  contentType属性:设置response.setContentType的内容。
pageEncoding属性:告诉容器,jsp文件的编码格式。因为容器需要先读取jsp文件的内容
                                         (即解码),某些容器不能够正确识 别jsp文件的编码格式,需要明确指
                                          定。servlet&jsp经典总结 eg: <%@pagecontentType="text/html;charset=utf-8" pageEncoding="utf-8" import="java.util.*"%>
  contentType="text/html;charset=utf-8" 可以间接的设置response.setContentType("text/html;charset=utf-8")
  pageEncoding="utf-8":告诉容器,jsp文件的编码格式。因为容器需要先读取jsp文件的内容(即解码),某些容器不能够正确识别jsp文件的编码格式,需要明确指定。
  (3)jsp是如何运行的?
  step1,容器会先将.jsp为后缀的文件转换成一个.java文件(其实就是一个servlet) 。
  html(css,js) -------> 在service方法里,使用out.write输出。
  <% x %>    --------->放到service方法里,照搬。
  <%= x %>    ---------> 在service方法里,使用out.print(x)输出。
            <%!...%>  --------->给servlet添加新的属性或者方法。
             .jsp文件:
   <body style="font-size:30px;font-style:italic;">
  <%! int i = 100;
  int add(int a,int b){
  return a + b;
  }
  %>
   <%=i%><br/>
  1+1=<%=add(1,1)%>    
   </body>
  .java文件:
  public final class a1_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {
  int i = 100;//属性
  int add(int a,int b){//方法
  return a + b;
  }
  step2, 容器会调用servlet来处理请求。
          对应的.java文件:
  
20、转发
(1)什么是转发?
  一个web组件(servlet/jsp)将未完成的处理通过容器转交给另外一个web组
  件继续完成,转发的组件共享request和response。转发可以实现不同web组件之间的数据传递,这样可以方便实现业务逻辑和显示逻辑相分离。
  最常见的情况:一个servlet获得了相应的数据,然后转发给一个jsp,
                      由这个jsp依据这些数据进行展现。
  (2)如何转发?
  step1,绑订数据
  request.setAttribute(String name,Object obj);
  step2,获得一个转发器
  RequestDispatcher rd = request.getRequestDispatcher(String url);
  step3,转发
  rd.forward(request,response);
  在转发的目的地(比如一个jsp),可以调用
  Object request.getAttribute(String name);
       其中:request.getAttribute(String name)返回的为Object型的对象,需要根
       据实际情况进行类型转换。
  注意:如果绑订名称(即name参数)对应的值不存在,返回null。
  (3)需要注意的问题:
  a,转发执行之前,不能够调用out.close()。
  b,转发执行之前,会先清空response上缓存的数据。
          c,转发和重定向一样,均不等同于return,之后的代码扔然会得到执行。
         eg:
  request.getRequestDispatcher("emplist.jsp").forward(request,response);
            System.out.println(“Hello”);
            转发之后,服务器端仍然会输出Hello
  (4)特点
  a,转发之后,浏览器地址栏的地址不变。
  b,转发的目的地必须是同一个应用内部的某个组件的地址
       c,转发所设置及的各个组件可以共享同一个request,response对象
  转发和重定向的区别:
  1)地址
  转发的地址必须是同一个应用内部的某个组件(不能跨应用,不能跨服务器),重定向的地址没有限制。
  2)能否共享request
  转发可以,重定向不行。原因是转发是一次请求,重定向为两次请求,Request的生命周期只能在一次请求内,请求结束,Request 被删除。(因为request,response对象的生命周期与一次请求响应的时间相同。即当请求到达容器时,容器创建request,response,当响应发送完毕,容器会销毁request,response)。
  3)浏览器地址栏的地址是否变化
  转发不变,重定向会变。
  4)事件是否处理完毕
  转发是一件事未做完,重定向是一件事已经做完(一件事有多个组件协同完成)。一件事情已经做完,再做另外一件事情,使用重定向;一件事情未做完,使用转发。
  5)代码执行效率
  重定向中,浏览器需要向新连接发送请求,而转发不需要。(所以重定向效率较低)
21、servlet异常如何处理?
方式一:
  使用转发
  step1,绑订错误提示信息到request对象上,然后转发给相应的错误处理页面。
  step2,编写错误处理页面。
  有以下两种情况:
  情况一:
     Servlet:
   request.setAttribute("error", "系统繁忙,请稍后重试!"); request.getRequestDispatcher("error.jsp").forward(request, response);
    JSP:
    <body>
        <%=(String)request.getAttribute("error") %>
    </body>
    情况二:
     Servlet: request.getRequestDispatcher("error.jsp").forward(request, response);
    JSP:
  <body>
  <h1>系统出错,请稍后重试!</h1>
  </body>
  方式二:
  让容器处理
  step1,将异常抛给容器
  step2,编写一个错误处理页面,并且配置:
  web.XML:
  <error-page>    
    <exception-type>javax.servlet.ServletException</exception-type>
    <location>/error.jsp</location>
  </error-page>
  Servlet:
  throw new ServletException();
  方式三:
  使用重定向:
  response.sendRedirect(“error.jsp”);
  注:服务器出现异常后,如果servlet.java中没有捕获异常并处理,那么异常会自动交给容器进行处理,容器会查找web.xml配置中是否有错误处理页面的配置,如果找不到就会向浏览器返回异常信息。
22、include指令 
   告诉容器,在将.jsp文件转换成.java文件时,在指令所在的位置插入file属性所指定的文件,以实现页面的拆分。
    比如: <%@include file="head.jsp"%>
23、路径问题
1)什么是路径问题?
在填写链接地址(<a href="del.do">test</a>)、
  表单提交地址(<form action="modify.do">)、
      重定向(response.sendRedirect("list.do"))以及转发(request.getRequestDispatcher("empList.jsp"))时
  如何写相对路径和绝对路径。
2)什么是相对路径
  不以"/"开头的路径,表示相对于当前路径。
  3)什么是绝对路径
  以"/"开头的路径,在jsp中ip地址即为当前跟路径。
  4)如何去写绝对路径
  链接地址、表单提交地址、重定向地址应该从应用名开始写,转发的地址应该从应用名之后开始
  写(因为转发的目的地必须是同一个应用内部的某个组件的地址)。
  在实际应用开发中应尽量使用绝对路径()。
  使用绝对路径时,一定不要将应用名写死,应该使用 String request.getContextPath()来获得
  实际部署时的应用名。
 (因为web容器如果更改部署路径,则以前页面中使用的地址会失效,如部署路径由web01给位web02后,之前的还有”/web01”便会无效)
24、案例
   登录
   drop table if exists t_user;
   create table t_user(
   id int primary key auto_increment,
   username varchar(50) unique,
   pwd varchar(30),
   age int
   );
   unique: 唯一性约束。
    insert into t_user(username,pwd,age) 
    values('tom','test',22);
25、中文如何处理(连接数据库的情况下)
.html文件:
.html文件中,要添加如下代码,确保浏览器打开页面所用的编码格式以及该页面提交表单时的数据编码:
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
.java文件:
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
.jsp文件:
.jsp文件中,要加入如下代码,其中第一行代码的作用是设置.jsp文件被容器编译时的编码格式,第二行相当于间接的设置了:response.setContentType("text/html;charset=utf-8");: 
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"  contentType="text/html;charset=utf-8"%>
 还要设置表单中的method="post"。
 数据库配置:
 如果要访问数据库:
 保证数据能够正常地保存中文。
 对于mysql数据库:
 create database dbname default characther set utf-8;
 使用jdbc访问数据库是,必须保证jdbc驱动程序能够识别数据库中保存的数据的编码。
 jdbc:mysql://localhost:3306/jsd1302db?useUnicode=true&charterEncoding=utf8;
26、状态管理
 (1)什么是状态管理?
 HTTP协议的特点为:一次请求,一次连接。所以每次交互时,需要重新建立连接,那么多次交互时便不能共享数据。
   状态管理可以将浏览器与web服务器之间多次交互(一次交互即一次连接的建立和断开)当作一个整体来看待,并且将多次交互所涉及的数 据保存下来。
 (2)怎样进行状态管理?
  a, 使用cookie将状态(多次交互所涉及的数据)保存在客户端。
  b, 使用session将状态保存在服务器端。
     浏览器在第一次访问服务器时,服务器将一些数据以set-cookie消息头的形式发送给浏览器。浏览器会将这些数据保存起来。当浏览器再次访问服务器时,会将这些数据以cookie消息头的形式发送给服务器。通过这种方式,可以管理用户的状态。
 (3)cookie技术
1)什么是cookie?
a,是一种客户端的状态管理技术
b,浏览器访问服务器时,服务器会将少量的数据使用set-cookie消息头的方式发送给浏览器。
        浏览器会将这些数据保存下来,当浏览器再次访问服务器的时候,会将这些数据以cookie消息头的方式发送给服务器。
2)创建cookie
  Cookie c = new Cookie(String name,String value);
  response.addCookie(c);
    eg:  //创建Cookie
  Cookie c1 = new Cookie("username", "tom");
  Cookie c2 = new Cookie("realname",URLEncoder.encode("小飞虾","utf-8"));//添加中文字符
  Cookie c3 = new Cookie("sex", "male");
  Cookie c4 = new Cookie("age", "23");
  response.addCookie(c1);
  response.addCookie(c2);
  response.addCookie(c3);
  response.addCookie(c4);
  out.println("<h1>添加cookie成功</h1>"); 
  out.close();
  服务器发送的响应消息包:
  HTTP/1.1 200 OK
  Server: Apache-Coyote/1.1
  Set-Cookie: username=tom
  Set-Cookie: realname=%E5%B0%8F%E9%A3%9E%E8%99%BE
  Set-Cookie: sex=male
  Set-Cookie: age=23
  Content-Type: text/html;charset=utf-8
  Content-Length: 29
  Date: Wed, 15 May 2013 06:15:14 GMT      
  3)查看cookie
  Cookie[] request.getCookies();
  注意: 该方法有可能返回null。
  String cookie.getName();
  String cookie.getValue();
  eg:   Cookie[] cookies = request.getCookies();
  if(cookies != null){
    for(int i = 0; i <cookies.length;i++){  
                 Cookie c = cookies[i];
      String name = c.getName();
      String value = c.getValue();
      out.println("<h2>"+name + ":" + URLDecoder.decode(value, "utf-8") );
  //如果value为普通字符串(不含有”%”URLDecoder.decode(value,"utf-8") 的值仍为vlaue
  }esle{
                  out.println(“没有任何Cookie”);
                 }
             }
       浏览器发送的请求数据包:
   GET /web06/findCookie HTTP/1.1
   Host: localhost:8888
       User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
   Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
       Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
   Accept-Encoding: gzip, deflate
       Cookie: 
   username=tom; sex=male; age=23; realname=%E5%B0%8F%E9%A3%9E%E8%99%BE
   Connection: keep-alive
  4)编码问题
  cookie的值只允许是ascii字符,如果是中文,需要将中文转换成相应的由ascii和“%”组成的字符串。
  String URLEncoder.encode(String str,String code);
  String URLDecoder.decode(String str,String code);
  因为ascii码不支持中文,所以要想让cookie保存中文(确切地说是中文的另外一种表示形式),就要在创建cookie时将中文用某种方法按照特定格式转换成一串标记,这样cookie就可以保存这种标记了(间接的保存了中文)。当下次,服务器查看cookie时,会将获取到的中文标记通过相应的方法按照相应的格式进行还原(把中文标记转换为中文)。
  eg:
  创建cookie:
  Cookie c = new Cookie("username",URLEncoder.encode("小飞虾","utf-8"));
  response.addCookie(c);
  其中URLEncoder.encode("小飞虾","utf-8")方法将字符串”小飞 虾”按照utf-8的编码方式转换成相应的字符串(形如:%AE%A5%BD%...,字符串实际上是相应的字节数组中数组元素的16进制加上了%)。
查看cookie:
  Cookie[] cookies = request.getCookies();
  if(cookies != null){
  for(int i=0;i<cookies.length;i++){
  Cookie c = cookies[i];
  String name = c.getName();
  String value = c.getValue();
  out.println(name + " " + URLDecoder.decode(value,"utf-8") + "<br/>");
  }
          其中URLDecoder.decode(value,"utf-8")方法将字符串value按照相
          应utf-8编码转换成相应的中文字符。
  5)生存时间
  cookie.setMaxAge(int seconds);
  注意:
  单位是秒servlet&jsp经典总结
  seconds > 0 : 浏览器会将cookie保存在硬盘上,超过指定的时间,会删除该cookie。
  seconds < 0 : 缺省值,浏览器会将cookie保存在内存里面,只有当浏览器关闭,才会删除该cookie。
  seconds = 0 : 删除cookie。
  比如,要删除一个名称为username的cookie:
  Cookie c = new Cookie("username","");
  c.setMaxAge(0);
  response.addCookie(c);
          上面删除cookie的过程包括先覆盖浏览器里面原有的名为
          username的cookie,然后再删除覆盖后的cookie。(之所以这样做,是因为对于浏览器中保存的cookie,服务器无法直接
          删除,只能发送一个同名的cookie去覆盖掉原有的cookie,然后通过设置此cookie的存活时间为0来删除覆盖后的cookie)
  6)路径问题
  浏览器在访问服务器的某个地址的时候,会自动比较该地址与cookie的地址(路径)是否匹配,如果匹配就会向服务器发送相应的
  cookie 。
  a,cookie的路径 cookie都会有一个默认的路径,其值等于创建该cookie的组件的路径。
  比如:  /web06_2/app01/addCookie.jsp创建了一个cookie,则
                该cookie的路径就是/web06_2/app01。
  b,匹配规则
  要访问的路径必须是cookie的路径或者其子路径。
  /web06_2/findCookie1.jsp   error!
  /web06_2/app01/findCookie2.jsp   ok
  /web06_2/app01/sub/findCookie3.jsp ok
  c,修改cookie的路径
  cookie.setPath(String path);
  一般情况下,总是会设置: cookie.setPath("/appname");这样,
       可以保证应用内部的某个组件所创建的cookie可以被该应用内部的所有组件都能访问到。
  7)cookie的限制
  a, cookie可以被用户禁止。
  b, cookie不安全。
  c, cookie只能够保存少量的数据(大约是4k)。
  d, cookie保存的cookie的个数也有限制(大约300个)
  e,cookie只能够保存字符串。
  (4)session技术
  1)session是什么?
  a,是一种服务器端的状态管理技术。
  b, 浏览器在访问服务器的时候,服务器(要调用getSession()方法)会创建一个session对象(该对象有一个id,称之为  sessionId,是唯一的),服务器默认情况下会将这个sessionId以set-cookie消息头的方式(cookie机制)发送给浏览  器,浏览器会将这些数据保存起来;当浏览器再次访问服务器的时候,将sessionId发送给服
    务器,服务器会依据sessionId找到对应的session对象。
  浏览器和服务器交互发送的数据包对比:
  第一次浏览器发送的请求数据包:
  GET /web06_2/some HTTP/1.1
  Host: localhost:8888
  User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
  Accept-Encoding: gzip, deflate
  Connection: keep-alive
  服务器发送的响应数据包:
  HTTP/1.1 200 OK
  Server: Apache-Coyote/1.1
  Set-Cookie: JSESSIONID=595689F43520D9BCFD7E748577C1C854; Path=/web06_2
  Content-Length: 0
  Date: Wed, 15 May 2013 08:18:19 GMT
  第二次浏览器发送的请求数据包:
  GET /web06_2/some HTTP/1.1
Host: localhost:8888
  User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
  Accept-Encoding: gzip, deflate
  Cookie: JSESSIONID=595689F43520D9BCFD7E748577C1C854
  Connection: keep-alive
  Cache-Control: max-age=0
  服务器发送的响应数据包:
  HTTP/1.1 200 OK
  Server: Apache-Coyote/1.1
  Content-Length: 0
  Date: Wed, 15 May 2013 08:19:47 GMT
  2)如何获得一个session对象?
  方式一:
  HttpSession s = request.getSession(boolean flag);
  当flag = true时:
  服务器先查看请求当中是否有sessionId, 如果没有,则创建一个session对象;如果有sessionId,服务器会依据sessionId查找对应的session对象,如果找到,则返回,找不到,创建一个新的session对象。
  当flag = false时:
  服务器先查看请求当中是否有sessionId, 如果没有,会返回null;如果有sessionId,服务器会依据sessionId查找对应的session对象,如果找到,则返回,找不到,返回null。
  方式二:
       HttpSession s = request.getSession();等价于request.getSession(true)。
  3) session的常用方法
                //获得sessionId
  String session.getId();
               //绑定数据
  session.setAttribute(String name,Object obj);
               //获取绑定数据
  Object session.getAttribute(String name);
  注意:如果绑订名称对应的值不存在,返回null。
  //移除绑定数据
  session.removeAttribute(String name);
  4)session的超时限制
  a,什么是session的超时限制?
  服务器会将空闲时间过长的session对象删除。
  大部分服务器默认的超时限制是30分钟,可以修改服务器的默认的超时限制。
  比如tomcat,可以修改 conf/web.xml
<session-config>
       <session-timeout>30</session-timeout>
  </session-config>
  也可以将以上配置放到某个应用的web.xml文件当中。(只对当前应用下的Servlet有效)
  //设置空闲时间
  b, session.setMaxInactiveInterval(int seconds);
  5)立即删除session
  session.invalidate();
  //区别于session.removeAttribute(Stirng name)
  6)案例:使用session验证:防止非登录用户通过地址栏输入地址直接访问受保护的页面。
              (也可以将所有jsp文件拷贝到WEB-INF目录下。因为WEB-INF目录中的内容不能直接访问,但能转发过来。)
  step1,在登录成功以后,在session对象上绑订数据。比如:
  servlet部分:session.setAttribute("user",user);
  step2,对于需要保护的资源(比如,main.jsp),添加验证代码,比如:
  jsp部分: 
       <% Object obj = session.getAttribute("user") ;
  if(obj == null){
  //用户没有登录成功,或者登录成功但session超时了
  //(session超时,服务器会自动删除session对象)
  response.sendRedirect("login.jsp");
  return;
  }
  %>
27、图片验证码实例:
<img src="checkCode" id="img1"/>
 <a href="javascript:;" onclick="document.getElementById('img1').src = 'checkCode?'+((new Date()).getTime()或者Math.random())">换一个?</a>
1.a href="javascript:;"语句可以让页面不会刷新,a href=""时页面会刷新;
  2.<a href="checkCode">时页面会刷新且页面上只剩下了验证码图片。
  3.src='checkCode?'+Math.random(),如果写成.src='checkCode'不加Math.random()对于某些浏览器的某些版本,如果使用get方式发请求,浏览器会先缓存之前访问的数据,如果访问的地址不变,不会向服务器重新发送请求。
  4.可以在连接中加入javascript代码,
  <a href="javascript:window.alert('Hello');">click me</a>
  点击链接时,页面会弹出警告框“Hello”。
  <a href="javascript:;" 
  onclick="location='modify.do?id=<%=item.getP().getId()%>&qty=' + document.getElementById
  ('p_<%=item.getP().getId()%>').value;">更改数量
  </a>
  等价于:
  <a href="javascript:location='modify.do?id=<%=item.getP().getId()%>&qty=' + document.getElementById
  ('p_<%=item.getP().getId()%>').value;">
  更改数量
  </a>
28、URL重写
1、用户如果禁止cookie,如何继续使用session?
  (1)url重写是什么?
  访问服务器端的某个地址时,要给这个地址添加上sessionId(也就是说,
  要重写url,形如http://localhost:9009/web08_1/some;jsessionid=F629638559B43254608A0D71D9839797)。
                如果用户进制了cookie,那么服务器发送过来的sessionId,浏览器便不会保存。发送sessionId除了之前用到的以cookie消息头的方式发送外,还可以通过请求行发送(在请求资源路径后面加上sessinid,)这样,即使用户禁止掉了cookie,也可实现session技术。
  (2)如何给地址添加sessionId?
  a, 链接地址,表单提交地址。
  response.encodeURL(String url);
  eg:在jsp页面中加入:
  <a href="<%=response.encodeURL("some")%>">Click me</a>
  点击链接后,发现浏览器的地址栏为:http://localhost:9009/web08_1/some;jsessionid=F629638559B43254608A0D71D9839797
 浏览器第一次访问服务器时,服务器使用response.encodeRedirectURL("some")方法将含有sessionId的页面发送给浏览器,浏览器端点击链接后,会在请求行发送GET /web08_1/some;jsessionid=F6A458CDAFBCD5BCF0A6BD83004CCA9C HTTP/1.1请求,这样就实现了不需要通过发送cookie消息头而向服务器发送SessionId的目标。
  b,重定向
  response.encodeRedirectURL(String url);
  在AServlet.java中加入:
  HttpSession session = request.getSession();
  session.setAttribute("name", "Tom");
  response.sendRedirect(response.encodeRedirectURL("B"));
  在BServlet.java中加入:
  HttpSession session = request.getSession();
  String name = (String) session.getAttribute("name");
  out.println(name);
  浏览器访问A,服务器收到请求后,向浏览器发送302状态码及Location: http://localhost:8888/web08_1/B;jsessionid=BB19FB4F9CBB70064502E4164AA63C74(Location消息头),服务器收到响应后立即向该地址发送请求,这样,即使浏览器禁掉了cookie,仍然可以向服务器发送sessionId。
     注:转发与URL重写没关系。
29、过滤器
(1)什么是过滤器?
  servlet规范当中定义的一种特殊的组件,可以拦截容器的调用过程并且进行处理。
  过滤器也是一个web组件
  过滤器相当于防火墙一样,浏览器在访问servlet时,要先访问过滤器,符合条件的才让其访问servlet,否则请求便被拒绝。
  过滤器在应用部署时filter对象便被创建,相当于servlet中XML添加了
  Load-on-starup配置一样(servlet便会在容器部署时创建)
  过滤器和Servlet共享request和response
  过滤器doFilter()---->其他doFilter()---->如果通过---->servlet的servlice
  过滤器可以进行session验证
  (2)如何写一个过滤器?
  step1,写一个java类,实现Filter接口。
  step2,在doFilter方法里,实现处理逻辑。
  step3,配置过滤器(web.xml)
  注:在web.xml中,放在上面的filter配置对应的过滤器会被优先执行
  (3)初始化参数
  step1,配置初始化参数
  <init-param>
  step2,使用FilterConfig提供的 String getInitParameter(String paraname);
  filter和servlet配置对比:
  <filter>
  <filter-name>filter2</filter-name>
  <filter-class>web.CommentFilter2</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>filter2</filter-name>
  <url-pattern>/comment</url-pattern>
  </filter-mapping>
  对比:
  <servlet>
  <servlet-name>CommentServlet</servlet-name>
  <servlet-class>web.CommentServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>CommentServlet</servlet-name>
  <url-pattern>/comment</url-pattern>
  </servlet-mapping>
  (4)过滤器的优先级
当有多个过滤器都满足过滤的条件,则按照<filter-mapping>的先后顺序来执行相应的过滤器。
  (5)过滤器的优点
  a, 可以将多个web组件相同的处理逻辑集中写在过滤器里面,方便代码的维护。
  b,可以实现代码的"可插拔性":增加或者减少某个模块,不会影响到整个程序的正常运行。
  (6)过滤器和servlet整个生命周期的执行顺序:
  Filter1's destroy...
  Filter2's destroy...
  Filter1's init...
  Filter2's init...
  Filter1's doFilter begin...
  Filter2's doFilter begin...
  CommentServlet's service start......
  CommentServlet's service end.
  Filter2's doFilter end.
  Filter1's doFilter end.
  Filter1's destroy...
  Filter2's destroy...
30、上传文件(扩展)
step1,设置表单的enctype="multipart/form-data",并且,表单的提交方式必须设置为post方式。
  step2,服务器端,不能够直接使用request.getParameter方法来获得参数值(服务器端用request.getParameter("name")读出的值为null),
          需要InputStream request.getInputStream(),通过分析InputStream来获得参数值。一般我们使用一些工具(比如apache提供的 
          commons-fileupload.jar)来分析。
30、监听器
(1)什么是监听器?
  servlet规范当中定义的一种特殊的组件,用来监听容器产生的事件并进行处理。
事件主要包括两大类:
  第一大类:生命周期相关的事件,指的是容器产生或者销毁、request,session,ServletContext对象(也叫ServletContext上
          下文)的产生或者销毁时产生的事件。
  第二大类:绑订相关的事件,指的是容器调用了
                  request,session,ServletContext对象的setAttribute,
         removeAttribute产生的事件。
  注:由于csdn篇幅宽度限制,如看不清楚图片,可以将将图片拖至单的网页查看。
  (2)如果写一个监听器
  step1,写一个java类,依据要监听的事件类型实现相应的监听器接口。
  step2,在监听器接口所声明的方法里面,编写相应的处理逻辑。
  step3,注册监听器。(web.xml)
  案例:统计在线人数。
  我们可以写一个监听器,实现HttpSessionListener接口。当容器创建了
       一个session或者销毁了一个session,都会产生相应的事件,我们只需要
  当监听器将人数加1或者减1即可。
0 0
原创粉丝点击