1、servlet技术是基于Request-Response编程模型----HTTP协议也是基于请求响应模式
因此servlet技术可以用来开发基于HTTP的web应用程序
学习servlet,首先要阅读javaee的API----应用程序接口 实现这些接口的类的使用
2、servlet快速入门:
1)、编写web project
2)、写个class继承HttpServlet
3)、在web.xml中配置servlet程序,也就是虚拟访问路径
**用户在浏览器上可以通过这个路径,访问你的servlet程序**
3、覆盖doGet和doPost方法,进行输出
*servlet可以动态生成 网页文件*
执行过程:
1)、用户在客户端发起url请求:http://localhost/day05/Hello----web.xml/Hello 映射Helloservlet程序
2)、用户提交请求时get方式提交 执行HelloServlet的doGet方法,如果是post方式提交,就执行HelloServlet的doPost方式提交。
4、servlet运行原理:
编写的servlet没有main函数-----Tomcat服务器中的主程序来调用servlet程序执行
间接实现Servlet接口:
servlet是个接口,我们在写servlet程序的时候,要实现这个接口,但是如果直接实现这个接口的话,
我们要实现servlet接口中的方法,这不利于我们的开发,因此,我们可以直接继承实现了servlet接口的
类即可,首先有个类GenericServlet直接就实现了Servlet,并且GenericServlet类中还添加了不少的方法,
但是在实际开发中,我们并没有去继承GenericServlet接口,而是实现了GenericServlet的子类HttpServlet
这个类。在HttpServlet类中,又增添了不少方法,方便我们开发。
5、servlet接口的提出,为了解决基于请求-响应模型数据处理(并没有涉及与HTTP相关的API)
接口servlet---接口servletResponse---接口httpServletResponse,接口在一级一级的继承。
接口servlet的实现类-------GenericServlet类-------------HttpServlet类。
6、servlet生命周期:
void init(ServletConfig config)//负责servlet对象的初始化,只在第一次调用服务的才初始化;
void service(ServletRequest req,ServletResponse res)//提供服务方法,只要是在servlet对象被销毁
之前就是之前产生的一个servlet对象一直在调用service方法(服务);
void destroy()//销毁,在重启或者关闭服务器的时候才执行销毁方法;
结论:
1、init方法 ,在浏览器第一次访问servlet程序时被调用(只被调用一次);
2、每次请求,在服务器内部都会产生一个单独线程,执行servlet对象的service方法。
3、服务器正常关闭或者重启时调用servlet的destroy方法。
7、servlet对象是Tomcat服务器创建的,每次服务器调用servlet的service方法时,都会为该方法创建Request
对象和Response对象。
8、servlet中的service方法和HttpServlet中的doGet、doPost的区别?关系?----要看HttpServlet源码
在HttpServlet代码实现中,根据请求方式的不同,调用相应的doXXX方法.
9、之前我们的servlet对象都是当用户发出请求的时候才创建出来,现在我们可以配置servlet随服务器的
启动就进行初始化。-----<load-on-startup>
**<load-on-startup>中间可以是数字</load-on-startup>-----一般是0--9,0的优先级最高。
10、我们在写servlet的时候不需要去覆盖service方法,因为我们已经继承了HttpServlet,这个类已经
帮我们实现了service方法,而service方法内又调用了doGet和doPost方法,因此,我们只需要去重写
doGet和doPost方法。
还有就是,如果我们直接实现了servlet接口的话,我们要实现接口中的所有方法,其中有Init(初始化)
方法,我们只需要去覆盖无参数的构造方法,不必去覆盖有参数的构造方法,因为有参数的方法内部调的
还是无参数的方法。
11、一个servlet可以配置多个url-pattern
URL配置格式三种方式:
1)、完全路径匹配(以 / 开始) 例如:/hello
2)、目录匹配:(以 / 开始) 例如:/abc/* 或者是 /*
3)、扩展名匹配(一定不能以 / 开始) 例如:*.do *.action
典型错误:/*.do 不能这么写!!!
优先级:完全路径匹配>目录匹配>扩展名匹配
* . :代表当前的目录,也可以使用 ./ 来表示;
* .. :代表上一层目录,也可以 ../ 来代表。
如果改项目名称的时候,不仅要修改文件夹的名字,还要修改properties里的webroot名字!!!
12、Init方法:servlet的初始化。
学习这个方法,void init(ServletConfig config)
1)、创建一个servlet
2)、在web.xml文件的<servlet>标签内,通过<init-param>标签来为servlet配置初始化参数。
<init-param>
<param-name>ZUA</param-name>
<param-value>郑州航院</param-value>
</init-param>
13、在servlet程序中通过servletConfig对象,获得ZUA对应的数据。
String getInitParameter(String name)----获得指定param-name的value值
Enumeration<String> getInitParameterNames()----获得所有的param-name值
要想在doGet和doPodt方法中获得servlet的初始化参数,你可以这么做:
将ServletConfig对象保存成实例成员变量:在Init方法中写:
private servletConfig config;
然后让,this.config=config;就OK了。
然而GenericServlet类已经将servletConfig保存成成员变量-----因此在子类中通过getServletConfig()方法
获得servletConfig对象。
结论:子类servlet不需要覆盖 init(ServletConfig),只需要通过GenericServlet中的getervletConfig()
获得servletConfig对象。
14、ServletContext是servlet上下文对象。
每个工程都会创建ServletContext对象,这个对象代表当前web工程
操作ServletContext ,必须通过ServletConfig获得对象。
应用:
1、获得整个web应用初始化参数
2、实现全局数据共享
3、实现服务器端转发功能
4、读取web工程资源文件
15、获得web应用的初始化参数和ServletConfig对象的不同?
ServletConfig配置的参数只对servlet有效;如果配置参数,让所有的servlet都可以访问,
就要用ServletConfig了。
1)、在xml文件中写下面这些:
<context-param>
<param-name>Hobby</param-name>
<param-value>唱歌</param-value>
</context-param>
你在当前工程的所有Servlet中都可访问到这些初始化参数。
2)、通过ServletContext在多个servlet之间实现数据共享
在ServletContext中保存站点访问次数,每当一个用户访问站点,次数+1;
在servlet初始化过程中,向servletContext保存访问次数------------servletcontext对
象的setAttribute();
访问次数----放到servletContext中,-----所有的servlet 都可以访问
在servletContext中保存的数据,在所有的servlet中都可以访问,全局共享的。
3)、通过ServletContext完成服务器端程序的转发(不怎么常用)
转发:服务器端在处理客户端的请求时,需要多个服务器程序同时处理,需要采用转发操作。
重定向:服务器进行处理后,需要通知客户端访问下一个目标程序,继续处理。
二者区别:转发是在服务器内部进行的,重定向是服务器通知客户端进行的。
4)、通过ServletContext读取资源文件(web工程中必须将文件路径转换为绝对磁盘路径)
注意:这里的路径必须是绝对磁盘路径,还有就是,用servlet读取文件的时候,只能读取部署到
Tomcat中webapps中的文件,对应于在我们的项目中也就是只能读取WebRoot下和src下的文件,src中
的文件部署到Tomcat中在WEB-INF的classes目录下。
我们要用getServletContext().getRealPath(“/XXX”)来获得绝对磁盘路径。/ 就代表WebRoot
因为WEB-INF/classes非常特殊(存放.class文件目录),被类加载器加载,可以通过Class类对象读取
该目录下的文件。
String filename = c.getSource("/a1.txt").getFile();-----------/ 就代表/WEB-INF/classes
这种通过类对象读取文件的操作方法是通用的。。。。
5)、缺省servlet:处理其它servlet都不处理的请求
这个也有好处:你可以获得客户端请求的文件路径----文件名,然后你可以通过ServletContext来
拿到它的绝对磁盘路径(如果存在的话),之后就是通过文件流来读取文件并输出了。
16、Servlet学习的两条主线:
--HTTP协议
--Servlet生命周期
主要学习三个方法:
--init()
--service()
--destroy()
service方法有两个参数:ServletRequest和ServletResponse
service(ServletRequest req, ServletResponse res)
在实际开发过程中,不需要覆盖service方法--------因为它的实现类HttpServlet会根据请求方式来自动
调用doGet方法和doPost方法,而这两个方法的参数是HttpServletRequest和HttpServletResponse。
17、客户端的每次请求都会创建request和response对象,然后被传到service()、doGet()和doGet()方法中。
response常用的API:
setStatus----设置状态码
setHeader---设置头信息
getOutputStream---获得字节流
getWrite----获得字符流
常用状态码:
200---请求处理成功
302---客户端重定向
304---客户端访问资源没有被修改后,客户端访问本地缓存
404---访问的资源不存在
500---服务器内部出错
18、案例一:通过302 + Location 头信息实现页面重定向效果
response.setStatus(302);
response.setHeader("Location", "/day06/welcome.html"); // 相对路径 和 绝对路径
19、头信息存在多个值
Accept-Encoding: gzip, deflate --- key:value1,value2
response.addHeader 用于设置响应头有多个值 ------ 不常用
重点:setHeader
20、为什么sun公司要退出JSP技术?
servlet生成网页比较复杂,本身不支持HTML语法,html代码需要通过response输出流输出,JSP支持HTML
语法,生成HTML更加方便。
21、JSP技术和servlet技术的区别和关系?
JSP和servlet技术都是用来动态生成网页的, servlet不支持HTML语法,生成网页麻烦,JSP支持HTML
语法,生成网页方便,JSP运行时翻译成servlet执行,其实JSP就是servlet技术。
22、JSP运行原理是怎样的?
客户端访问JSP文件,服务器读取JSP文件,根据JSP生成servlet,然后servlet编译运行,生成动态网页。
23、JSP常见的嵌入标签
<%! %>--定义翻译后servlet程序的 全局变量或全局方法、内部类
<%= %>--表达式 输出内容到浏览器 效果等同于out.print
<% %>--脚本代码块,嵌入java运行代码----不翻译
****************************************************************************************
24、JSP翻译servlet,存放在tomcat/work目录下
JSP翻译servlet页面时,所有的HTML被翻译为out.write输出
25、JSP的注释:(3种)
JSP注释:<%-- --%>
这个JSP注释只是在JSP源码中显示,当JSP被翻译成servlet时,在servlet中是不会显示的。
java注释:/** */文档注释 /* */多行注释 //单行注释
/** */文档注释可以生成javadoc用来注释你的包、类、成员变量、成员方法。
这类注释会在JSP翻译为servlet时,也在servlet中存在,但是执行的时候是被忽略的(毕竟只是注释)
HTML 注释:<!-- -->
在jsp翻译为servlet时,会被翻译为out.write ,在生成html页面源码中该注释也是存在的。
结论:JSP注释在翻译时消失,java注释在运行时消失,HTML注释不消失。
HTML注释是不能阻止jsp或者java代码执行的。
26、JSP指令(JSP Directive),语法<%@ 指令名称 属性=值 属性=值...%>
page指令--用来定义JSP文件的全局属性---<%@ page 属性=值>
language 只能是java
extends 来指定JSP翻译后的servlet继承的父类,这个属性一般不设置,如果非要设置,继承类必须
是servlet的实现类。
session 定义JSP中是否可以直接使用session隐含对象
如果设置为true,在jsp翻译为servlet时生成以下两句代码:
HttpSession session = null;
session = pageContext.getSession();
**如果JSP中想使用HttpSession对象,使用session属性默认值true。
import JSP翻译成servlet时导入的包,默认导入的包有以下三个:
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
还有个jre默认的包:java.lang包
如果是需要其他的包,就用import导入相应的包。
isELIgnored 设置JSP是否执行EL表达式的。 一般就是默认值false
27、通过contentType和pageEncoding来设置JSP的页面编码
contentType ---在servlet生成HTML,由服务器传输给浏览器时采用的编码
pageEncoding ---是jsp源文件代码存储到硬盘上的编码集
二者的编码格式可以不一样,但是要深刻理解它们之间到底是什么关系。
28、通过errorpage和isErrorPage控制JSP页面错误时的跳转
设置错误友好界面---当页面发生错误,不应该让用户看到一个代码错误页面,而是一个比较有好的界面。
可以通过errorpage指定,当页面发生错误跳转到哪个页面。
在错误友好页面中,可以通过设置isErrorPage属性,来获得错误原因。
--但是在实际的开发中一般是不用上述的;
--错误页面的第二中处理方式:配置web.xml
<error-page>
<error-code>500</error-code>
<location>/demo2/gooderror.jsp</location>
</error-page>
配置完这个时候,所有的500错误页面,都会跳转到这个gooderror.jsp页面。当然,你也可以配置
其它的错误信息页面,404,302.。。。
29、include指令,用来静态包含一个页面---主要就是将页面的公共部分提取出来,通过include完成页面布局。
语法:<%@ include file="文件名"%>
包含的时候是把被包含页面的整个内容都包含进来,因此,被包含页面只需要是HTML片段就OK了,否则
包含进来后,整个页面会显得很乱。
静态包含:包含目标文件的源代码,源代码合并到一起,一起执行,不管包含几个jsp页面,都只
生成一个servlet程序。
30、taglib指令,用来在jsp页面引用标签库文件
**定义标签作用,为了简化jsp页面开发
**通过taglib指令引入jstl标签库--语法:<% taglib uri="" prefix="" %>
uri--定义标签,唯一命名空间
prefix--命名空间前缀
引用jstl时,在导入jstl.jar中,METE-INF/c.tld
<shortname>c</shortname>------就是prefix属性
<uri>http://java.sun.com/jsp/jstl/core</uri>---就是uri属性
31、JSP的九个内置对象:
什么事内置对象??
在JSP翻译为servlet代码时,有些对象默认已经创建好了,这类对象可以在jsp中直接使用。
request-----------------------HttpServletRequest--请求对象
response----------------------HttpServletResponse--响应对象
session-----------------------HttpSession--会话对象
application-------------------ServletContext--web应用全局唯一对象
page--------------------------this(HttpServlet)
pageContext-------------------PageContext
out --------------------------JspWriter
config------------------------ServletConfig--初始化数据
exception---------------------Throwable(所有异常父类)--当页面是个错误页面,用exception获取异常信息
32、page代表当前jsp生成的servlet对象
**page是object类型,只能使用object中的方法----这个对象在开发中不建议使用
**page如果非要使用,可以将其强转为其它类型的对象(HttpServlet)
33、servlet有几种数据范围? 三种---request、session、servletContext
jsp在servlet三种数据范围的基础上又新添page数据范围----jsp有四种数据范围:request、session、page、application
**page数据范围存放数据,只在当前jsp内有效。
34、pagecontext代表当前页面上下文
1)、向page范围存取数据
findAttribute 依次在page、 request、session、application 四个数据范围进行数据查找
2)、pagecontext用来获得其它八个隐含对象
35、out对象功能是向浏览器输出信息,是jspWriter类型,内部使用PrintWriter实现,拥有独立缓冲区。
out对象的创建,是通过pagecontext获得的,在创建pagecontext对象时需要指定out缓冲区的大小和是否
自动刷新(flush)
通过page指令可以设置buffer(缓冲区大小)、autoflush(是否自动刷新)。
out向浏览器输出内容和response.getWriter()向浏览器输出内容的区别?
out输出的时候,要先进入response.getWriter()缓冲区,然后再向浏览器输出内容。
36、jsp标签Action(jsp动作)
jsp中的六个动作标签:<jsp:useBean> <jsp:setProperty> <jsp:getProperty>----这三个与javabean操作相关
<jsp:include> <jsp:param> <jsp:forword>
<jsp:include>---效果等效于request.getRequestDispatcher().include
功能等价于<%@ include%>
原理:动态包含
语法:<jsp:include page="文件路径" />
动态包含和静态包含的区别??
<jsp:include>标签:动态包含,在index servlet执行时完成包含动作,包含结果是目标jsp翻译servlet
生成的html页面,每个被包含的jsp会翻译成servlet单独执行。
<%@ include file=""%>:静态包含,在jsp翻译为servlet时,执行包含动作,包含结果是将目标jsp翻译的
servlet和index.jsp翻译的servlet一起执行。
<jsp:forword>---等效于request.getRequestDispatcher().forward
<jsp:param>----用来传递参数,但是这种方式基本上被淘汰了。
如果真要传参数,我们最多的是用setAttribute,就好了。
37、EL表达式语言,来自民间,servlet2.4之后EL被纳入官方规范
功能:
1)、EL获得JSP四个范围中保存的数据(访问javabean的属性)
2)、EL表达式支持运算
3)、EL内置11个对象-----web开发常用对象
4)、EL调用java方法
EL是javaee1.4版本才被纳入规范,javaee1.3及以前版本默认对EL不解析
**如果想javaee1.3以及以前版本解析EL----设置page属性isELIgnored=false
38、使用EL获得jsp四个范围的数据
这么使用(指定数据范围):${pageScope.属性名称}、${sessionScope.属性名称}、
${requestScope.属性名称}、${applicationScope.属性名称}
如果不指定数据范围:${属性名称}----调用pageContext.findAttribute在四个数据范围内依次查找
查找,如果不存在,返回空串"",不是null
传统的用法:<%=request.getAttribute(属性名称)%>
39、EL表达式(Expression Language) 11个内置对象
pageScope requestScope sessionScope applicationScope 四个数据范围,用来取值
pageContext 当前jsp上下文 ----- ${pageContext.request.contextPath }
${param.name} 等价于 request.getParameter("name")
${paramValues.hobby} 等价于 request.getParameterValues("hobby")
${header.referer} 等价于 request.getHeader("referer")
${headerValues["Accept-Encoding"]} 等价于 request.getHeaders("Accept-Encoding")
${initParam.name} 等价于 getServletContext().getInitParamter("name")
40、必须掌握cookie隐含对象写法
Cookie[] cookies = request.getCookies();
if(cookies==null){
out.println("cookie不存在!");
}else{
for(Cookie cookie : cookies){
if(cookie.getName().equals("address")){
out.println(cookie.getValue());
}
}
}
使用EL获取cookie: : ${cookie.address.value }
41、EL获取数据值,经常需要对取得的值进行处理------这里就用到了EL函数
步骤:1、编写java类,提供static方法 2、编写tld文件,在tld文件中对函数进行定义描述。
sun公司在JSTL中提供了一套EL函数库,这套函数在导入jstl的jar包后,可以直接使用。
用法很简单:1)、导jar包 2)、在jsp页面中导入函数--这句很固定:<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
42、JSP开发模式:
Model1:JSP(负责页面显示,跳转,调用JavaBean)+JavaBean(封装和处理数据)
Model2: JSP(只是页面显示)+JavaBean(数据的封装、处理)+Servlet(控制整个程序处理流程,调用JavaBean进行数据处理,调用JSP进行页面显示)
43、架构模式:MVC----Web应用需要三个部分组成
1)、Model(模型):封装数据,处理数据
2)、View(视图):用来页面显示
3)、Controller(控制器):控制程序的处理流程
然而 ,我们的JSP+JavaBean+Servlet这种开发模式刚好符合MVC架构。
44、什么是JavaBean?
1)、是一个java类
2)、必须存在无参数的构造方法
3)、所有成员变量都是private
4)、如果想让private成员变量被外界访问,可以提供public的get和set方法。
在jsp页面中写入这么一句话:
<jsp:useBean id="person" scope="page" class="demo2.Person"></jsp:useBean>
它在服务器的work/Catalina/jsp01/org/apache/jsp/demo2/demo1_jsp.java中会自动创建一个对象,
代码如下:(synchronized---同步的意思)
demo2.Person person = null;
synchronized (_jspx_page_context) {
person = (demo2.Person) _jspx_page_context.getAttribute("person", PageContext.PAGE_SCOPE);---获得page范围的person属性
if (person == null){
person = new demo2.Person();
_jspx_page_context.setAttribute("person", person, PageContext.PAGE_SCOPE);--将创建的person对象放入page范围。
}
}
代码效果:从page范围返回获得person对象,如果不为null,直接使用,如果为null,就创建person对象。
useBean就相当与创建了Person对象。
下面这两个分别是对对象的属性进行赋值和取值:
<jsp:setProperty property="" name=""/>
<jsp:getProperty property="" name=""/>
setProperty的特殊用法:(详见jsp01/demo2/..)
<jsp:setProperty property="*" name="p"/>---会根据请求的数据自动封装person属性