一,Web服务器的历史
CGI(common gateway interfact)
Cgi模式
Cgi模式的特点,是将服务端的动态资源基于进程方法来运行。由于进程的执行非常耗费时间,且内存空间浪费。所系效率及其低下。
FastCGI
所谓的fastCGI的模式其实就是在当前的CGI模式中添加的了一个pooling的概念,在服务器启动时初始化固定的进程来提高处理客户端请求的速度,但是该方法治标不治本。
二,servlet技术的特点
与传统的CGI模式不同,servlet运行模式更改为单进程多线程的模式。
单进程:服务器
多线程:服务端的servlet
三,servlet的继承结构
Http协议
1、单向性:只有发送请求了,才会有相应产生。
2、无状态:协议本身并没有状态的记录,当客户端多次访问服务端时,服务端并不会知道 你曾经访问过他。
基于http协议我们能够采用哪些方式来发送请求呢?
DOGET
DOPOST
DOHEAD
DODELETE
get与post区别:
1.get方式提交表单表单中的数据会在地址栏中显示。而post方法则不会。
2.get方式提交表单长度是有限制的512字节,而post理论上是无限的。
3.get方式提交表单会在http数据包中的第一行出现,而post在空一行的body中出现
4.get方式永远是已字符方式提交。而post既可以已字符也可以已字节。
五,http数据包
get
post
手动编写第一个servlet
1、编写servlet代码
1)你的servlet必须要继承HttpServlet。在你的servlet中添加doGet或者是doPost。
2)doGet或者是doPost方法中都会含有两个入参:
HttpServletRequest
HttpServletResponse
3) 该方法需要抛出两个异常:
IOException
ServletException
4)通过HttpServletResponse对象获取向客户端输出的字符流对象
PrintWriter pw = response.getWriter();
5)通过调用PrintWriter中的printl方法完成内容的输出
6)导包:
我们需要将
HttpServlet ,HttpServletRequest,HttpServletResponse,IOExcetpion.ServletException这些对象的包import进来
1
2
3
|
import javax.servlet.http.*; import java.io.*; import javax.servlet; |
7)你的servlet至少需要在一个包下(切记)
Package com.bjsxt;
8) 编译你所写的servlet。在编译时需要注意,由于我们的servlet中时用到了javaEE平台下类。所以需要指定javac去什么位置找相应的类库。
9) 将编译好的servlet的class文件部署容器中。
1.需要在webapps目录下建立一个目录
2,在项目的目录中必须要包含一个名称为:WEB-INF的目录
3在WEB-INF的目录中 必须包含一个classes目录
4.按照servlet中所定义的正确的包名来建立目录,将class文件拷贝到相应的目录中。
5.需要在WEB-INF的目录中与classes目录同级建立一个名称为web.xml的文件
Web.xml:项目部署描述文件。在该文件中配置servlet的相关信息。
6.编写web.xml完成对servlet的配置。需要配置两个节点
<servlet>
<servlet-mapping>
详细配置如下
1
2
3
4
5
6
7
8
9
|
<servlet> <servlet-name>suibian</servlet-name> <servlet- class >com.bjsxt.HelloWorld</servlet- class > </servlet> <servlet-mapping> <servlet-name>suibian</servlet-name> <url-pattern>/suibian. do </url-pattern> </servlet-mapping> |
<servlet-name>::给servlet起个别名,叫什么都行。只要在同一个web.xml中不重复就可以。
<servlet-name>::配置当前 给哪个servlet起别名的servlet的全名。
<servlet-mapping>:配置servlet与uri的映射
<servlet-name>:为哪个servlet中的servlet做uri的映射配置
<url-pattern>:为这个servlet所配置的访问的uri是什么.注意:必须uri中必须要含有/
2、运行servlet
只要启动tomcat,在客户端浏览器中输入为servlet所配置的uri就可以访问了
一、servlet的生命周期
servlet接口中定义了作为一个servlet在整个生命周期中应该拥有三个阶段
1, 初始化
2, 服务
3, 销毁
servlet的生命周期是由容器管理的
servlet的生命周期:
简化版:适用于笔试的时候
1,servlet的生命周期是由容器管理的(这句话非常重要!!!!!!)
2.他分别经历三个阶段:初始化 服务 销毁
如果是面试可以展开谈一谈:
1,把笔试上的东西 先说一边。
2.当有第一个客户端浏览器访问这个servlet时,容器会将这个servlet实例化并且调用一次init方法,然后在新的线程中调用service方法,然后容器并不会立即销毁这个对象,当容器在关闭的过程中。会销毁这个servlet对象,但是在销毁这个对象之前会调用一次destroy方法。
如果在销毁这个对象之前 在有一个客户端浏览器来访问这个servlet,那么容器不会再次实例化这个servlet了。而是直接在新的线程中调用service方法。
在eclipse中构建一个servlet
1、创建一个servlet的步骤
第一步
第二步
第三步
2、使用eclipse构建web工程的步骤
第一步 在eclipse中配置tomcat
第二步 创建web工程
第三步 部署项目
一、servlet的作用
1. 获取表单数据
2. 获取浏览器附加信息
3. 处理数据(可以在serlvet中通过调用其他的处理数据方式来完成。如jdbc,rpc,rmi。。。)注意第三点是欠你们的
4. 给客户端产生一个相应
5. 在相应中添加附加信息
二、在serlvet中如何获取表单数据呢?
1.Key=value
String value = getParameter(String key);
2.Key = value& key = value1& key=value2
String[] arr = getPramteterValues(String key);
三、作业
编写一个页面,做用户的数据采集。采集项为:
1、 姓名
2、 年龄
3、 密码
4、 性别
5、 爱好
6、 省份
7、 简介
一、servlet的能力
1, 获取浏览器提交的表单数据
2, 获取浏览器的附加信息
3, 处理数据
4, 给客户端产生一个相应
5, 在相应中添加附加信息
二、获取浏览器提交的表单数据
String value = request.getParameter(String key);
String[] arr = request.getParameterValues(String key);
在获取表单数据时,如果表单数据中含有中文,此时会产生乱码。
乱码解决方式:
1, 通用方式:
1
2
3
4
|
String value = request.getParameter( "username" ); value = new String(value.getBytes( "iso-8859-1" ), "utf-8" ); System.out.println(value); |
2, 解决post提交时所产生的乱码问题
1
2
3
4
|
//注意不能解决get提交表单时的中文乱码问题 request.setCharacterEncoding( "utf-8" ); String value = request.getParameter( "username" ); |
3.解决get提交表单时的乱码问题
需要修改tomcat的配置文件(server.xml)--<Connector>添加URIEncoding="utf-8"
1
2
3
|
<Connector port= "8080" protocol= "HTTP/1.1" connectionTimeout= "20000" redirectPort= "8443" URIEncoding= "utf-8" />
|
文件上传
1,在做文件上传时。需要注意的是,表单的提交方式必须是post的,因为我们需要让表单以字节方式提交,而get只能是字符提交,很显然不适用。
2,需要在form表单中修改请求的头信息。将原来的默认的字符提交修改为字节提交。
修改方式为:在form标签中添加一个属性和值: enctype=”multipart/form-data”
enctype=” multipart/form-data”:该属性表示当前表单为字节格式。服务器接收到该数据包后,发现请求的头部是multipart/form-data时就不会去解析当前的http数据包了。所以,我们也无法使用request.getParameter()去获取表单数据了。
3.在servlet中,如果需要处理表单中的内容。我们需要通过request对象获取通信流,通过对流的对象操作完成相应的表单处理。但是比较麻烦。后期我们会使用apache的专门用于处理文件上传的组件:common-fileupload。欠你们的。
获取浏览器的附加信息
什么是浏览器的附加信息?
所谓的浏览器附加信息其实就是浏览的基本信息。比如:浏览器的品牌,浏览器支持的语言,浏览器支持的文件格式等。
获取方式:
String value = request.getHeader(key);
通过浏览器的附加信息的key获取value
Enumeration enu= request.getHeaderNames();
该方法表示获取附加信息的所有的key返回一个枚举。
1
2
3
4
5
|
Enumeration<String> enu= request.getHeaderNames(); while (enu.hasMoreElements()){ String key =enu.nextElement(); out.println( "<tr><td>" +key+ "</td><td>" +request.getHeader(key)+ "</td><tr/>" ); } |
给客户端产生一个相应
1.为相应设置编码
response.setContentType("text/html;charset=utf-8");
text/html:表示告知浏览器当前返回的相应内容的类型是什么。
charset=utf-8:表示告知浏览器用什么编码格式做相应的数据包的字节到字符的转换。同时用什么编码方式在页面中查看。
2.设置response.setContentType();来改变相应类型
请留意MIME.doc
相应图片
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//将需要给客户端相应的图片读进来 InputStream is = new FileInputStream( new File( "f:/2.jpg" )); byte [] buff = new byte [is.available()]; is.read(buff); //在相应之前必须要设置相应类型 response.setContentType( "image/jpeg" ); //把读进来的图片相应给客户端 OutputStream os = response.getOutputStream(); //字节输出流。而getWriter返回的字符输出流 os.write(buff); os.flush(); is.close(); os.close(); |
文件下载
在servlet中实现文件下载需要注意的地方有两点。
1. 相应类型需要做修改,response.setContentType(“bin”);
2. 在相应中添加附加信息response.addHeader(“Content-dispositation”,”attachment;filename=”aa.jgp””);
3. 在下载时解决文件名是中文时的乱码问题
String filename = new String(filename.getBytes(“utf-8”),”iso-8859-1”);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//将需要给客户端相应的图片读进来 File file = new File( "f:/鲁东大学.jpg" ); InputStream is = new FileInputStream(file); byte [] buff = new byte [is.available()]; is.read(buff); String fileName = new String(file.getName().getBytes( "utf-8" ), "iso-8859-1" ); //在相应之前必须要设置相应类型 response.setContentType( "bin" ); response.addHeader( "Content-disposition" , "attachment;filename="" +fileName+ """ ); //把读进来的图片相应给客户端 OutputStream os = response.getOutputStream(); //字节输出流。而getWriter返回的字符输出流 os.write(buff); os.flush(); is.close(); os.close();
|
关于servlet的线程安全问题
Servlet是一个线程不安全的技术。我们在servlet中定义成员变量时,需要额外注意,如果非要定义成员变量,那么以读取为主。千万不要又读又写。如果真的有这样的需求。加锁拉解决数据安全性的问题。
SingleThreadModel:servlet中提供的一个标识接口,该接口标识实现了该接口的servlet的运行方式会由并行化改为串行化执行。效率及其低下。所以该接口解决线程安全的方式已经过时,不推荐使用了。
Servlet在解决线程安全上更推荐我们使用锁来解决。
Servlet中的常见对象
1. ServletContext
2. ServletConfig
3. Cookie&session
一,servletContext对象
Sevlet上下文对象的作用是:
1,相对路径转绝路径
1
2
3
4
5
6
7
8
|
String path = "/1.jpg" ; //1.获取serlvetcontext对象 ServletContext sc = this .getServletContext(); //相对路径转绝对路径 String realPath = sc.getRealPath(path); File file = new File(realPath); InputStream is = new FileInputStream(file); System.out.println(realPath); |
2,获取容器附加信息
1
2
3
4
5
|
ServletContext sc = this .getServletContext(); response.setContentType( "text/html;charset=utf-8" ); PrintWriter pw = response.getWriter(); pw.println( "Tomcat Server Info: " +sc.getServerInfo()+" 支持Servlet "+sc.getMajorVersion()+" ."+sc.getMinorVersion()); |
3,全局容器
Servletcontext通过两个api完成对他的添加与读取的操作
setAttrbuter(String key,Object value);
Object value = getAttrbuter(Stirng key);
3.1自启动的servlet
所谓 的自启动的servlet表示,该servlet的实例化不依赖于请求,而是依赖于容器。当容器启动时会实例化这个servlet。
如果将一个servlet修改为自启动呢?
在web.xml文件中找到这个servlet所对应的在该节点中添加100 其中100为优先级的标识,他并不是一个时间。当为多个serlvet配置了自启动时,tomcat会根据数值的大小来觉得启动的先后顺序。数值越小的优先级越高。
使用全局容器时需要注意的地方:
千万不要存业务数据。因为ServletContext的生命周期太长了。意味着存放在该对象下的数据也会一直存在,那么我们还需要考虑到数据同步的问题。
4, 读取web.xml文件中的配置信息
配置web.xml
1
2
3
4
|
<context-param> <param-name>key</param-name> <param-value>param-value</param-value> </context-param> |
获取配置文件中的配置信息
1
|
String value = sc.getInitParameter( "key" );
|
servletConfig
用户读取我们在servlet节点中配置的配置信息。注意一个每个servletConfig对象只能去读取在web.xml文件中对于当前这个serlvet的配置信息中的节点中的值。不能夸servler获取。
Web.xml
1
2
3
4
5
6
7
8
9
10
|
<servlet> <description></description> <display-name>ServletConfigDemo</display-name> <servlet-name>ServletConfigDemo</servlet-name> <servlet- class >com.bjsxt.ServletConfigDemo</servlet- class > <init-param> <param-name>ServletConfigDemo-key</param-name> <param-value>ServletConfigDemo-value</param-value> </init-param> </servlet> |
代码
1
2
|
ServletConfig sc = this .getServletConfig(); sc.getInitParameter( "ServletConfigDemo-key" );
|
三,cookie 与 session
Http协议特点:1,单向性。2无状态。
Cookie:是一个依赖于客户端维持回话状态的对象。
Cookie特点:如果我们的程序需要给客户端浏览器返回一个cookie那么这个对象是需要我们自己来创建的。cookie对象的结构为key与value结构。Cookie对象的类型又分为两种1,状态cookie。2,持久化cookie。如果我们需要使用cookie对象向客户端浏览器传递数据,那么数据本身不能是中文。当客户端浏览器请求servlet时,客户端浏览器会将这个服务器曾经写回给他的所有的cookie对象在请求中传递过来。
1、Cookie的类型:
1)状态cookie:状态cookie的特点是浏览器会将该对象保存在运行浏览器的进程中。他的生命周期是谁这浏览器的存在而存在,随着浏览器的消亡而消亡
2)持久化cookie:持久化cookie的特点是浏览器会将这个cookie对象持久化到磁盘中。当cookie设置时间到达时,浏览器就不会在请求中传递这个cookie了。对于保存cookie的文件 我们不需要管理。浏览器自己回来管理这些文件。
如果创建一个持久化cookie呢?其实就是调用cookie对象下的一个api
1
2
|
Cookie c = new Cookie( "first" , "frist" ); //状态Cookie c.setMaxAge( 120 ); //单位为秒 |
2、cookie传值中含有中文的解决方式
1)可以使用加密算法来解决,但是需要注意的是在选择加密算法时一定要选择具有可逆能力的加密算法。
1
2
3
4
|
String value = EncUtil.encrypt( "我是中国人" ); //使用ENCUtil工具类完成加密 String str = EncUtil.decrypt(c.getValue()); //使用ENCUtil工具类完成解密 |
2)可以使用jdk中的URLEncoder与URLDecoder来完成中文的处理。
1
2
|
String str = URLEncoder.encode( "我是中国人" , "utf-8" ); //编码 String str = URLDecoder.decode(c.getValue(), "utf-8" ); //解码 |
3)服务端返回给客户端浏览器时的cookie数量
浏览器能够接受服务端所返回的cookie的数量是有限的,具体多少个和浏览器的品牌有关系。
1. session对象讲解
2. jsp讲解
3. jsp中的原始标签
4. 请求转发与重定向
一,HttpSession
解释:HttpSession对象是可以建立客户端与服务端之间的会话,但是该会话是否建立。取决于我们是否为这个客户端创建HttpSession对象。如果创建了。那么这个HttpSessino就表示当前这个客户端与服务端的会话已经建立。那么Httpsession对象只为这一个客户端服务。
HttpSession的运行原理:
当客户端浏览器访问servlet时,如果执行的代码中执行了request.getSession(true|false),那么此时服务端会根据你给的参数来决定如果建立会话。如果参数给定的是true那么服务器会先去 “账本中”查找看是否有针对这个客户端所对应的HttpSession对象,如果有,则返回给你。如果没有则创建一个新的给你。同时将sessionID通过cookie对象带回给客户端。注意是一个状态cookie。也就意味着,如果浏览器关闭,那么在服务端与该客户端对应的Httpsession也就丢失了。如果给定的参数是false,服务端则会将原来的httpSession返回给你。如果没有,那就拉倒。啥都不给你了。如果调用的是无参的getSession().和给true的含义相同。
HttpSession的生命周期
创建:当有客户端浏览器请求servlet时,如果在servlet中执行了request.getSession()方法时容器才会创建session对象。
销毁:销毁的时间不确定。
1, 通过HttpSession的api来销毁HttpSession对象
Invalidate()销毁session对象
2, 设置HttpSession的失效时间
可以在两个地方设置。
1) tomcat--conf--web.xml
1
2
3
|
<session-config> <session-timeout> 1 </session-timeout> //单位为分钟 </session-config> |
注意:修改tomcat中的web.xml配置session的失效时间是全局性。会对当前这个tomcat中所有的且没有配置session失效时间的项目生效。
2) 修改项目中的web.xml添加对session的超时时间配置
1
2
3
|
<session-config> <session-timeout> 1 </session-timeout> //单位为分钟 </session-config> |
如果是自己的web.xml中配置的,那么仅针对当前这个项目生效。
总结:我们通过session的api可以了解,HttpSession对象是可以为我们做数据保存的。但是,切记:由于Httpsession的生命周期特别恶心,不长不短。所以不建议向HttpSession中存放业务数据。我们一般只存放针对这个客户端的用户登录信息。
2.如何编写一个jsp
在jsp中如果想编写java代码,那么必须要写到特定的标签中。否则容器并不认为你写的内容是java代码。
Jsp什么时候会被容器的jsp引擎编译成一个servlet?
1),当客户端浏览器第一次请求这个jsp时,容器的jsp引擎会将该jsp编译成一个servlet并且运行他。
2),当jsp文件发生改变时,容器的jsp引擎会在此编译这个jsp到一个servlet。
那么jsp提供的能够编写java代码的标签有哪些呢?
1. jsp的三种原始标签。
1) 声明标签:<%! %>在声明标签中所编写的代码,最终会出现在jsp编译成.java源文件的类下出现。
2) 脚本标签:<% %>在脚本标签中所编写的代码,最终会出现在jsp编译的.java的原文件中的 _jspService()方法的方法体中出现。
3) 赋值标签:<%= %>在赋值标签中所编写的代码,最终会被放入到字符的输出流的方法的参数中。所以切记。在使用赋值标签时,该标签中的内容不能包含分号。
2. Jsp的指令标签
<%@ page %> <%@include %>
<%@ page%>中的属性讲解
language="java":告诉jsp引擎当前在jsp中所使用的语言是什么语言。现在只支持java
import="java.util.*":导入什么包
pageEncoding="UTF-8":有两层含义,1,如果你的相应类型是text/html 并且没有设置charset=utf-8时,那么pageEncodig属性里的值会被自动填充到contentType中。但是仅限于是text/html。2.当前页面用什么编码来保存
contextType=:设置jsp的相应类型,该属性中的值最终会被填充到response.setcontexttype()方法中。
extends="":让当前的jsp继承于谁。默认的是从HttpJspBase一般情况下不需要改动
isThreadSafe="true" 线程是否安全的。默认的是不安全
errorPage="error.jsp":一但程序出错了会自动跳转到你给定页面中。
isErrorPage="true":当前页面是否创建异常对象。
session="true":访问当前页面是否创建一个HttpSession对象。默认的是创建一个的。如果不需要将true改为false就可以了。
3. jsp2.0以后的JSTL,EL表达式
4.jsp的动作标签
1. jsp的内置对象
2. 请求转发与重定向
3. Jsp+servlet实战
一,jsp的内置对象(暗对象)
所谓的jsp的内置对象其实就是在jsp中已经为我们提供好了。拿来就可以使用的。
共有9个。
Jsp中 servlet中
request HttpServletRequest
response HttpServletResponse
application ServletContext
session HttpSession(该对象的创建是由page指令标签中的session属性中的值是true还是false来决定是否创建的。)
config ServletConfog(作业了解config对象的使用)
out PrintWriter(JspWriter)
exception Throwable (该对象是否创建取决于page指令标签中的isError属性的值是true还是false)
page
pageContext
二,请求转发与重定向区别
1.请求转发一次请求/响应的过程,而重定向是两次请求/响应的过程
2.请求转发地址栏的地址不变化,而重定向地址会发生变化。
3.请求转发方式可以利用request对象来传递数据,而重定向不能利用request传递数据。
4.如果是插入数据,更新数据,删除数据以后到结果页面应该采用重定向的方式。
三,jsp+servlet实战
对数据做简单的增删改查。