Servlet学习笔记(一)javaWeb应用基本

1 B/S concept
  B/S结构(Browser/Server结构)结构即浏览器和服务器结构。
  它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。

2 How to develop a WebApp.

1)WebApp的组成(符合JAVAEE规范).
2)例子.
firstWeb(webroot)
     /WEB-INF/web.xml
     /index.html
     /student.html
3) 部署到应用服务器.  
通过url访问:
http://localhost:8080/firstWeb/
or
http://127.0.0.1:8080/firstWeb/
思考:通过url访问index.html和直接用浏览器打开index.html文件效果一样么?
其过程有何差别?

3 HTTP introduction.

HTTP(Hyper Text Transfer Protocol)是超文本传输协议的缩写,
它用于传送WWW方式的数据。HTTP协议采用了请求/响应模型。

客户端向服务器发送一个请求,请求头包含请求的方法、URI、协议版本、

以及包含请求修饰符、客户信息和内容的类似于 MIME的消息结构。
request:
<!--start-->
GET /firstWeb/ HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
If-Modified-Since: Fri, 11 May 2007 03:46:02 GMT
If-None-Match: W/"216-1178855162000"
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: 127.0.0.1
Connection: Keep-Alive
<!--end-->


服务器以一个状态行作为响应,相应的内容包括消息协议的版本,

成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。
response:
<!--start-->
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
ETag: W/"216-1178955948000"
Last-Modified: Sat, 12 May 2007 07:45:48 GMT
Content-Type: text/html
Content-Length: 216
Date: Sat, 12 May 2007 07:45:56 GMT

<html>

<head>
<title>Welcome to SD0702 HomePage</title>
</head>
<body>
<center>
  <h1>
  <font color="blue">
  Welcome to SD0702...
    </font>
  </h1>
  </center>
</body>
</html>
<!--end-->
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求
(具体代码含义参看http代码对照表)

4 Servlet introduction.

1) 什么是Servlet
Servlet是用Java编写的Server端程序,它与协议和平台无关。是服务器端的组件。
只能在容器内运行,有自己的生命周期(当然可以给servlet一个main方法,
然后在客户端运行。这是servlet失去了它原有的意义,退化成了一个普通的Java类)。
a) 高效
CGI:进程(开销大,共享资源不方便)
Servlet:线程(开销小,共享资源方便)
b) 方便
Servlet提供了大量的实用工具例程,例如自动地解析和解码HTML表单数据、
读取和设置HTTP头、处理Cookie、跟踪会话状态等。
c) 功能强大
  在Servlet中,许多使用传统CGI程序很难完成的任务都可以轻松地完成。
  例如,Servlet能够直接和Web服务器交互,而普通的CGI程序不能。
  Servlet还能够在各个程序之间共享数据,使得数据库连接池之类的功能很容易实现。

d) 可移植性好

  Servlet用Java编写
Servlet: java class, 接收HttpRequest, 生成HttpResponse(生成动态页面)

2) 如何开发Servlet

a) Servlet class有特定的继承关系
interface: Servlet javax.servlet.*)
class: GenericServlet (javax.servlet.*)
class: HttpServlet (javax.servlet.http.*)
GenericServlet implements Servlet
HttpServlet extends GenericServlet

Http  POST,GET,...

HttpServlet doPost(),doGet(),...
GenericServlet service()

b) 实现特定的生命周期方法

init(), init(ServletConfig config)
service(HttpServletRequest request, HttpServletResponse response)
destroy()

c) 例子:

需要导入的包
import javax.servlet.*;
import javax.servlet.http.*;
public class ConcreteServlet extends HttpServlet{
init(){}
service(HttpServletRequest request, HttpServletResponse response){}
destroy(){}
}

HelloServlet.java

功能:
标题:Welcome to SD0702 HomePage
内容:居中显示 Hello our friends,today is (current date),
               Welcome to visit our HomePage.
firstWeb
     /WEB-INF/web.xml
     /WEB-INF/classes/HelloServlet.class
    
http://localhost:8080/firstWeb/hello


d)如何部署一个包含了Servlet的Web应用

I   建立特定的目录结构(Done)
II  编写Servlet源文件(Done)
III 编译Sevlet,并将class文件放到/WEB-INF/classes位置(Done)
IV  修改web.xml,增加Servlet的描述信息(remained step)
  <servlet>
    <servlet-name>helloServlet</servlet-name>     --->Servlet name
    <servlet-class>HelloServlet</servlet-class> --->Servlet class的位置
  </servlet>
  <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>     -->Servlet name(has been defined)
    <url-pattern>/hello</url-pattern>             -->Access the servlet thru  url pattern        
  </servlet-mapping>
  --->Servlet的映射名,Browser通过此名字来访问Servlet
V  将整个应用目录复制到%TOMCAT_HOME%/webapps/下,Tomcat自动激活应用。

3) 使用Servlet接收用户输入信息

a)通过表单(form)提交数据
<form action="login" method="POST" enctype="multipart/form-data">
action: 表单提交给服务器的哪个资源处理
method: 提交方式 "POST","GET"等
GET---->通过URL提交表单信息,由于受到URL长度的限制,只能传递大约1024字节。
<!--get方法提交表单-->
GET /guessWeb/guess?answer=abc&times=&luckNo= HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost:8090/guessWeb/
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: 127.0.0.1
Connection: Keep-Alive
<!--end-->

POST--->通过Http Body提交表单信息,传输的数据量大,可以达到2M。

<!--post方法提交表单-->
POST /guessWeb/guess HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://127.0.0.1:8090/guessWeb/index.html
Content-Type: application/x-www-form-urlencoded
Content-Length: 25

answer=abc&times=&luckNo=

<!--end-->

enctype: multipart/form-data 通常可用于上传文件


例:

//表单通过GET方法(默认)提交给login映射的资源处理
//login为在web.xml中配置的url-pattern或者是jsp文件等
<form action="login">
student name:<input type="text" name="name"/>
<br>
student age:<input type="text" name="age"/>
<br>
student nick:<input type="text" name="nick"/>
<br>
             <input type="text" name="nick"/>
<br>
<inut type="submit" value="submit"/>
</form>

b)如何在服务器端获得表单提供的数据


I request对象

HttpServletRequest对象由Web Container封装用户Http请求数据报而成,
可通过它获得所有跟用户请求数据报相关的信息。
getProtocol():String
getMethod():String
getRemoteHost():String
getRemotePort():int
getHeader():String

getParameter(String name):String

返回指定输入参数(名为name)的值
getParameterValues(String name):String[]
返回指定输入参数(名为name)的所有值
getParameterNames():Enumeration
返回请求对象中全部输入参数的名称
例:
String name=request.getParameter("name");
String age=request.getParameter("age");
String[] nicks=request.getParameter("nick");

II 解决Servlet中的中文乱码问题:

<1>静态中文信息乱码
response.setContentType("text/html; charset=gbk");
<2>中文输入乱码
a request.setCharacterEncoding("gbk");(解决post方法提交表单中文乱码问题)
b String name =new String(request.getParamete("name").getBytes("iso-8859-1"));
(b不推荐使用)
c 通过修改%TOMCAT%/conf/server.xml (解决get方法提交表单中文乱码问题)
加入 URIEncoding="gbk"
<3>静态html页面的中文化问题
<meta http-equiv="content-type" content="text/html; charset=gbk"> 

III 用户管理

功能:用户登录和用户注册
登录:username,password,role(select)
注册:姓名,密码,婚否(radio),电话(用户最多可以有填写3个电话号码,无需验证合法性)
loginWeb
      /WEB-INF/web.xml
      /WEB-INF/classes/com.LoginServlet.class
      /WEB-INF/classes/com.RegisterServlet.class
      /login.html
      /register.html


1 IDE+Tomcat Server.
2 Servlet Life cycle.
3 ServletConfig&ServletContext.
4 SingleThreadModel(interface).
5 RequestDispatcher.
6 exercise.
*****************************************************************

1 IDE+Tomcat Server.

熟悉Myeclipse环境下配置Tomcat服务器以及部署和运行Web App。

tomcat

   /bin  可执行文件
   /conf 配置文件
   /logs 日志文件
   /temp 临时文件
   /work 工作目录
   /server 服务器包
   /common 公用包
   /shared 共享包
   /webapps WebApp发布目录

2 Servlet Life cycle.

1) ClassLoader载入Servlet类并实例化
2) 调用init()
3) 调用service()<doGet(),doPost(),etc>处理客户端请求
4) 调用destroy()

  <servlet>
    <servlet-name>s1</servlet-name>
    <servlet-class>com.S1Servlet</servlet-class>
    <load-on-startup>3</load-on-startup>
  </servlet>
<servlet>
    <servlet-name>s2</servlet-name>
    <servlet-class>com.S2Servlet</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
load-on-startup: 表示Servlet在部署时通过ClassLoader直接载入并初始化,
数值越低(从1开始计数),载入的优先级越高。否则,用户第一次访问的时候才实例化Servlet。
值相同,一般按在web.xml文件中的出现的顺序执行。

init()--->对Servlet将要使用的资源作初始化,如读入配置文件信息等(只执行一次)

init(ServletConfig config)
service()----->为客户端提供服务,能够被多客户端多次调用(每个请求都要执行一次)
destroy()--->在Web Container停止Web App或WebApp被停止/reload时调用,
通常完成一些资源释放,停止后台程序等工作。释放或销毁一些非内存资源。
(只执行一次)
例子:
观察三个生命周期方法何时执行
lifecycleWeb
       /WEB-INF/web.xml
       /WEB-INF/classes/com/LifeCycleServlet.class
      
部署和实例化一个Servlet的情况有两种
1)web.xml中没有load-on-startup标记
a 在用户第一次请求的时候tomcat服务器加载servlet类,
并且实例化一个对象,接着执行init方法。最后执行service方法为第一次请求服务。
b 用户的第二次以及其后的所有请求,servlet对象直接调用service方法为其服务。
2)web.xml中有load-on-startup标记
a 在webapp被启动的时候,tomcat服务器加载servlet类,并且实例化一个对象,
接口执行init方法。
b 用户任何请求,servlet对象都调用service方法为其服务。

destroy方法什么时候执行?:关闭webapp的时候(只执行一次)。


3 ServletConfig&ServletContext.


ServletConfig:从一个servlet被实例化后,对任何客户端在任何时候访问有效,

但仅对本servlet有效,一个servlet的ServletConfig对象不能被另一个servlet访问。

ServletContext:对同一个WebApp的任何servlet,任何人在任何时间都有效,

这才是真正全局的对象。

  <servlet>
    <servlet-name>lifecycleServlet</servlet-name>
    <servlet-class>com.LifeCycleServlet</servlet-class>
    <init-param>
      <param-name>email</param-name>
      <param-value>narci.ltc@gmail.com</param-value>
    </init-param>
    <load-on-startup>5</load-on-startup>
  </servlet>

String email=config.getInitParameter("email");


ServletConfig---->对应某个具体的Servlet,主要用来读取web.xml中配置的

Servlet初始信息,不能被其它Servlet共享

如何获得ServletConfig对象

1)init(ServletConfig config)
2)this.getServletConfig()


ServletContext---->对应整个Web Application运行环境,可以用来读取web.xml

中配置的应用初始信息,写日志,共享数据等,ServletContext被所有Servlet共享

如何获得ServletContext对象

1)config.getServletContext()
2)this.getServletContext()

利用ServletContext写日志

log(String info)

例子:

如何获取web.xml配置文件中的context param和init param。
比较它们的作用域范围有什么不同。学会使用context对象写日志。
classNo:context param
email:intit param
phone:init param
configWeb
    /WEB-INF/web.xml
    /WEB-INF/classes/com/ConfigServlet.class
    /WEB-INF/classes/com/ContextServlet.class   


4 SingleThreadModel(interface).

该接口已经废弃(deprecated)
请不要实现 SingleThreadModel 接口。
这种实践将导致 Web 容器创建多个 servlet 实例;
即为每个用户创建一个实例。对于任何大小的应用程序,
这种实践都将导致严重的性能问题。
request  <--->servlet实例(对象) 一一对应的

正常servlet:

n个request <--->一个servlet实例(对象)
深入理解:servlet是单实例多线程
servlet对象只有一个

public class SomeServlet extends HttpServlet implements SingleThreadModel{}


代替SingleThreadModel的方案:

Servlet是单实例,多线程:使用synchronized块解决同步问题。
提示:在Servlet中尽量少使用成员变量,一旦使用必须自己维护其并发问题。

实际应用中,service()方法中使用synchronized来解决并发问题,synchronized

块作用域应该越小越好,并且通常只在对实例变量作修改时使用。
同步控制的粒度要尽量小。

建议:

1)尽量不要使用成员变量。一旦使用,必须自己控制并发问题。
2)同步块应该尽可能小。

例子:


count:int 访问计数

name:String 用户名称
singleWeb
    /WEB-INF/web.xml
    /WEB-INF/classes/com/VisitorServlet.class  (SingleThreadModel)
    /WEB-INF/classes/com/Visitor2Servlet.class   
注意:对成员变量的访问必须注意同步操作


5 RequestDispatcher.


RequestDispatcher---->实现Servlet之间的请求传递(页面跳转)

forward(ServletRequest, ServletResponse)  //跳转到其他资源
include(ServletRequest, ServletResponse)  //包含其他资源

如何获得RequestDispatcher对象

1) request.getRequestDispatcher(String page)   ---->相对路径
2) ServletContext.getRequestDispather(String page)  ---->绝对路径

例子:

用户登录,成功跳转到target servlet,失败则跳转到fail.html
target servlet包含版权声明页面(copyright.html)。
login2Web
    /WEB-INF/web.xml
    /WEB-INF/classes/com/LoginServlet.class
    /WEB-INF/classes/com/TargetServlet.class 
    /login.html
    /fail.html
    /copyright.html
   
6 exercise.
改写用户登录WebApp,要求通过读取web.xml来决定用户登录成功和失败后分别跳转到的那个
资源。不管用户登录成功还是失败,必须写日志,记录下用户名、密码、角色以及登录时间。
login3Web
    /WEB-INF/web.xml
    /WEB-INF/classes/com/LoginServlet.class
    /WEB-INF/classes/com/TargetServlet.class    (登录成功,需要包含版权信息)
    /login.html
    /fail.html
    /copyright.html
   
练习:(ServletConfig,ServletContext,RequestDispatcher)
一个网上书店系统,用户分5个等级,对网上书店上所有商品,
一星会员可以享受 95%的优惠。
二星会员可以享受 90%的优惠。
三星会员可以享受 85%的优惠。
四星会员可以享受 80%的优惠。
五星会员可以享受 75%的优惠。
其中外文书籍对任何用户都有额外的95%的优惠,计算机类书籍也有额外的85%的优惠
bookWeb
    /WEB-INF/web.xml
    /WEB-INF/classes/com/ForeignBookServlet.class
    /WEB-INF/classes/com/ComputerBookServlet.class 
     /WEB-INF/classes/com/OtherBookServlet.class   
    /foreign.html
    /computer.html
    /other.html

用户输入要购买的图书以及价格等信息提交后,将这打折后的价格和其他信息返回显示

给用户。每次购买行为要求写日志。
日志格式为:用户名 购买的图书名称 原价 打折后的价格 购买时间

ServletConfig:

1)this.getServletConfig()     任何方法中都可以调用
2)config.getServletConfig()   在init(ServletConfig config)方法可以调用

ServletContext:

1)this.getServletContext()    任何方法中都可以调用
2)config.getServletContext()  在init(ServletConfig config)方法可以调用

public MyServlet extends HttpServlet{


ServletConfig config=getServletConfig();//可不可以? null

//不可以!
//原因:成员变量的初始化次序优先于构造方法。
//而我们ServletConfig对象是在调用了init方法之后才初始化的。
//init的执行肯定是在执行了构造方法之后才执行。

ServletContext context=getServletContext();//null?

//?

public void init(){}

...

}


1 Access Resources.
2 Connection Pool.
3 DataSource.
4 DAO.
5 exercise.
**************************************************************
1 Access Resources.
1)要在WebApp中访问数据库,必须先将其JDBC Driver复制至%TomcatHome%/common/lib下。
2)直接创建数据源方式获得数据库连接
重写用户登录模块
create database test;

use test;

//创建用户表
create table t_user(
t_id int auto_increment primary key,
t_name varchar(20),
t_pass varchar(128),
t_role varchar(20)
)

insert into t_user(t_name,t_pass,t_role) values ('Alice','Alice','admin');

insert into t_user(t_name,t_pass,t_role) values ('Maxwell','Maxwell','guest');
insert into t_user(t_name,t_pass,t_role) values ('test','test','admin');
...

login3Web

      /WEB-INF/web.xml
      /...
     
3)通过配置连接池获得数据库连接。
a 在WebApp需要配置web.xml文件
资源引用
web.xml需要作如下配置:
  <resource-ref>
    <res-ref-name>jdbc/test</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>                   可选值:Application
    <res-sharing-scope>Shareable</res-sharing-scope> 可选值:Unshareable
  </resource-ref>

通过JNDI访问数据源

import javax.naming.*;
Context ic=new InitialContext();
DataSource ds=(DataSource)ic.lookup("java:comp/env/jdbc/test");
//ds=is.lookup("jdbc/test");
Connection con=ds.getConnection();//代替DriverManager.getConnection();

web.xml中配置环境变量(可以通过JNDI访问)

    <env-entry>
        <description>my email</description>
        <env-entry-name>email</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>narci.ltc@gmail.com</env-entry-value>
    </env-entry>
        <env-entry>
        <description>Is Trainer</description>
        <env-entry-name>isTrainer</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>true</env-entry-value>
    </env-entry>
b 在应用服务器要配置连接池。
Tomcat:server.xml
...
         <Context
            path="/login3Web">
          <Resource
            name="jdbc/test"
            type="javax.sql.DataSource"
            username="narci"           
            password="11"
            driverClassName="com.mysql.jdbc.Driver"
            maxIdle="10"
            maxWait="5000"
            validationQuery="select * from student"
            url="jdbc:mysql://localhost/test"
            maxActive="10"/>
        </Context>
...
    * maxActive
    - 同一时刻可以自数据库连接池中被分配的最大活动实例数。
    * maxIdle
    - 同一时刻数据库连接池中处于非活动状态的最大连接数。
    * maxWait
    - 当连接池中没有可用连接时,连接池在抛出异常前将等待的最大时间,单位毫秒。
   
   
2 Web App访问数据库
1)从结构上优化()
DAO: Data Access Object
设计DAO接口可进一步抽象持久化逻辑
VO:  Value Object:其实就是标准的Java Bean,只是对应数据库中的一张表。
Java Bean的要求
a 空参数的构造器
c 对属性的标准访问方法setter、getter方法
String name;
public void setName(String name){}
public String getName(){}
3、远程传递时需要实现java.io.Serializable

2)从性能上作优化

使用连接池,减少因物理连接带来的系统开销,提升数据库访问性能



关键字: cookie session 1 Trace state:Cookie.
2 Trace state:Session.
3 exercise.
************************************************************

1 Trace state:Cookie.


Cookie:客户端保存状态的机制,通过cookie文件来记录信息

Cookie编程:
从request中获得cookie:Cookie[] request.getCookies()
创建一个Cookie:        new Cookie(String name,String value)
获得cookie中的信息:    Cookie.getValue() getName()
设置cookie的有效时间: Cookie.setMaxAge(int seconds)//单位秒
0:不支持cookie
负数:会话cookie,即不写文件
把cookie写回客户端:    response.addCookie(Cookie cookie)
例子:
用户访问计数(CookieVisitorServlet):cookie版本
第100名访问者奖励一个小礼品
C:/Documents and Settings/%user%/Cookies

创建TwoCookieServlet

要求:创建两个Cookie写回客户端,并设置有效时间10s,观察cookie文件中的内容及
TCP Monitor监视到的HTTP数据报内容
Cookie cookie1=new Cookie("userName","Tommy");
Cookie cookie2=new Cookie("className","SD0702");

HTTP response的内容

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: userName=Tommy; Expires=Fri, 18-May-2007 03:01:10 GMT
Set-Cookie: classNo=SD0702; Expires=Fri, 18-May-2007 03:01:10 GMT
Content-Type: text/html;charset=gbk
Transfer-Encoding: chunked
Date: Fri, 18 May 2007 03:01:00 GMT

7a

<HTML>
  <HEAD><TITLE>Two Cookie Servlet</TITLE></HEAD>
  <BODY>
<h1 align=center>两个小甜饼</h1>
  </BODY>
</HTML>

0

在cookie没有超时的情况下,HTTP request会带上cookie的信息
GET /cookieWeb/two HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: 192.168.2.53:8082
Connection: Keep-Alive
Cookie: userName=Tommy; classNo=SD0702


例子:显示所有的Cookie

ListCookieServlet

三种类型的cookie

寿命
setMaxAge:0 不支持Cookie
          负数,会话Cookie,保持在浏览器,不写文件
          整数,普通Cookie,写文件
注意:Cookie需要客户端浏览器的支持,
如果浏览器禁用Cookie的话,我们的所有Cookie就无效

2 Trace state:Session.

Session:服务器端保存状态的机制,通过HttpSession对象来记录信息
Session编程:
获得Session: request.getSession()   getSession(boolean b)
request.getSession()与getSession(true)等价:
没有session对象时候自动创建session对象
getSession(false):没有session对象时候返回null,不会自动创建session对象
Session存信息:  HttpSession.setAttribute(String name,Object o)
Session取信息:  Object HttpSession.getAttribute()
设置Session有效时间:(单位秒)
HttpSession.setMaxInactiveInterval(int interval)
设置session无效的时间,负数表示永不过时。
手工销毁Session:  HttpSession.invalidate()
判断Session是否新建:    boolean HttpSession.isNew()
获得SessionID:          HttpSession.getId()

用户访问计数(SessionVisitorServlet):session版本

第100名访问者奖励一个小礼品

客户端维护SessionID:

1)通过Cookie来维护SessionID
Web Server生成Session对象后,每次作response时,会自动把SessionID发回到客户端,
客户端把SessionID记入会话Cookie,下次请求时自动带上
服务器第一次的相应会生成一个session id,发送到客户端
HTTP response:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=46C8177FB3EAC6F7FD868E6FA147E9CD; Path=/sessionWeb
Content-Type: text/html;charset=gbk
Transfer-Encoding: chunked
Date: Fri, 18 May 2007 03:54:31 GMT

+++++++++++++++++++++++++++++++++++++++++++++++++++++

下一次客户端的请求会带上以cookie的形式session id
HTTP request:
GET /sessionWeb/visitor HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: 192.168.2.53:8082
Connection: Keep-Alive
Cookie: JSESSIONID=46C8177FB3EAC6F7FD868E6FA147E9CD


2)重写URL来维护SessionID(当客户端阻止cookie时,可采用这种方式维护sessionid)

把sessionID加到请求的URL中
out.println("<a href="+response.encodeURL("visitor")+">access again</a>");
http://192.168.2.53:8082/sessionWeb/visitor;jsessionid=1CA21297D00524960931F00F69FF7A4A


销毁Session:

1)session.invalidate()
2)
a session.setMaxInactiveInterval(int interval)(a优先级高于b方法) 1800
也可通过web.xml来设最长不激活时间:
b <session-config>
    <session-timeout>30</session-timeout>
  </session-config>
default value: 60min
3)Web Server crash(服务器定制,webapp被停止,session都会被销毁。


3

维护状态的方式
1)Cookie
2)Session
3)隐藏表单域
<input type="hidden" name="times" value=""/>
4)URL重写
http://localhost:8080/visitorWeb/visitor?name=Alice&age=23


1 Filter.
2 Listener.
3 exercise.
*************************************************************
过滤器

1.  什么是过滤器?

答:与Servlet相似,过滤器是一些Web应用程序组件,可以绑定到一个Web应用程序档案中。但是与其他Web应用程序组件不同的是,过滤 器是“链”在容器的处理过程中的。这就意味着它们会在servlet处理器之前访问一个进入的请求,并且在外发的响应信息返回到客户前访问这些响应信息。 这种访问使得过滤器可以检查并修改请求和响应的内容。

2.  过滤器可以用于:

答:1) 为一个Web应用程序的新功能建立原型(可被添加到Web应用程序中或者从Web应用程序中删除而不需重写基层应用程序代码);
    2) 向过去的代码中添加新功能。

3.  过滤器放在容器结构什么位置?

答:过滤器放在Web资源之前,可以在请求抵达它所应用的Web资源(可以是一个servlet、一个JSP页面,甚至是一个HTML页面这样的 静态内容)之前截获进入的请求,并且在它返回到客户之前截获输出请求。

4.  过滤器的存活周期

答:过滤器有四个阶段(与servlet类似):
    1) 实例化;
    2) 初始化(调用init()方法);
    3) 过滤(调用doFilter()方法);
    4) 销毁(调用destroy()方法);

5. 过滤器类和接口

答:所有的过滤器都必须实现javax.servlet.Filter接口:
    1) 容器调用init()方法初始化过滤器实例:
       public void init(FilterConfig config) throws ServletException
    2) doFilter()方法包含过滤器逻辑:
       public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
    3) destroy()方法由容器在销毁过滤器实例之前调用:
       public void destroy();
    4) FilterChain的doFilter()方法之后的代码构成了后期处理过滤器调用。

6.  配置过滤器

答:使用<filter>和<filter-mapping>元素来配置:
    <filter>
       <filter-name>XSLTFilter</filter-name>                   //过滤器名
       <filter-class>filters.SmartXSLFilter</filter-class>     //具体过滤器类
       <init-param>                                            //初始化参数
          <param-name>xsltfile</param-name>
          <param-value>/xsl/stockquotes.xsl</param-value>
       </init-param>
    </filter>
    <filter-mapping>                        //将过滤器应用于Web应用程序中的每个Web资源
       <filter-name>Logger</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

如何开发Filter:

1)implement javax.servlet.Filter
2)生命周期方法
init()
doFilter()
destroy()
3)filter在webapp启动时候被实例化,容器会执行其init()方法。
4)filter request, response
public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) {
    try {
//filter request
      request.setCharacterEncoding("gbk");
  //检查filter是不是同一个实例     
      System.out.println("process request:"+this);

      filterChain.doFilter(request, response);
    
//filter response
      System.out.println("process response:"+this);
    }
    catch (ServletException sx) {
      filterConfig.getServletContext().log(sx.getMessage());
    }
    catch (IOException iox) {
      filterConfig.getServletContext().log(iox.getMessage());
    }
  }
5)deploy filter in web.xml
  <filter>
    <filter-name>encodingfilter</filter-name>
    <filter-class>filter.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>encodingfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

6)多个filter的执行次序

根据 <filter-mapping> 的先后次序决定
web.xml
  <filter-mapping>
    <filter-name>encodefilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>visitorfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
把所有请求客户端的IP地址和请求的时间写入日志文件。
用户投票
例子:
惰性认证
保护某些页面
if (role == null || !role.equals("admin")) {

      try {
        res.sendRedirect("../login.html");
      }
      catch (IOException ex) {
      }
    }
    try {
      filterChain.doFilter(request, response);
    }
    catch (ServletException sx) {
      filterConfig.getServletContext().log(sx.getMessage());
    }
    catch (IOException iox) {
      filterConfig.getServletContext().log(iox.getMessage());
    }

2 Listener.


Listener:

--->ServletContext,HttpSession(2.3)   ServletRequest(2.4)

1)implements ServletContextListener.

2)override listener method.
3)在webapp启动是被实例化。
4)web.xml
  <listener>
      <listener-class>com.MyListener</listener-class>
  </listener>

例子:

Web应用程序生命周期事件及监听器(Servlet V2.3版本以后新增功能)

1. 什么是事件监听器?

答:1) 支持ServletContext、HttpSession(since v2.3)及ServletRequest(since v2.4)中状态改变的事件通知;
    2) 实现了一个或多个servlet事件监听器接口的类型;
    3) 控制ServletContext、HttpSession(since v2.3)及ServletRequest(since v2.4)中的生命周期;

2. Servlet Context事件监听器

答:1) 对于应用程序而言在JVM层别管理资源或保存状态
    2) 有二种类型的事件监听器:
       a. ServletContextListener(以下是该监听器的方法)
          contextDestroyed(ServletContextEvent sce)
          contextInitialized(ServletContextEvent sce)
       b. ServletContextAttributeListener(以下是该监听器的方法)
          attributeAdded(ServletContextAttributeEvent scab)
          attributeRemoved(ServletContextAttributeEvent scab)
          attributeReplaced(ServletContextAttributeEvent scab)

3. HTTP Session事件监听器

答:1) 管理从同一个客户端或用户向一个Web应用程序发出的一系列请求相关的状态或资源;
    2) 有二种类型的事件监听器:
       a. HttpSessionListener(以下是该监听器的方法)
          sessionCreated(HttpSessionEvent se)
          sessionDestroyed(HttpSessionEvent se)
       b. HttpSessionAttributeListener(以下是该监听器的方法)
          attributeAdded(HttpSessionBindingEvent se)
          attributeRemoved(HttpSessionBindingEvent se)
          attributeReplaced(HttpSessionBindingEvent se)

4. Servlet Requst事件监听器

答:1) 管理整个request生命周期的状态
    2) 有二种类型的事件监听器
       a. ServletRequestListener(以下是该监听器的方法)
          requestDestroyed(ServletRequestEvent sre)
          requestInitialized(ServletRequestEvent sre)
       b. ServletRequestAttributeListener(以下是该监听器的方法)
          attributeAdded(ServletRequestAttributeEvent srae)
          attributeRemoved(ServletRequestAttributeEvent srae)
          attributeReplaced(ServletRequestAttributeEvent srae)

5. 监听器类的规定

答:1) 必须在部署描述符中配置实现类;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值