servlet的运行过程

1、什么是Servlet?

sun公司制订的一种用于扩展web服务器功能的

组件规范。

(1)扩展web服务器功能:

早期的web服务器(比如apache web server,

iis)只能够处理静态资源的请求(需要事先将页面

文件写好 ,并存放到服务器特定的目录下面),

不能够处理动态资源的请求(即依据请求参数,通过

计算,生成一个新的页面)。

扩展方式,早期是使用CGI程序来扩展:

CGI(common gateway interface),CGI是一个规范,

约定了web服务器与CGI程序(使用perl,c等语言开发的

,并且符合CGI规范的程序)相互调用的过程。

CGI程序有三个问题:

a,开发比较复杂(需要开发人员去解析请求参数)

b,可移值性比较差(c,perl等语言依赖于平台)

c,性能问题(一个请求,会启动一个进程,进程的开销

比较大)

现在,可以使用Servlet来扩展。

(2)组件规范

a,什么是组件?

是符合规范的,并且具有部分功能的软件模块,组件

必须部署到容器里面才能运行。

b,什么是容器?

是符合规范,并且提供组件的运行环境、管理组件的

生命周期的一个程序。

2、如何开发一个Servlet?

step1, 写一个java类,实现Servlet接口或者继承

HttpServlet抽象类。

step2,编译。

step3,打包。

建立一个如下的目录结构:

appname(应用名)

WEB-INF

classes(放 .class文件)

lib(可选,放一些.jar文件)

web.xml(描述文件)

step4,部署。

将step3生成的整个目录结构或者使用jar命令将整个

目录结构压缩生成的.war文件拷贝到servlet容器

相应的目录下面。

step5,启动servlet容器,访问:

在浏览器地址栏输入:

http://ip:port/appname/servlet-url

3、tomcat的安装与使用

(1)安装

可以从www.apache.org下载tomcat的安装文件,或者

将/opt/apache-tomcat.zip文件解压到/home/soft01。

(2)启动

cd /home/soft01/apache-tomcat/bin

sh startup.sh  (window: startup)

启动有问题的同学:  sh  catalina.sh run

在浏览器地址栏输入:  http://localhost:8080

(3)关闭

cd /home/soft01/apache-tomcat/bin

sh shutdown.sh

(4)各个目录的作用:

bin:  可执行文件,比如启动和关闭服务器的命令文件。

common: 存放共享的文件。

conf: 服务器的配置文件。

webapps: 部署目录。

work:服务器运行时产生的一些临时文件。

4、使用myeclipse来开发Servlet?

step1, 启动myeclipse,配置myeclipse,使myeclipse

可以启动和关闭tomcat。

step2, 创建一个web工程。

5、servlet是如何运行的?

在浏览器地址栏输入 http://localhost:8080/web01

/sayHello

step1,浏览器依据ip,port建立与服务器之间的连接。

step2,浏览器将请求数据(请求资源路径,请求参数)按照http协议

打包(http请求数据包),发送给服务器。

step3,服务器解析请求数据包,将请求数据封装到request

对象里面(封装的目的,是为了方便servlet获得请求数据包中的

数据,如果没有request对象,就需要在servlet类里面编写

解析请求数据包的代码)。另外,服务器还会创建一个对象response

对象(用来存放servlet处理的结果)。

step4,服务器依据请求资源路径(web01/sayHello)找到对应的

servlet的配置,创建servlet对象。

step5,服务器会调用servlet对象的service方法(在调用该方法时,

会将事先创建好的request,response对象作为参数传递进来)。

可以在service方法里面,通过request获得请求数据,也可以

将处理之后的结果存放到response对象上。

step6,服务器从response对象上取出处理结果,生成响应数据包。

发送给浏览器。

step7,浏览器解析响应数据包,取出处理结果,生成相应的界面。

1、http协议(了解)

(1)什么是http协议?

超文本传输控制协议(w3c定义),它定义了浏览器与

web服务器之间数据传输的过程以及数据的格式。

(2)数据传输的过程:

step1, 浏览器建立与服务器之间的连接。

step2,浏览器打包,发送请求。

step3,服务器处理请求之后,将处理结果打包,发送响应。

step4,服务器立即关闭连接。

特点:一次请求,一次连接。

优势:“效率高”,服务器可以在一段时间内,尽可能为更多

的客户服务。

(3)数据的格式

a,请求数据包

请求行: 请求方式 请求资源路径 协议类型及版本

若干消息头:

消息头是一般情况下是由浏览器或者服务器自动生成的

,在特定情况下,也可以通过编程的方式来生成一些

消息头。比如,浏览器在向服务器发请求时,会生成

user-agent消息头,告诉服务器浏览器的类型和版本。

实体内容:

只有当请求方式是post方式时,请求参数才会放到

实体内容里面。当请求方式是get时,请求参数会添加

到请求资源路径里面。

b,响应数据包

状态行: 协议的类型与版本 状态码 描述

状态码:一个三位数字,表示不同含义,状态码

由w3c定义。

404: 依据请求资源路径,找不到对应的资源。

200: 服务器处理正常

500: 系统错误,一般是程序在执行过程当中,发生了

异常。

405:找不到service方法。

若干消息头:

服务器也可以发送一些消息头给浏览器,比如,发送

content-type消息头,告诉浏览器服务器返回的数据的

类型。

实体内容:

处理结果。

2、get与post请求

(1)哪一些情况下,浏览器以get方式向服务器发请求:

a,在浏览器地址栏输入某个地址

b,点击链接

c,表单默认提交方式

(2)哪一些情况下,浏览器以post方式向服务器发请求:

a,设置表单的method="post"。

(3)get与post方式的区别:

get方式会将请求参数添加到请求资源路径的后面,

因为请求行能够存放的数据量有限(2k左右),所以get方式

只能提交少量的数据给服务器。

get方式会将请求参数显示在浏览器地址栏,不安全。

post方式会将请求参数添加到实体内容里面,理伦上讲,

提供的数量大小没有限制。另外,不会将请求参数显示在

浏览器地址栏,相对安全。要注意,http协议不会对数据

做加密处理。

3、常见的错误及处理方式

(1)404:

错误原因: 请求资源路径写错。

解决方式:检查请求资源路径,

按照http://ip:port/appname/servlet-url标准检查。

(2)500:

错误原因:程序运行出错。

解决方式:检查程序代码。比如检查程序代码是否

添加了数据验证代码(比如,程序没有添加数据验证代码,

用户就有可能提交一些非法的参数值)。

此外,还要检查和代码相关的配置文件是否正确。

另外,程序如果在运行过程当中,依赖一些其它的资源,

比如要访问数据库,那么要看数据库是否正常运行。

(3)405

错误原因:服务器找不到service方法。

解决方式:检查service方法的签名。

4,处理中文

(1)servlet如果要输出中文

解决方式:

response.

setContentType("text/html;charset=支持中文的编码");

java语言在内存里面,保存的所有字符采用unicode编码格式。

当将内存当中的字符输出到硬盘上的文件时,

需要做编码(unicode -- > 某种本地编码格式,比如gbk,utf-8)

反过来,将文件里的内容读取到内存,

需要解码(某种本地编码格式,比如gbk,utf-8 --> unicode)。

(2)表单当中有中文参数值,如何处理?

出现乱码问题的原因:

当点击表单提交按钮时,浏览器会对表单中的中文参数值

按照打开表单所在的页面时的编码格式进行编码。

服务器在默认情况下,会使用iso-8859-1这种编码格式

进行解码。

解决方式:

方式一:request.setCharacterEncoding("utf-8");

方式二:  str = new String(str.getBytes("iso-8859-1"),"utf-8");

注意:方式一只能处理post请求。

练习:

写一个add_emp.html,该html文件提供一个表单,包含

员工姓名,薪水,年龄三个表单域。当点击提交,提交给

AddEmpServlet来处理,该Servlet读取三个请求参数值,

然后输出员工的所有信息。

5、使用mysql数据库

(1)登录

mysql -uroot;

(2)显示所有的数据库实例

show databases;

(3)创建一个新的数据库实例(并且设置缺省的字符集是utf8)

create database jd1208db default character set utf8;

(4)使用某个数据库实例

use jd1208db;

(5)查看当前数据库有哪些表

show tables;

(6)建表

create table  t_emp(

id  int primary key auto_increment,

name varchar(32),

salary double,

age int

);

auto_increment: 自增长列,每当插入一条新的记录,

数据库会自动生成一个值。

insert into t_emp(name,salary,age) values(‘zs‘,10000,24);

insert into t_emp(name,salary,age) values(‘ww‘,20000,34);

6、在Servlet类里面,使用jdbc访问数据库。

step1,将jdbc驱动程序所对应的.jar文件拷贝到WEB-INF\lib

下。

step2,在servlet类里面,使用jdbc访问数据库,要注意

异常的处理。

练习:

写一个ListEmpServlet,该servlet查询t_emp表,将所有

记录查询出来,然后生成一个表格显示给用户。

http://ip:port/web02/list

1、重定向

(1)什么是重定向?

服务器向浏览器发送一个状态码302及一个消息头

Location(包含有一个地址,该地址称为重定向地址);

浏览器会立即向重定向地址发送请求。

(2)如何重定向?

//url:重定向的地址,可以是任意的一个地址

response.sendRedirect(String url);

(3)编程需要注意的问题

a,在重定向之前,服务器会先清空response中

存放的数据。

b,在重定向之前,不能够调用out.flush(),out.close()。

(4)特点

a,重定向的地址是任意的。

b,重定向之后,浏览器的地址会变成重定向地址。

2、dao(data access object)

(1)dao是什么?

封装了数据访问逻辑的模块。

(2)如何写一个dao?

step1, 实体类

用来封装记录,方便程序操作。

比如,在数据库里面有一张表 t_emp,可以设计一个

实体类Employee。

step2, dao接口

比如,为了方便对t_emp表进行操作,可以设计一个

接口EmployeeDAO

//接口设计,不应该涉及具体的实现技术。

public List<Employee> findAll() throws Exception;

step3,实现dao接口

比如,写一个EmployeeDAOImpl类

1、dao

(1)dao是什么?

封装了数据访问逻辑的模块。

(2)如何写一个dao?

step1, 实体类

用来封装记录,方便程序操作。

比如,在数据库里面有一张表 t_emp,可以设计一个

实体类Employee。

step2, dao接口

比如,为了方便对t_emp表进行操作,可以设计一个

接口EmployeeDAO

//接口设计,不应该涉及具体的实现技术。

public List<Employee> findAll() throws Exception;

step3,实现dao接口

比如,写一个EmployeeDAOImpl类

step4, 工厂类

能不能做到dao的实现发生了改变,比如从jdbc

的实现改为hibernate的实现,不影响调用者?

可以通过引入"工厂设计模式"来解决:

什么是“工厂”,工厂负责为调用者提供一个符合接口

要求的对象,调用者不用了解对象的创建细节。这样

做的好处是, 当对象的创建细节发生了改变,不会

影响到调用者。

2、servlet容器如何处理请求资源路径?

比如,在浏览器地址栏输入http://ip:port/web04/abc.html

其中"/web04/abc.html"称为请求资源路径,会放到请求数据包

里面,发送给servlet容器(web服务器)。

step1,依据应用名("/web04")找到应用所在的文件夹,然后

找到web.xml文件,去匹配"/abc.html":

step2:匹配过程:

精确匹配:

通配符匹配:使用"*"来代替任意的字符。

比如:

<url-pattern>/*</url-pattern>

<url-pattern>/abc/*</url-pattern>

后缀匹配:使用"*."加上后缀。

比如:

<url-pattern>*.do</url-pattern>

匹配所有以.do结尾的请求。

step3:如果没有匹配成功,此时会认为是一个文件,

去查找该文件,如果找到,返回;找不到,返回404。

3、让一个servlet处理多种不同请求。

step1, 使用后缀匹配模式。

step2, 在servlet的service方法里面,分析

请求资源路径。

4、servlet的生命周期

(1)生命周期的含义?

servlet容器创建servlet对象,分配资源进行初始化操作,

然后调用相应方法处理请求以及销毁servlet对象的过程。

(2)生命周期包括四个阶段:

a,实例化(创建servlet对象)

a1,实例化在什么时候进行?

第一种情况:当请求到达容器时,容器查找对应的

servlet对象是否已经存在,如果不存在,则创建;

如果已经存在,则不再创建。

第二种情况:容器事先创建好servlet对象。只需要

在web.xml文件中,添加<load-on-startup>配置即可。

a2,如何实例化?

调用servlet的构造器。

b,初始化(分配资源)

b1,如何初始化?

调用servlet的init(ServletConfig config)方法,

容器在调用该方法时,会事先创建好一个config对象,

该对象的作用是提供了访问servlet的初始化参数的方法。

b2,初始化参数

step1,在web.xml文件里,使用<init-param>配置

初始化参数。

step2,使用ServletConfig提供的

getInitParameter(String paraName)获得参数值。

b3, 如何实现自己的初始化处理逻辑?

override init(ServletConfig config)方法。

override init()方法(推荐)

b4,init方法只会执行一次。

c,就绪(调用相应方法处理请求)

容器调用service方法来处理请求。

d,销毁(销毁servlet对象)

容器在销毁servlet对象之前,会调用destroy方法。

只会执行一次该方法。

(3)生命周期相关的接口与类

a,Servlet接口

init(ServletConfig config)

service(ServletRequest req,ServletResponse res)

destroy()

b,GenericServlet抽象类

实现了init,destroy方法。

c,HttpServlet抽象类

实现了service方法,该方法会依据请求类型分别调用

doGet,doPost方法。所以我们在写一个servlet时,

可以选择两种方案来编写处理逻辑:

第一种方式:override service方法

第二种方式:override doGet,doPost方法

d,ServletConfig接口

String getInitParameter(String paraName);

e,ServletRequest接口/ HttpServletRequest接口

f,ServletResponse接口/ HttpServletResponse接口

练习:

给产品计税:

产品的价格(price) = 原始价格 * (1 + 税率)。

税率与销售城市的对应关系可以写在web.xml文件里面,

比如:

<init-param>

<param-name>taxRate</param-name>

<param-value>bj,0.13;sh,0.14;cs,0.08</param-value>

</init-param>

1,jsp是什么?

java server page(java服务器端页面技术)

sun公司制订的一种服务器端动态页面生成技术的规范,在jsp

技术当中,只需要在html标记当中,添加少量的java代码,就可

以实现动态页面。

因为直接使用servlet输出动态页面非常麻烦(需要使用

out.println),并且难以维护(如果页面发生改变,需要修改

java代码)。所以,sun才会制订jsp规范。

2, 如何写一个jsp文件?

step1,写一个以.jsp为后缀的文件。

step2,在该文件里面,可以添加如下的内容:

1) html(css,javascript): 直接写。

2) java代码:

a, java代码片断

<%  java代码   %>

b, jsp表达式

<%=java表达式%>

3)隐含对象:

a,隐含对象是什么?

是在.jsp文件里面,可以直接使用的一些对象,

比如out,request,response。

b,为什么可以直接使用?

因为容器会自动添加创建这些隐含对象的代码。

4)指令:

a,指令是什么?

通知容器,在将.jsp文件转换成.java文件时做一些

额外的处理,比如导包。

b,指令的基本语法?

<%@指令名称 属性%>

c,page指令

import属性 : 导包

比如: <%@page import="java.util.*"%>

<%@page import="java.util.*,java.text.*"%>

contentType属性:设置response.setContentType的内容。

pageEncoding属性:告诉容器,.jsp文件的编码是什么,

这样,容器在读取.jsp文件的内容时,就不会发生乱

码问题。

3,jsp是如何执行的?

step1, 容器先将.jsp文件转换成一个.java文件(其实,就是将

jsp转换成一个对应的servlet) 。

a, html    ------>  service方法里,使用out.write输出(

write方法会将"null"转换成""输出)。

b,<%  %>  ------>  service方法里,照搬。

c,<%=  %> ------>  service方法里,使用out.print输出。

out.print();

step2, 执行servlet的service方法。

4、转发

(1)什么是转发?

一个web组件(servlet,jsp)将未完成的处理通过容器

转交给另外一个web组件继续完成。

常见的情况是:一个servlet获得数据之后,转发给

一个jsp来生成相应的页面。

(2)如何转发?

step1,绑订

//绑订数据到request

request.setAttribute(String name,Object obj);

//解除绑订

request.removeAttribute(String name);

//依据绑订名称获得绑订值,如果找不到,返回null。

Object request.getAttribute(String name);

step2,获得转发器

//url:转发的目的地。

RequestDispatcher rd =

request.getRequestDispatcher(String url);

//step3,转发

rd.forward(request,response);

(3)转发需要注意的问题

a,在转发之前,服务器会清空response中的所有数据。

b,在转发之前,不能够调用out.flush(),out.close()。

(4)特点

a,转发的目的地地址只能够是同一个应用内部某个

组件的地址。

b,转发之后,浏览器地址栏的地址不变。

5、给容器配置错误处理页面

当应用程序在运行过程当中,发生了系统异常,可以这样处理:

step1,编写一个错误处理页面

step2,在web.xml文件当中,配置错误处理页面

练习:

1、完成员工信息管理系统

2、完成注册功能

要求,如果用户名已经存在,提示用户换一个,

否则,插入用户信息,跳转到登录页面。

create table t_user(

id int primary key auto_increment,

username varchar(50) unique,

name varchar(255),

password varchar(20),

gender char(1)

);

unique:唯一性约束

1、转发与重定向的区别

相同点:都可以实现某一个web组件执行之后,接着调用另外

一个web组件。俗称"跳转"。

(1)重定向的地址是任意的,而转发的地址必须是同一个

应用内部的某个组件的地址。

(2)重定向之后,浏览器地址栏的地址会变成重定向地址,

而转发不变。

(3)重定向所涉及的组件不能够共享request对象,而

转发可以。

请求对象(request),响应对象(response)的生存时间

是一次请求与响应期间。重定向需要两次请求,会创建两

个完全不一样的request对象。

2、路径问题

链接地址、表单提交地址、重定向、转发

<a href="地址">

<form action="地址">

response.sendRedirect("地址");

request.getRequestDispatcher("地址")

1)什么是相对路径

不以"/"开头的路径

2)什么是绝对路径

以"/"开头的路径

3)怎样写绝对路径

链接地址、表单提交地址、重定向这三种情况,绝对路径

从应用名开始写;转发从应用名之后开始写。

String request.getContextPath();

3、状态管理

1)什么是状态管理

将浏览器与服务器之间多次交互所涉及的数据按用户

保存下来。

2)如何进行状态管理

a,cookie(小甜饼)

将状态(也就是浏览器与服务器之间交互所涉及的数据)

保存到浏览器端。

b,session(会话)

将状态保存在服务器端。

3)cookie

a,cookie是什么?

浏览器访问服务器时,服务器将少量的数据以

set-cookie消息头的方式发送给浏览器,浏览器

会将这些数据保存下来;当浏览器再次访问服务器

时,会将之前保存的数据以cookie消息头的方式 

发送给服务器。

b,如何创建cookie?

//name:cookie的名称,value:cookie的值

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

response.addCookie(c);

c,查询cookie

//如果没有发现cookie,会返回null。

Cookie[] getCookies();

String name = cookie.getName();

String value = cookie.getValue();

d, 如何处理中文

cookie只能够保存ascii字符。

将中文转换成ascii字符。

//encode: 先对str进行编码,然后将编码之后

//得到的字节数组转换成一个ascii字符串。

String str2 = URLEncoder.encode(

String str,String code);

//decode:解码

String str2 = URLDecoder.decode(String str,

String code);

练习:

写一个Find_Add_CookieServlet, 该servlet

首先查询有没有一个名叫"userprofile"的cookie,

如果有,则显示该cookie的值;如果没有,则创建

该cookie(cookie的值自己设置,比如"abc",不用考虑

编码问题);

e,生存时间

cookie.setMaxAge(int seconds);

seconds:单位是秒

seconds > 0, 浏览器会将cookie保存在硬盘上。当超过

指定的时间,浏览器会删除该cookie。

seconds = 0,删除cookie:

比如,要删除一个名叫"addr"的cookie:

Cookie cookie = new Cookie("addr","");

cookie.setMaxAge(0);

response.addCookie(cookie);

seconds < 0,默认值,浏览器会将cookie保存到内存

里。

f,cookie的路径问题

浏览器在向服务器发请求时,会先比较

cookie的地址与要访问的服务器的地址是否匹配,

只有匹配的cookie才会发送给服务器。

f1, cookie的默认的路径:

等于创建该cookie的组件的地址。

f2,匹配规则

要访问的服务器的地址必须是cookie的路径或者

其子路径时,浏览器才会将cookie发送给服务器。

f3,调用cookie.setPath(String path);方法来设置

cookie的路径。

常见的设置 cookie.setPath("/appname");

g、cookie的限制:

a, cookie可以被禁止。

b, cookie能够保存的数据很小,大约4k左右。

c, cookie的个数也有限制。

d, cookie能够保存的数据类型只能是字符串。

e,cookie不安全。

1、session

(1)什么是session?

浏览器在访问服务器时,服务器会创建一个session

对象(该对象有一个唯一的id号,称之为sessionId),服务器

默认情况下,会将这个sessionId以set-cookie消息头的

方式发送给浏览器;浏览器会将这个sessionId保存下来(内存),

当浏览器再次访问服务器时,会将sessionId发送过来,

服务器依据sessionId可以找到之前创建的session对象。

(2)如何获得一个session?

a,  HttpSession session = request.getSession(boolean flag);

当flag为true时:

当请求到达服务器时,服务器会检查请求当中是否

包含sessionId,如果没有,服务器会创建一个session对象;

如果有sessionId,服务器会依据sessionId查找对应的

session对象,如果找到了,则返回,如果找不到,则

创建一个新的session对象。

当flag为false时:

当请求到达服务器时,服务器会检查请求当中是否

包含sessionId,如果没有,返回null。

如果有sessionId,服务器会依据sessionId查找对应的

session对象,如果找到了,则返回。如果找不到,返回

null。

b, HttpSession session = request.getSession();

等价于request.getSession(true)。

(3)HttpSession接口中声明的常用方法

String getId(); //返回sessionId

setAttribute(String name,Object obj); //绑订

//如果绑订值不存在,返回null。

Object getAttribute(String name);

removeAttribute(String name); //解除绑订

(4)session的超时限制。

服务器会将空闲时间过长的session对象从内存当中删除,

称之为session的超时限制。

可以通过修改服务器的配置来设置服务器的

超时限制。

比如tomcat可以修改 /conf/web.xm中的

<session-config>

<session-timeout>30</session-timeout>

</session-config>

也可以将以上配置信息添加到某个web应用的web.xml

文件里。

//设置session对象的最大空闲时间

session.setMaxInactiveInterval(int seconds);

(5)删除session

session.invalidate();

2、session验证

step1,在登录成功以后,绑订相关数据到

session上。比如

session.setAttribute("user",user);

step2,在需要保护的资源代码里面,添加

session验证代码:比如

Object obj = session.getAttribute("user);

if(obj == null){

response.sendRedirect("login.jsp");

}

练习:

在访问http://ip:port/appname/list.do时,检查用户是否

登录过,如果没有,跳转到登录页面。

3、验证码

练习:

写一个CheckcodeServlet,生成一个验证码,要求

验证码长度必须为5,并且字符必须是随机从

"A~Z","0~9"当中取出的字符组成。

比如  "AM27B"

4、购物车

(1)功能点

a,商品列表

(2)实现

a,商品列表

step1, 建表

create table t_computer(

id int primary key auto_increment,

model varchar(50),

pic varchar(100),

prodDesc text,

price double

);

step2,建一个web工程 shoppingcart

step3,写实体类 Computer

step4, 写ComputerDAO( List<Computer> findAll())

step5, 写ActionServlet(采用*.do匹配),该servlet调用

ComputerDAO获得一个List<Computer>集合,然后转发

给Computer_list.jsp。

step6,Computer_list.jsp(只需要遍历List<Computer>集合)

购物车

(1)功能点

a,商品列表

b,购买商品

c,查看购物车

d,删除商品

e,清空商品

f,修改商品数量

(2)实现

a,商品列表

b,购买商品

将用户点击的商品添加到购物车,如果已经购买,需要

提示用户。

1、如果用户禁止cookie,如何继续使用session?(了解)

可以使用url重写机制来解决这个问题。

(1) 什么是url重写。

在要访问的组件的地址后面添加sessionId。

(2)如何进行url重写。

链接地址、表单提交地址使用

response.encodeURL(String url)。

重定向地址使用

response.encodeRedirectURL(String url)。

比如: 

response.sendRedirect(

response.encodeRedirectURL("list.do"));

1、session的优点和缺点

优点:

a,安全

b,保存的数据大小理伦上讲没有限制

c,保存的数据类型更丰富

缺点:

a,浏览器关闭,session机制失效(因为sessionId

保存在了内存里面)。

b,所有的状态数据都保存在了服务器端,所以,服务器的

压力(内存空间的占用)比较大

2、过滤器

(1)什么是过滤器?

servlet规范中定义的一种特殊的组件,可以对容器的

调用过程进行拦截。

(2)编程

step1,写一个java类,实现Filter接口

step2,在doFilter方法里面实现拦截处理

step3,配置过滤器(web.xml)。

练习:写一个CommentFilter2过滤器,该过滤器

检查评论的内容的长度,如果超过20个字符,则提示

用户评论的长度非法。否则,调用CommentServlet输出

评论的内容。

(3)过滤器的优先级

<filter-mapping>配置的先后顺序决定过滤器执行的先后顺序。

(4)初始化参数

step1,在web.xml文件中,使用

<init-param>给过滤器配置一些初始化参数

step2, String FilterConfig.getInitParameter(String paraName);

(5)过滤器的优点

a,将多个组件相同的或者近似的代码(常见的有

session验证、权限管理、编码处理等等)放在过滤器里面,

方便代码的维护。

b,可以实现代码的“可插拔性"(增加或者减少某个模块,不

会影响到整个程序的正常执行)。

3、监听器

(1)什么是监听器?

servlet规范中定义的一种特殊的组件,用来监听

容器产生的两类事件并处理。

两类事件:

当容器创建或者销毁request,session,

ServletContext(servlet上下文对象)这三个

对象时产生的事件 --->生命周期相关事件。

当执行了request,session,ServletContext的

setAttribute,removeAttribute方法时产生的

事件 --->绑订相关事件。

(2)ServletContext接口

容器在启动的时候,会为每一个已经部署的应用

创建唯一的一个符合ServletContext接口的对象,称之

为Servlet上下文对象。该对象会一直存在,除非关闭

容器。

a,如何获得servlet上下文对象

a1,GenericServlet.getServletContext();

a2,HttpSession.getServletContext();

a3,ServletConfig.getServletContext();

a4,FilterConfig.getServletContext();

b,作用

b1,绑订数据

setAttribute,removeAttribute,getAttribute

request,session,servletContext三个对象,生命周期

的长度依次增大,在使用时,基本原则是,在满足需要的情况下,

优先使用生命周期短的。

b2,访问全局的初始化参数

String getInitParameter(String paraName)

b3, 依据逻辑路径获得实际部署时的物理路径

String getRealPath(String path);

(3)如何写一个监听器

step1,写一个java类,依据监听事件的类型选择实现一个

相应的监听器接口。

step2,在接口声明的方法里面,实现相应的监听处理逻辑。

step3,配置监听器(web.xml)。

统计在线人数:

写一个监听器CountListener(

实现HttpSessionListener)

1、上传文件

step1, 给表单添加

enctype属性,并且设置其值为

"multipart/form-data"。浏览器不再

对表单中的数据进行编码,而是将表单中的

每一个表单域的数据划分成各个数据块发送给

服务器。此时,服务器端不能够再使用request.getParameter

方法。只能通过调用InputStream request.getInputStream(),

在得到这个输入流以后,分析获得数据。一般会借助于一些工具

来分析。另外,表单的提交方式必须为post方式。

step2, 服务器端借助于一些开源工具(比如apache提供的

commons-fileupload.jar)来分析获得相关的数据。

2、线程安全问题

(1)线程安全问题产生的原因

在默认情况下,容器只会为每一个servlet创建唯一的

一个实例。

当有多个请求到达容器时,容器会创建多个线程来处理

请求,如果多个线程同时修改某个servlet实例的

属性,就有可能发生线程安全问题。

(2)解决

a,加锁:使用synchronized对有线程安全问题的代码加锁。

b,让一个servlet实现SingleThreadModel接口(该

接口没有声明任何的方法)。容器会为实现了这个

接口的servlet创建多个实例(一个线程一个实例)。

建议少用,因为有可能产生过多的实例。

servlet小结

1、servlet基础

(1)什么是servlet?

(2)什么是servlet容器?

(3)servlet依赖容器运行吗?

(4)如何开发一个servlet?

(5)http协议的基础知识(了解)

2、servlet核心

(1)表单处理

a,如何获得表单中的请求参数值

String request.getParameter(String paraName);

//city=bj&city=sh&city=wh

String[] request.getParameterValues(String paraName);

b,有中文参数值

step1,要保存表单所在的页面以指定的编码格式打开。

step2,

//post请求

request.setCharacterEncoding(String code);

//get,post请求

new String(str.getBytes("iso-8859-1"),"utf-8");

(2)get请求与post请求

a,哪一些是get请求

b,哪一些是post请求

c,get请求的特点

d,post请求的特点

e,区别

(3)重定向与转发

a,什么是重定向

b,如何重定向

response.sendRedirect(String url);

c,重定向需要注意的问题

d,重定向的特点

e,什么是转发

f,如何转发

request.getRequestDispatcher(String url).

forward(request,response);

g,转发需要注意的问题

h,转发的特点

i, 区别

(4)servlet的生命周期

a,四个阶段

b,servlet什么时候实例化

c,load-on-startup参数

e,init方法如何override

f,线程安全问题(产生的原因,解决方式)

g,相关的接口与类(Servlet,GenericServlet,HttpServlet,

ServletConfig,ServletRequest,ServletResponse,

HttpServletRequest,HttpSevletResponse)。

h,初始化参数(init-param)

3、状态管理

(1)状态管理的含义

(2)如何进行状态管理

(3)cookie

a,什么是cookie

b,如何创建一个cookie

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

c.setMaxAge(int senconds);

c.setPath(String path);

response.addCookie(c);

c,编码问题

URLEncoder.encode(String name,String code);

String URLDecoder.decode(String name,String code);

e,生存时间

setMaxAge(int seconds)

f,路径问题

setPath(String path)

g,查询

Cookie[] request.getCookies();

String cookie.getName();

String cookie.getValue();

h, cookie的限制

(4)session

a,什么是session?

b,如何获得一个session?

HttpSession request.getSession();

HttpSession request.getSession(boolean flag);

c,HttpSession提供的常用方法

String getId();

setAttribute,getAttribute,removeAttribute

d,session的超时

setMaxInactiveInterval(int seconds);

也可以修改配置文件。

e,删除session

session.invalidate();

f,如果禁止cookie,如何继续使用session?(url重写)

response.encodeURL(String url);

response.encodeRedirectURL(String url);

g,session的优缺点

4、数据访问

(1)使用jdbc访问数据库

(2)dao

a,什么是dao?

b,如何去写一个dao?

5、过滤器与监听器

(1)什么是过滤器?

(2)如何写一个过滤器?

(3)过滤器的优先级

(4)初始化参数

(5)过滤器的优点

(6)什么是监听器

(7)如何写一个监听器

(8)ServletContext接口

a,什么是servlet上下文对象?有何特点?

b,如何获得?

c,作用

setAttribute,getAttribute,removeAttribute

String getInitParameter(String name);

String getReal(String path);

6、上传文件(扩展)

7、典型案例

(1)员工管理(增删改查)

(2)session验证

(3)验证码

(4)购物车(session, session + cookie)

(5)交友系统

一、jsp基础

1、什么是jsp?

2、如何写一个jsp?

step1, 写一个以.jsp为后缀的文件

step2, 添加:

(1)html :直接写

(2)java代码:

a, java代码片断:

<%   %>

b, jsp表达式:

<%=   %>

c, jsp声明

<%!   %>

给jsp对应的servlet添加属性或者方法。

(3)使用指令

a,page指令:

import:导包

pageEncoding:jsp文件的编码。

contentType:设置response.setContentType的内容。

session:true(缺省)/false,当值为false时,对应的

servlet不再添加获得session的代码。

isELIgnored:true(缺省)/false,当值为true时,

容器会忽略el表达式。

isErrorPage:true/false(缺省),如果值为true,表示

这个jsp是一个错误处理页面。

errorPage:指定一个错误处理页面。

step1,编写一个错误处理页面,可以设置

isErrorPage="true",然后,调用exception

隐含对象的方法输出错误信息。

step2,在jsp页面文件里面,使用errorPage

指定由哪一个错误处理页面来处理错误。

language:

b,include指令

file:容器在将.jsp文件转换成.java文件时,在该

指令所在的位置插入相应的文件的内容。

c,taglib指令

导入标签(具体用法见标签的使用)。

(4)隐含对象

out

request

response

session

application

exception

pageContext:PageContext接口的实例,容器会为

每一个jsp实例创建唯一的一个pageContext对象。

其作用:

绑订数据: setAttribute,getAttribute,removeAttribute

绑订到该对象上的数据只能由对应的jsp实例访问。

找到其它八个隐含对象:pageContext提供了相应的

方法来获得其它八个隐含对象。

config:ServletConfig接口的实例。

page:相当于this(jsp实例本身)

(5)注释

<!--  注释内容 --> :注释的内容不会显示在页面上,

但是,如果注释的内容是java代码,会执行。

<%--  注释内容   --%>注释的内容不会显示在页面上,

如果有java代码,会忽略。

3,jsp是如何执行的

step1, .jsp文件转换成一个对应的servlet

html   ---- > service方法里,使用out.write输出

<%   %> ---> service方法里,照搬

<%=  %> ---> service方法里,使用out.print输出。

<%!   %> ----> 对应的servlet添加属性或者方法

step2,调用servlet。

练习:

完成“网上交友”。

一、jsp标签与el表达式

1、jsp标签是什么?

因为直接在.jsp文件中添加java代码,虽然可以实现

动态页面,但是,不利于维护(比如,将.jsp文件交给美

工来修改的话,就很不方便)。所以,sun制订了jsp标签

技术,其实质是,将jsp文件中的java代码写在一个标签类

里面,然后,在jsp文件中添加一个类似于html的标签,

当容器执行jsp时,会依据标签找到标签类,然后调用标签类

中的代码。

2、el表达式是什么?

是一种简单的计算规则,用于给标签的属性赋值。现在,

也可以直接输出。

3、el表达式的使用:

1)访问bean的属性

第一种方式:

${user.name}: 容器会依次从pageContext,

request,session,application中查找绑订名为

"user"的对象,如果找到了,则不再向下继续查找。

接下来,调用该对象的getName方法,最后输出。

相比于直接写java代码,有两个优点:

会将null转换成""输出,另外,找不到某个对象,

不会报空指针异常,会输出""。

可以使用${sessionScope.user.name}来指定从

session中查找。此外,还有requestScope,pageScope,

applicationScope查找范围。

第二种方式:

${user["name"]},这种形式有两个优点:

允许[]里面出现变量,比如 ${user[prop]}。

允许[]里面出现从0开始的下标,

比如${user.interest[0]},输出数组某个元素的值。

2)获得请求参数值

${param.username} 等价于

request.getParameter("username");

${paramValues.city} 等价于

request.getParameterValues("city");

3)进行简单的计算,计算结果可以给标签的属性赋值,或者

直接输出。

a,算术运算: "+","-","*","/","%"。注意,不能够进行字符

串的连接操作。

b,关系运算:"==","!=",">",">=","<","<="。

c,逻辑运算: "&&","||","!"。

d,empty运算:

以下四种情况结果为true。

d1,空字符串  ""

d2,空的集合

d3,值为null

d4,找不到某个对象

4、jstl标签(java standard taglib,是一系列标签,由

apache开发,但sun将其标签化)

1)编程的基础步骤

step1,将标签对应的.jar文件放到WEB-INF\lib下。

D:\czh\MyEclipse 5.5.1 GA\

eclipse\

plugins\

com.genuitec.eclipse.j2eedt.core_5.5.1\

data\

libraryset\

JSTL1.1\lib

jstl.jar  standard.jar

step2,在.jsp文件里面,使用taglib指令导入标签。

<%@taglib uri="" prefix=""%>

uri:一个命名空间。

prefix:命名空间的前缀。

2)几个核心的标签

a,<c:if test="" var="" scope="">

标签体(这儿,允许出现java代码

<%  %>,<%= %>,<%!  %>)

</c:if>

如果test属性值为true,则执行标签体的内容。如果

为false,则不会执行标签体的内容。

test属性一般使用el表达式来赋值。

var属性指定一个绑订名称。

scope属性指定绑订的范围(page,request,session,application)

<c:choose>,<c:when>,<c:otherwise>

when,otherwise必须用写在choose标签里面。

when可以出现多次,而otherwise最多只能出现1次。

when标签有一个test属性,含义及用法跟if标签中的一样。

<c:forEach var="" items="" varStatus="">

</c:forEach>

遍历集合, items属性指定要遍历的集合,一般使用el

表达式来赋值。var属性指定绑订名,绑订范围是

pageContext,绑订值是items指定的集合中的某个元素。

varStatus属性指定绑订名,该绑订名对应的对象

(由容器创建这个对象)封装了迭代的状态,该对象

的index属性表示正在被访问的对象的下标,count属性

表示是第几次访问。

3)标签执行的过程

容器依据命名空间找到对应的标签描述文件(容器

会从WEB-INF\或者是.jar文件的META-INF下查找

.tld文件),然后依据标签名找到对应的标签类 ,接下来,

会创建标签类的实例并调用相应的方法。

练习:

将员工管理系统中的emplist.jsp与empUpdate.jsp中的

java代码代替为jsp标签与表达式。

日期这部分java代码先不用管。

5、自定义标签

step1, 写一个java类,继承SimpleTagSupport类。

step2, override doTag方法,在该方法里面,编写

相应的处理逻辑。

step3, 在.tld文件里,描述标签。.tld文件必须要放在

WEB-INF\下,或者是META-INF\下。

<body-content>empty</body-content>:

没有标签体。

<body-content>scriptless</body-content>

可以有标签体,但是,标签体的内容不能够出现任何的

java代码(<%  %>,<%=  %>,<%!  %>)。

<body-content>JSP</body-content>

可以有标签体,标签体的内容可以出现java代码。只有

复杂标签技术支持JSP。简单标签技术只支持empty,

scriptless。

练习:写一个<c1:date/>,会按照"yyyy-MM-dd"的格式输出

系统日期。

6、el函数

跟标签的使用步骤一样。el函数会对el表达式的结果进行

处理并输出。

7、自定义el函数

step1,写一个java类,需要提供public static方法。

step2,在public static方法里面,提供处理逻辑。

step3,在.tld文件中描述函数。

二、mvc(model,view,controller)

1、什么是mvc?

是一种软件架构思想,将一个软件的组成部分划分成三种

不同类型的模块,分别是模型(封装业务逻辑),视图(用户交互),

控制器(协调)。

按照mvc思想,所有的请求通过视图发送给控制器,控制

器调用相应的模型来处理请求;模型处理之后的结果会交给控制器,

由控制器选择一个合适的视图将结果展现给用户。

这样做的主要原因,是为了方便模型的复用(复用包含

两个方面的含义:第一个,模型返回的数据,可以使用

不同的视图来展现;第二个,对于同一个模型

,可以提供

不同的视图来访问。)

2、在web应用当中,如何使用mvc?

模型: 使用java类来实现。

视图: 使用jsp来实现。

控制器:  使用servlet(或者Filter)来实现。

"贷款申请":

用户通过表单提交“帐号”,“贷款金额",后台

通过帐号查询t_account表:

如果帐号不存在,提示用户帐号错误。

如果帐号存在,则比较余额与贷款金额:

如果贷款金额 > 余额 * 10,则提示余额不足。

否则,系统生成一个序列号,该序列号

要显示给用户,并且保存到数据库。

3、mvc的优点?

1)模型可以被不同的视图来复用。

2)模型很方便用来测试。(比如,将业务逻辑写在

servlet里,需要部署才能测试)。

3)按照mvc的思想,可以对系统分层。

方便分工,也方便代码的维护。

4、缺点:

增加设计的难度,增加开发的工作量。

时间: 2024-11-13 12:33:45

servlet的运行过程的相关文章

IOS学习之路- 运行过程

1. 执行Main函数(在main.m文件中) 2. 加载MainStoryborad.storyboard文件 * 创建ViewController文件 * 根据storyboard文件中描述创建ViewController中的UIView(父层) * 创建UIView内部的所有子控件 * 将创建好的所有UIView对象跟ViewController做相应的关联(IBAction,IBoutlet  ) 3. 将程序的第一个控制器内部的UIview显示到手机屏幕上. IOS学习之路- 运行过程

OC学习小结之ios运行过程详解

1)ios核心类 UIView 视图,屏幕上能看得见的东西都是视图,例如:按钮.文本标签.和表格等 UIViewController:内部默认有个视图(UIView),负责管理UIView的生命周期.装配数据到UIView上显示.处理其事件 ios采用MVC模式:model -view -controller 2)运行过程 ios运行原理 1.先执行main函数 2.main函数调用UIApplicationMain函数 创建一个UIApplication实例,这个是一个单例对象,一个ios程序

程序启动和运行过程

摘抄自:http://www.cnblogs.com/kenshincui/p/3890880.html#runProcess 程序的运行过程 在几乎所有的程序开发中程序一般都是从main函数开始运行的,那么IOS程序也不例外,在上图中我们可以看到Xcode为我们生成了一个main.m文件: // // main.m // FirstIOS // // Created by Kenshin Cui on 14-2-23. // Copyright (c) 2014年 Kenshin Cui. A

从内存中分析程序的运行过程

我觉得图形是最可以直观一种解释方法,所以先把程序运行过程的图形解析流程给大家,通过图形来一步一步的理解才是最让人清楚,直观的: 流程图懂了,好多事情也就懂了!

Windows窗口程序运行过程

现在,简单介绍下windows应用程序的大概运行过程,让刚开始接触Windows开发或者MFC开发的同学有一个大致的了解. 1.创建一个窗口首先要注册一个窗口类,初始化wndclass中的各个域,设置窗口过程函数. 2.调用RigisterClass来注册这个窗口类. 3.创建窗口.CreateWindow 4.显示窗口.ShowWindow 5.刷新窗口.UpdateWindow 5.消息循环. 这里主要讲解消息循环. 消息循环中的循环是由程序中 while(GetMessage(&msg,N

黑马程序员----整个程序的运行过程

程序的运行过程: 1.编写代码: 2.编译:把C语言代码翻译成0和1 *工具:clang编译器,(Xcode 3 gcc Xcode 4 llvm clang) *指令:cc -c 文件名.c *编译成功会自动生成一个.o目标文件 3.连接:把我们的.o目标文件和系统自带的函数库合并在一起,生成一个可执行文件 *指令:cc 文件名.o *链接成功后会自动生成一个.out可执行文件 4.运行 *指令:./a.out(./代表在当前文件夹下,a.out为生成的可执行文件) 注意: 1.cc 文件名.

appium界面运行过程(结合日志截图分析)

appium界面运行过程: 1.启动一个http服务器:127.0.0.1:47232.根据测试代码setUp()进行初始化,在http服务器上建立一个session对象3.开始调用adb,找到连接上的设备,设置设备id4.等待设备准备好响应命令5.开启logcat日志监控6.将生成的apk属性信息文件strings.json存到了设备 /data/local/tmp目录下7.读取apk安装情况8.端口映射,发给appium httpserver的内容,经过httpserver后直接发给设备 f

Perl 关于在程序运行过程中重新开启标准输入的问题

遇见问题是,如何程序运行的时候已经将标准输入使用"<"符号或者"|"符合在命令行定向为一个文件. 可是在程序的运行过程中希望从键盘得到输入内容. 因为/dev/tty为当前进程的控制台,STDIN 为当前的标准输入. 如果重定向,例如: perl script.pl <myfile.txt STDIN 被指向 myfile.txt, 但是 /dev/tty 仍然来自于控制终端.所有的Unix都是这样,不单单是指这个perl. 那么解决方案: #!/usr

flume sink运行过程简单分析

没有运行,直接看源码得到sink简单运行过程 SinkRunner负责运行sink程序 内部类 PollingRunner implements Runnable {  private SinkProcessor policy; } 负责运行sink run方法 while (!shouldStop.get()) { try { if (policy.process().equals(Sink.Status.BACKOFF)) { counterGroup.incrementAndGet("ru