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、缺点:
增加设计的难度,增加开发的工作量。