1.Servlet概述.
1.1何为Servlet.
-
Servlet(Server Applet)是一个Java程序,是在服务器上运行以处理客户端请求并做出响应的程序。
1.2JSP和Servlet的区别.
-
Servlet 比 jsp出现早;
-
Servlet是由JAVA代码构成,擅长于流程控制和事务处理,通过Servlet来生成动态网页很不直观;
-
JSP由HTML代码和JSP标签构成,可以方便地编写动态网页;
-
Servlet在Java代码中可以通过HttpServletResponse对象动态输出HTML内容;
-
JSP是在静态HTML内容中嵌入Java代码,然后Java代码在被动态执行后生成HTML内容;
-
JSP是Servlet技术的扩展,本质上就是Servlet的简易方式;
-
JSP侧重于视图,Servlet主要用于控制逻辑。
-
在实际应用中采用Servlet来控制业务流程,采用JSP来生成动态网页。
1.3实现Servlet的三种方式.
-
实现Servlet有以下三种方式:
-
实现Servlet接口;
-
继承GenericServlet抽象类(略带);
-
继承HttpServlet【主要】。
-
1.4Servlet案例演示-继承HttpServlet.
-
Servlet代码:
-
web.xml配置:
1.5web.xml配置的执行原理.
1.6web.xml映射路径配置说明.
-
<url-pattern>映射路径配置有三种:
-
完全路径匹配模式:以"/"开头,例如:/aaa/bbb.do、/bbb.do;
-
目录匹配模式:以“/”开头,例如:/aaa/*、 /*:
-
/aaa/*:表示访问的时候 /aaa/ 后面可以为任意值,也可以没有任何东西;
-
/* 表示访问Servlet的时候,任何东西都可以访问。
-
-
扩展名匹配模式:扩展名匹配不能以“/”开头。例如:/abc/*.do、/*.do都是错误的写法,正确的写法为 *.do。根据扩展名匹配,习惯上使用 *.do 来设置,此时访问 Servlet的时候,路径名中必须以 .do结尾。
-
-
匹配模式的优先级:完全路径匹配 >目录匹配 > 扩展名匹配。
1.5请求和响应对象.
1.5.1概述.
-
客户端给Web服务器发送一个http请求,web服务器就会针对每一次请求,分别创建一个用于代表请求的request(req)对象、和代表响应的response(resp)对象。
-
request对象就代表请求,所以我们可以通过request对象获得请求相关的数据和操作;
-
response代表响应,所以我们可以通过response对象进行对响应相关的数据封装和一些其他的操作。
-
-
request和response这两个对象是由 HttpServletRequest和HttpServletResponse两个接口的实现类创建的,在启动Web服务器(Tomcat)的时候就自动创建。
1.5.2HttpServletRequest介绍.
-
HttpServletRequest 对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在该对象中。
-
常用方法:
-
String getParameter(String name):获得客户端传送给服务器的参数值(单个值),该参数是由name指定的,通常是form表单中的参数。
-
String[ ] getParameterValues(String name):获得客户端传送给服务器的参数值(多个值,如:爱好),该参数是由name指定的,通常是form表单中的参数。
-
void setCharacterEncoding(String charset):设置请求的编码方式 防止中文乱码;
-
void setAttribute(String key, Object value):往作用域里面存值[键值对的方式];
-
Object getAttribute(String key):从作用域里面根据键获取值;
-
String getContextPath():动态的获取项目名。
-
-
注意区分:getParameter()和 getAttribute()方法的区别。
1.5.3HttpServletResponse介绍.
-
HttpServletResponse 对象代表服务器对客户端的响应,当服务器对客户端进行响应时,响应的数据、响应头、响应状态码都封装在该对象中。
-
常用方法:
-
-
void setContentType(String arg):设置响应的编码方式;
-
void addCookie(Cookie cookie) :向客户端写入Cookie;
-
PrintWriter getWriter():获取PrintWrite对象(一般用out命名);
-
1.6Servlet生命周期.
1.6.1生命周期流程图.
-
所谓 "Servlet生命周期",指的时 Servlet从创建到销毁整个过程所发生的事情(调用方法)。对比人的生命周期,一个人从出生到死亡之间所发生的事情。
-
Servlet生命周期如下图所示:
1.6.2生命周期案例演示.
-
通过实现Servlet接口进行演示。如:
1.6.3Servlet之init方法-了解.
-
servlet的 init方法是在 servlet在被创建时调用,用来完成初始化工作(可以通过观察init方法的执行次数验证 servlet是单例还是多例模式);
-
查看 GenericServlet类的源码,会发现有两个 init 方法,一个带了 ServletConfig参数,一个无参,有参的调用了无参的。如:
-
Tomcat默认调用的是有参的,因为在有参的 init方法里面调用了无参的 init方法,所以我们只需要重写无参的 init方法即可;
-
有一种情况我们就需要调用有参的 init方法,在获取 ServletConfig对象的时候,因为有参的 init方法里面带了个 ServletConfig参数,我们可以将该参数赋给定义好的 ServletConfig对象,从而获取 ServletConfig对象。
1.6.4Servlet之destroy方法-了解.
-
servlet的 destroy方法是在 servlet在被销毁时调用,注意是正常关闭 Tomcat才会执行;
-
注意,只要修改了 servlet里面的代码,然后保存,当前的 servlet会重新进行编译。重新编译 servlet其实就是先销毁容器里面当前的 servlet对象,然后再进行创建,所以在此过程中 destroy方法和 init方法都会被执行 【验证】。
1.7servlet之<init-param>和<context-param>标签.
1.7.1<init-param>标签.
-
<init-param>标签的作用及配置:
-
<init-param>配置在 servlet标签中,用来初始化当前 servlet对象的属性,属性存放在 servletConfig中,因此可以通过获取 servletConfig 对象的 getInitParameter("");方法来获取 servlet中<init-param>里配置的属性参数;
-
<init-param>写在 servlet中,web.xml中可以写多个servlet,而每个 servlet中可以设置多个<init-param>;
-
<init-param>里配置的属性参数仅在当前的 servlet中对象中有效。
-
<init-param>的原理如下:
-
当 servlet配置了<init-param>初始化参数之后,web容器在创建 servlet实例对象时,会自动将这些初始化参数封装到 ServletConfig对象中,并在调用 servlet的 init方法时,将 ServletConfig对象传递给 Servlet。进而,程序员通过Servlet对象得到当前 servlet的初始化参数信息。
-
-
servlet中配置 <init-param>如下所示:
-
-
获取<init-param>标签配置的属性:
1.7.2<context-param>标签.
-
<context-param>标签的作用及配置:
-
<context-param>写在 servlet之外,web.xml中可以有多个<context-param>,在整个 Tomcat上下文里面共享,不限制于某一个servlet;
-
web.xml中配置 <context-param>如下所示:
-
-
取<context-param>配置的参数:
1.7.3<init-param>和<context-param>的区别.
-
<init-param>:
-
是 Servlet范围内的参数,每个 servlet都可以有自己的 <init-param>,互相之间不能共享,如:
-
-
<context-param>:
-
是应用范围内的参数,存放在 Servlet上下文对象 ServletContext中。当服务器启动时,服务器会为每一个 WEB 应用创建一个唯一的 ServletContext对象,代表WEB应用,在同一个 web应用中所有 servlet对象共享同一个上下文对象。如:
-
1.8Servlet之<load-on-startup>标签.
-
<load-on-startup>1</load-on-startup>的作用:标记容器是否在启动的时候就加载这个servlet。
-
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet,正数的值越小,启动该servlet的优先级越高;
-
当是一个负数时或者没有指定时,则指示容器在该servlet被访问时才加载。
-
-
如果我们在 web.xml中设置了多个servlet的时候,可以使用 <load-on-startup>来指定 servlet的加载顺序,服务器会根据 <load-on-startup>的大小依次对 servlet进行初始化。不过即使我们将 <load-on-startup>设置重复也不会出现异常,服务器会自己决定初始化顺序。
-
配置<load-on-startup>后,servlet在启动后立即加载当前servlet,但只是调用 servlet的 init()方法,用以初始化该 servlet相关的资源。初始化成功后,该servlet可响应web请求;如未配置<load-on-startup>,容器一般在第一次响应web请求时,会先检测该 servlet是否初始化,如未初始化,则调用 servlet的 init()方法先初始化,初始化成功后,再响应请求。
-
一般在开发 web应用时,都会配置这个参数,有两个好处:
-
如果初始化过程失败,则容器会提示启动失败,此时我们能够提前知道相关错误;
-
配置该参数相当于将初始化 servlet的工作转移到容器启动过程,使得容器只要启动成功后,就可立即响应web请求。
-
-
配置方式如下:
1.9@WebServlet注解.
-
在 Servlet 中,web.xml 扮演的角色十分的重要,它可以将所有的 Servlet 的配置集中进行管理,但是若项目中 Servelt 数量较多时,web.xml 的配置会变得十分的冗长。这种情况下,注解(Annotation)就是一种更好的选择。
-
与 XML 不同,注解不需要依赖于配置文件,它可以直接在类中使用,其配置只对当前类有效,这样就避免了集中管理造成的配置冗长问题。
-
为了简化 Servlet 的配置,Servlet 3.0 中增加了注解支持,例如:@WebServlet、@WebInitParm 、@WebFilter 和 @WebLitener 等,这使得 web.xml 从 Servlet 3.0 开始不再是必选项了。
-
@WebServlet 用于将一个类声明为 Servlet,该注解会在部署时被容器处理,容器根据其具体的属性配置将相应的类部署为 Servlet。使用方式,如:@WebServlet("/请求URL")。
-
@WebServlet其它参数配置:
-
Servlet其它内容教程:@WebServlet注解(Servlet注解)。
2.页面跳转方式.
2.1转发-Request.
2.1.1概念.
-
请求,浏览器地址栏保持初始的URL地址不变,可以将上一个页面的数据带到下一个页面,属于服务器行为。
2.1.2方法-request.getRequestDispatcher().forward().
-
该方法在 服务器端内部 将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,但并不知道在服务器程序内部发生了转发行为。
-
用一个小故事来描述下转发的过程:一个绰号叫“浏览器”的人写信找张三借钱,张三的钱不够,于是张三找李四借了一些钱,然后加上自己的一些钱,最后再将这些钱汇给了“浏览器”。对于“浏览器”来说,他只发出了一次请求和收到了一次回复,他只知道从张三那里借到了钱,但是并不知道有一部分钱出自李四之手。
-
request.getRequestDispatcher().forward()方法的调用者与被调用者之间共享相同的 request 对象和 response 对象,它们属于同一个访问请求和响应过程。
2.1.3转发的特点.
-
地址栏不发生变化,显示的是上一个页面的地址。
-
请求次数:只有1次请求。
-
转发定位的目录:http://localhost:8080/项目名/【包含了项目名】。所以在转发的时候就不用在目标页面路径前面手动加项目名。
-
请求域中数据不会丢失,也就是可以将 request作用域中的数据继续往下一个页面传递。
2.2重定向-Response.
2.2.1概念.
-
响应,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL,不可以将数据带到下一个页面,属于客户端行为。
2.2.2方法-response.sendRedirect().
-
该方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了"浏览器"。由此可见,重定向的时候,"浏览器"一共发出了两封信和收到了两次回复,“浏览器”也知道他借到的钱出自李四之手。
-
response.sendRedirect()方法调用者与被调用者使用各自的 request对象和 response对象,它们属于两个独立的访问请求和响应过程。
2.2.重定向特点.
-
地址栏:显示新的地址。
-
请求次数:2次。
-
重定向定位的目录:http://localhost:8080/【没有项目的名字】。所以在重定向的时候要在目标页面路径前面加项目名。
-
请求域中的数据会丢失,因为是2次请求。
2.3转发和重定向小结.
2.3.1转发和重定向对比.
2.3.2使用的选择.
-
重定向的速度比转发慢,因为浏览器还得发出一个新的请求,如果在使用转发和重定向都无所谓的时候建议使用转发。
-
因为转发只能访问当前WEB的应用程序,所以不同WEB应用程序之间的访问,特别是要访问到另外一个WEB站点上的资源的情况,这个时候就只能使用重定向了。
2.3.3转发和重定向的应用场景.
-
上面已经总结出来,转发是要比重定向快,因为重定向需要经过客户端,而转发没有。有时候,采用重定向会更好,若需要重定向到另外一个外部网站,则无法使用转发。另外,重定向还有一个应用场景:避免在用户重新加载页面时两次调用相同的动作,尤其是在可以使数据发生改变的情况下。
-
例如,当提交产品表单的时候,执行保存的方法将会被调用,并执行相应的动作;这在一个真实的应用程序中,很有可能将表单中的所有产品信息加入到数据库中。但是如果在提交表单后,重新加载页面,执行保存的方法就很有可能再次被调用。同样的产品信息就将可能再次被添加,为了避免这种情况,提交表单后,你可以将用户重定向到一个不同的页面,这样的话,这个网页任意重新加载都没有副作用。
-
总结:增删改操作用转发,查询操作用重定向。
3.表单提交方式.
-
form表单的提交方式主要是两种:post和get。
-
当method为post时。浏览器把form数据封装到http body中,然后发送到server。数据不会显示在地址栏,而且没有数据长度限制。推荐使用。
-
当method为get时。则浏览器把form数据转换成一个字串(name1=name1&name2=name2…)然后把这个字串append到url后面,用 ?分割,再加载这个新的url。由于数据会显示在地址栏,不安全,所以不推荐使用。