如今,通用的浏览器取代了个性化的客户端,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.get
InitParameter(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: <%@page
contentType="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=F629638559B43254608A0D
71D9839797
)。
如果用户进制了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消息头),服务器收到响应后立即向该地址发送请求,这样,即使浏览器禁掉了session,仍然可以向服务器发送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即可。
31、ServletContext
(1)ServletContext是一个接口,当容器启动的时候,会为每一个应用创建唯
一的一个符合该接口的对象,称之为servlet上下文。该对象会一直存在,
除非容器关闭。另外,一个应用只有唯一的一个servlet上下文。(每一个
应用是一个ServletContext对象,就像每一个类都是class对象一样)
(2)如何获得servlet上下文?
a, GenericServlet.getServletContext();
b, ServletConfig.getServletContext();
c, HttpSession.getServletContext();
d, FilterConfig.getServletContext();
在.jsp文件中,servlet上下文只需用隐含对象application就可以了。
(3)servlet上下文的作用?
a, String getRealPath(String path);
依据逻辑路径("path")获得实际部署时的物理路径。
b, 绑订数据
setAttribute(String name,Object obj);
Object getAttribute(String name);
removeAttribute(String name);
servlet上下文绑订的数据可以被所有的组件访问到,并且因为servlet上
下文一直存在,所以可以随时访问。如果request,session,servlet上下文
都可以满足绑订数据的需要,应该优先使用生命周期短的
(request<session<servletContext)。
c,访问全局的初始化参数
指的是同一个应用内部的所有的servlet,filter都可以访问的初始化参
数。
step1,配置
<context-param>
<param-name>company</param-name>
<param-value>tarena</param-value>
</context-param>
step2,使用
String ServletContext.getInitParameter(String
paraname);
对于ServletContext,区别于Session和Request在.jsp文件中使用隐含对象application对象调用相应方法获得绑定值:application.getAttribute(String name);
其中,.java中的sctx对象和.jsp中application是同一个ServletContext对象,
.jsp在转为.java文件中的变量声明如下:
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
32、servlet线程安全问题
(1)为什么说servlet会有线程安全问题
a,容器在默认情况下,只会为servlet创建唯一的一个实例。
b,当容器收到一个请求,会启动一个线程来处理,就有可能有多个线
程同时访问某个servlet实例。
比如:
如果多个线程同时去修改servlet实例的某个属性值,就有可能发生
线程安全问题。
(2)如何解决线程安全问题?
a, 使用synchronized加锁
b,让servlet实现SingleThreadModel接口,容器会为每一个实现了该
接口的servlet创建多个实例(一个线程一个实例)。该方式不建议使
用,因为会创建过多的servlet实例,而导致服务器资源的过多开销。
33、XML配置文件顺序:
<web-app>
<!-- 全局的初始化参数 -->
<context-param>
<param-name>company</param-name>
<param-value>Mr.Zhu Co.,LTD</param-value>
</context-param>
<!-- 过滤器 -->
<filter></filter>
<!-- 注册监听器 -->
<listener>
<listener-class>web.CountListener</listener-class>
</listener>
<servlet>
<servlet-name>SomeServlet</servlet-name>
<servlet-class>web.SomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SomeServlet</servlet-name>
<url-pattern>/some</url-pattern>
</servlet-mapping>
<web-app>
34、servlet小结
(1)servlet基础
a,什么是servlet?
b,什么是servlet容器?
c,servlet依赖特定的servlet容器吗?
d, 如何开发一个servlet?
e,http协议的常识(什么是http协议,数据包的结构,
状态码,消息头)
f,get请求与post请求(哪一些是get请求,哪一些是
post请求,各自的特点)
(2)servlet核心
1)表单的处理
a,获得请求参数值
String request.getParameter(String paraname);
String[] request.getParameterValues(String paraname);
request.getParameter()获得所有请求参数的名字
request.getParameterMap()获得所有请求参数的键值对。
b,中文参数值
step1,保证页面按照指定的编码格式打开。
html: <meta http-equiv...>
jsp: <%@page pageEncoding contentType..%>
step2, 告诉服务器如何解码
request.setCharacterEncoding("utf-8");
或者 new String(str.getBytes("iso-8859-1"),"utf-8")
2)重定向与转发
a,什么是重定向?
b,如何重定向?
response.sendRedirect(String url)
c,重定向需要注意的问题?
d,重定向的特点
e,什么是转发?
f,如何转发?
request.setAttribte...
request.getRequestDispatcher().forward...
g,转发需要注意的问题?
h,转发的特点
i,转发与重定向的区别
3)容器如何处理请求资源路径?
4)如何让一个servlet处理多种请求?
5)servlet的生命周期
a,四个阶段
b,生命周期相关的接口与类
6)线程安全问题
a,线程安全问题是如何产生的?
b,怎样解决?
(3)状态管理
1)什么是状态管理?
2)cookie技术
a,什么是cookie?
b,如何创建一个cookie?
Cookie c = new Cookie(String name,String value);
response.addCookie(c);
c,编码问题
String URLEncoder.encode..
String URLDecoder.decode...
d,生存时间问题
setMaxAge(int seconds);
e,路径问题
setPath(String path);
f, cookie的限制
3)session技术
a,什么是session?
b,如何获得一个session?
HttpSession request.getSession(boolean flag);
HttpSession request.getSession();
c,常用方法
String getId();
setAttribute,getAttribute,removeAttribute
d,session超时
setMaxInactiveInterval(int seconds)
e,删除session
invalidate();
f,禁止cookie之后,如何继续使用session?
url重写
response.encodeURL(String url);
response.encodeRedirectURL(String url);
(4)数据库访问
a, 使用jdbc访问数据库
b, dao
(5)过滤器与监听器
a,什么是过滤器
b,怎样写一个过滤器
c,过滤器的优先级
d,过滤器的初始化参数
e,过滤器的优点
f,什么是监听器
g,怎样写一个监听器
h,servletContext
(6)扩展与典型案例
a,上传文件
b,员工信息管理
c,session验证
d,验证码
e,购物车
35、jsp基础
(1)什么是jsp?
(2)如何写一个jsp文件?
step1, 写一个以".jsp"为后缀的文件
step2,添加:
1)html (css,js): 直接写。
2)java代码:
a, java代码片断
<% java代码 %>
b, jsp表达式
<%= %>
c,jsp声明
<%! 变量、方法 %>
3)指令
a,page指令
import属性:导包
pageEncoding属性:告诉容器, jsp文件的编码格式。
contentType属性:设置response.setContentType的内容。
session属性:true(缺省)/false,当值为false时,容器不再负
责创建session对象了。
isErrorPage属性:true/false(缺省值),当值为true时,表示这
是一个错误处理页面(专门用于处理其它
jsp页面的异常的);
errorPage属性: 指定一个错误处理页面,该页面用来处理当
前页面所产生的异常。
我们可以采取以下步骤来处理jsp产生的异常:
step1, 编写一个错误处理页面,比如error.jsp,在该jsp文
件中,设置isErrorPage="true",调用exception
隐含对象输出错误的描述。(<h1>发生了错
误:<%=exception.getMessage()%></h1>)
step2, 在jsp文件中,使用errorPage="error.jsp",
来指定由哪一个页面来处理jsp运行过中的产生的异常。
isELIgnored属性:true(缺省)/false,当值为false时,表示
要求servlet容器不要忽略el表达式。servlet&jsp经典总结
b, include指令
file属性:被包含的文件。
c, taglib指令: 导入jsp标签
eg:<%@taglib uri="http://java.sun.com/jsp/jstl/core"
prefix="c" %>
其中,
uri(Uniform Resources Identifier-统一资源标识符)属性标示:
标签文件的命名空间
prefix属性表示命名空间的前缀
4)隐含对象
a, out
b, request
c, response
d, session
e, application: 即ServletContext对象
f, exception: 只有当isErrorPage=true时,才能使用,用于获取
异常信息。
g,pageContext: 容器会为每一个jsp实例(jsp对应的那个servlet
对象)创建唯一的一个符合PageContext接口要
求的对象,称之为page上下文。
作用1:
绑订数据:
setAttribute,removeAttribute,getAttribute
作用2:
提供了相应的方法来获得其它八个隐含对象:
eg:在自定义标签类showtime.java中,通过PageContex对
象获取JspWriter对象(就是out):
PageContext pctx = (PageContext)getJspContext();
JspWriter out = pctx.getOut();
h, config: ServletConfig实例,通过
config.getInitParameter(String string)获取初始化参
数。
i, page: jsp实例本身(很少用到)。
5)注释
a, <!-- 注释内容 -->:允许注释的内容是java代码,如果是
java代码,会被执行,执行的结果不会显示在浏览器端(但是在
浏览器查看源代码,可以看到被注释的内容)。
b, <%--注释内容--%>:注释的内容不能够是java代码。如果是
java代码,会被忽略。注释的内容不会显示在浏览器端。
(并且在浏览器查看源代码,看不到被注释的内容)。
eg:<body style="font-size:30px;font-style:italic;">
系统时间:<!-- <%=new Date()%> --><br/>
系统时间:<%--<%=new Date()%> --%>
</body>
html注释方法:<!--html的注释-->
xml注释方法:<!--xml的注释-->
css注释方法:/*css的注释*/
js的注释方法://js的单行注释,/*js的多行注释*/
jsp特有注释:<%--注释内容--%>
6)活动元素
a,什么是活动元素?
jsp实例在运行的时候,通知容器做一些处理。
b,<jsp:forward page=""/>:转发
c, <jsp:include page=""/>:调用另外一个jsp,这两个jsp的运行
结果最后会合并。
d, <jsp:userBean id="user" scope="request"class="bean.User">:
容器先查看scope指定的范围里面是否有
id属性指定的对象(
比如 request.getAttribute("user"),其中scope
可以设置为request,session,application,page),
如果有,则返回;如果没有,则创建该对象并
且绑订。
<jsp:setProperty name="user" property="name" value="tom">
给bean的属性赋值。
<jsp:getProperty name="user"
property="name">
读取bean的属性
(3)jsp是如何执行的?
step1, .jsp文件先转换成.java文件
html ----> service方法里,使用out.write输出。
<%.....%> ----> service方法里,照搬。
<%=...%> ----> service方法里,使用out.print输出。
<%!....%> ----> 给servlet添加新的属性或者方法。
step2, 容器会调用servlet来处理请求。
36、jsp标签与el表达式
(1)jsp标签是什么?
sun公司制定的一种技术规范,用来将jsp页面中的java代码使用类似
于html当中的标记来替换的一种技术。这样做的目的,是为了使jsp页面
更好维护以及更好的测试。
因为直接在jsp源文件里面写java代码,不方便代码的维护(比如,将jsp
交给美工去修改就很不方便),所以,sun公司制订了jsp标签技术的规范,
通过jsp标签(类似于html标签,比如div)来代替java代码,这样,jsp源文
件里面就不再有java代码了,页面会更简洁,维护也更方便。
(2)el表达式是什么?
是一套简单的计算规则,用于给jsp标签的属性赋值,现在el表达式也可
以脱离jsp标签直接使用,即直接输出。
(3)el表达式的使用
1)获取绑定数据以及访问bean的属性
获取绑定数据:
${user}容器依次从
pageContext,request,session,application中查找(即调用
getAttribute方法)绑订名为"user"的对象。
访问bean的属性:
方式一: ${user.name}: 容器依次从
pageContext,request,session,application中查找(即调用
getAttribute方法)绑订名为"user"的对象,然后调用该对象的
"getName"方法并输出。
${user.name}相当于:(Object)getAttribute(“user”).getName();
注意:
a,依次:如果找到了,则不再向下继续查找。如果最后都找
不到,则输出空字符串("")。
b,如果getName方法不存在,会报错。
c,如果要指定查找范围,可以使用
pageScope,requestScope,sessionScope,applicationScope,比如:
${sessionScope.user.name}
方式二: ${user["name"]},第二种方式,允许[]
里面出现变量,也可以允许出现从0开始的下标,
用来访问数组中的某个元素。
2)获得请求参数值
${param.name}:
等价于 request.getParameter("name");
${paramValues.city}:
等价于 request.getParameterValues("city");
3) 进行一些简单的计算,计算结果可以直接输出,
也可以给jsp的标签的属性赋值。
a, 算术运算: "+","-","*","/","%"。要注意,"+"操作不能够连接字符
串,只能求和。
${user.id+1}相当于${user.id}+1
${1 + “2”} =3
b,关系运算: "==","!=",">",">=","<","<="。
c,逻辑运算: "&&","||","!"。
d,empty运算:用来判断集合内容是否为空,或者是否是一个空字符串。
以下四种情况,结果为true:
空的字符串
空的集合
值为null
找不到对应的值
(4)jstl标签(java standard tag library,java标准标签库)
apache将一些标签捐献给了sun,sun将其命名为java standard taglib。
1)编程步骤
step1,将.jar文件拷贝到WEB-INF\lib下
standard.jar jstl.jar
step2,使用taglib指令引入要使用的标签。
2)核心标签
a, if标签
<c:if test="" var="" scope="">
</c:if>
test属性:当值为true时,执行标签体的内容。
test属性可以使用el表达式来赋值。
var属性:指定一个绑订名称
scope属性:指定绑订的范围:
("page","request","session","application")
eg1:<c:if test="${1>0}">
1比0大
</c:if>
输出结果为:1比0大
eg2:m输出男,f输出女
gender:
<c:if test="${user.gender =='m'}" var="rs" scope="request">男
</c:if>
<c:if test="${!rs}">女</c:if>
b,choose标签
用于执行分支,当某个条件满足时执行某一个分支,每个分支条
件用when标签标示
<c:choose>
<c:when test=""></c:when>
...
<c:otherwise></c:otherwise>
</c:choose>
when必须要放在choose标签里面,可以出现
一次或者多次,otherwise只能出现0次或者1次。
test属性:当值为true时,执行标签体的内容。
eg:
gender:<c:choose>
<c:when test="${user.gender == 'm'}">男</c:when>
<c:when test="${user.gender == 'f'}">女</c:when>
<c:otherwise>未知</c:otherwise>
</c:choose>
c, forEach标签
用来遍历一个集合
eg1:
在servlet中:request.setAttribute(“userList”,user);
<c:forEach items="${userList}" var="user" varStatus="s">
<tr class="row${s.index % 2 + 1}">
<td>${s.index}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${s.count}</td>
</tr>
</c:forEach>
eg2:
<c:forEach var="p" begin="1" end="5">
<p>Hello</p>
</c:forEach>
将打印5行Hello。
常见jstl标签:
a. <c:if test="" var="" scope="">
test属性: 当值为true,执行标签体的内容,为false,则不执行。
var属性: 指定一个绑订名。
scope属性: 指定一个绑订范围。
var属性和scope属性用于将test的结果绑订到指定的对象
(pageContext,request,session,application)上。
b. <c:choose>
用于分支,当某个条件满足,执行某一个分支。每一个分支条件用when标签来表示。
<c:when test="">
可出现多次,只用于<c:choose>
test属性: 当值为true,执行标签体的内容
<c:otherwise>
只出现1次,只用于<c:choose>
当其它分支都不满足条件,则执行该标签体的内容。
c. <c:forEach var="" items="" varStatus="">
用于遍历集合items属性:指定要遍历的集合。
var属性指定一个绑订名,jsp引擎会从集合当中取一个对象,绑订到 pageContext对象上。
varStatus属性:指定一个绑订名,对应的绑订值是一个java对象,封装了
遍历时的一些信息,包括当前遍历的对象的下标(index)以及 是第几次(count)遍历。
d. <c:url>
当用户禁止cookie以后,会自动在地址后面添加sessionId。
当使用绝对路径时,会自动在地址前添加应用名。
value属性:指定地址。在表单提交、链接当中,可以使用该标签。
e.<c:set var="" scope="" value="">
绑订一个对象到指定的范围。
value属性: 绑订值。
f.<c:remove var="" scope="">
解除绑订
g.<c:catch var="">
处理异常,会将异常信息封装成一个对象,绑订到pageContext对象上。
h.<c:import url="">
url指定一个jsp文件的地址,jsp会在运行时调用这个jsp。
i.<c:redirect url="">
重定向到另外一个地址。url属性指定重定向的地址。
j.<c:out value="" default="" escapeXml="">
用于输出el表达式的值。
value属性: 指定输出的值
default属性:指定缺省值。
escapeXml属性:设置成true,会将value中的特殊字符替换成相应的实体。缺省值就是true。
3)jsp标签的运行过程:
容器依据命名空间找到(从WEB-INF下,或者jar文件里面的
META-INF下查找)标签的描述文件(.tld文件),然后依据标签
的名称找到标签类,接下来将该标签类实例化,最后调用
该实例的相应的方法。
(5)自定义标签(使用简单标签技术)
step1,先写一个java类,继承SimpleTagSupport类。
step2, 在doTag方法(override SimpleTagSupport的doTag方法)里面,
编写处理逻辑。
step3, 在.tld文件里面,描述标签。可以参考c.tld。
注意:
<body-content>的值可以有三个,分别是:
empty: 该标签没有标签体。
scriptless: 该标签可以有标签体,但是,标签体的内容不能够是java
代码(<% %>,<%= %>,<%! %>)。
JSP:该标签有标签体,内容可以是java代码。
只有复杂标签技术支持该值,简单标签技术只支持
empty和scriptless。
如何在javaee5.0以上版本使用jstl和el表达式。
j2ee1.4: servlet2.4
javaee5.0: servlet2.5
tomcat5.5实现了servlet2.4
tomcat6.0实现了servlet2.5
方案1:使用tomcat6.0或者以上版本。
方案2:也可以继续使用tomcat5.5,如果使用el
表达式,要使用<%@page isELIgnored="false"%>,
如果要使用jstl标签,需要将jstl-1.2.jar文件拷贝到
WEB-INF\lib下。
37、mvc (model,view,controller)
(1)什么是mvc?
是一种软件架构的思想,将一个软件的组成部分划分成三种不同类型的模块,分别是:
模型(用于封装业务逻辑,包括业务数据和业务处理逻辑,由JavaBean组件(比如实体类,DAO,Service)实现),
视图(负责显示界面、与用户交互,处理表示逻辑,一种是展示数据,另一种是接受数据,由jsp组件实现),
控制器(用于控制流程,协调模型与视图,由Servlet、Filter组件(比如之前的ActionServlet)实现)。
使用mvc的最主要的原因是为了实现模型的复用:即模型只需要开发一次,模型不关心处理的结果如何展现,模型将结果交给不同的视图,由视图来展现这些数据;另外,可以利用不同的视图来访问同一个模型。
(2)如何使用mvc?
所有请求先发送给控制器(一般使用servlet或者filter来实现),控制器
依据请求的不同来调用相应的模型(使用java类来实现)来处理;模型将处
理结果交给控制器,控制器选择合适的视图(一般使用jsp来实现),视图将
处理结果以合适的方式展现给用户。
(3)MVC的优点:
企业程序更强调结构灵活,易于扩展和升级。所以广泛选用MVC模式开发。
(4)MVC的缺点:
使用mvc,会增加代码量,也会增加软件设计的难度,相应的开发成本也会增加。
网上申请贷款
客户端: 用户输入帐号(accountNo),
贷款金额(amount),点击提交。
服务器:
step1,检查帐号是否存在,不存在,提示用户,
否则,进行下一步。
step2, 检查余额是否满足(amount < balance * 10)
其中,balance是对应帐号上的余额。如果不满足,
提示用户,否则进行下一步。
step3, 生成一个序列号,保存到数据库,并且
提示用户记录该序列号,去柜台办理取款的手续。
create table t_account(
id int primary key auto_increment,
accountNo varchar(20) unique,
balance double
);
insert into t_account(accountNo,balance)
values('62258810',1000);
以上的"servlet&jsp经典总结"是我在学习servlet和jsp时的个人学习笔记,今天把她晒出来,希望与大家一起分享