2.Servlet&页面跳转方式&表单提交方式

1.Servlet概述.

1.1何为Servlet.

  • Servlet(Server Applet)是一个Java程序,是在服务器上运行以处理客户端请求并做出响应的程序。


1.2JSP和Servlet的区别.

  1. Servlet 比 jsp出现早;

  2. Servlet是由JAVA代码构成,擅长于流程控制和事务处理,通过Servlet来生成动态网页很不直观;

  3. JSP由HTML代码和JSP标签构成,可以方便地编写动态网页;

  4. Servlet在Java代码中可以通过HttpServletResponse对象动态输出HTML内容;

  5. JSP是在静态HTML内容中嵌入Java代码,然后Java代码在被动态执行后生成HTML内容;

  6. JSP是Servlet技术的扩展,本质上就是Servlet的简易方式;

  7. JSP侧重于视图,Servlet主要用于控制逻辑。

  8. 在实际应用中采用Servlet来控制业务流程,采用JSP来生成动态网页。


1.3实现Servlet的三种方式.

  • 实现Servlet有以下三种方式:

    1. 实现Servlet接口;

    2. 继承GenericServlet抽象类(略带);

    3. 继承HttpServlet【主要】。


1.4Servlet案例演示-继承HttpServlet.

  • Servlet代码:

  • web.xml配置:


1.5web.xml配置的执行原理.


1.6web.xml映射路径配置说明.

  • <url-pattern>映射路径配置有三种:

    1. 完全路径匹配模式:以"/"开头,例如:/aaa/bbb.do、/bbb.do;

    2. 目录匹配模式:以“/”开头,例如:/aaa/*、 /*:

      • /aaa/*:表示访问的时候 /aaa/ 后面可以为任意值,也可以没有任何东西;

      • /*  表示访问Servlet的时候,任何东西都可以访问。

    3. 扩展名匹配模式:扩展名匹配不能以“/”开头。例如:/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请求头中的所有信息都封装在该对象中。

  • 常用方法:

    1. String getParameter(String name):获得客户端传送给服务器的参数值(单个值),该参数是由name指定的,通常是form表单中的参数。

    2. String[ ] getParameterValues(String name):获得客户端传送给服务器的参数值(多个值,如:爱好),该参数是由name指定的,通常是form表单中的参数。

    3. void setCharacterEncoding(String charset):设置请求的编码方式 防止中文乱码;

    4. void setAttribute(String key, Object value):往作用域里面存值[键值对的方式];

    5. Object getAttribute(String key):从作用域里面根据键获取值;

    6. String getContextPath():动态的获取项目名。

  • 注意区分:getParameter()和 getAttribute()方法的区别。


1.5.3HttpServletResponse介绍.

  • HttpServletResponse 对象代表服务器对客户端的响应,当服务器对客户端进行响应时,响应的数据、响应头、响应状态码都封装在该对象中。

  • 常用方法:

    1. void setContentType(String arg):设置响应的编码方式;

    2. void addCookie(Cookie cookie) :向客户端写入Cookie;

    3. 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应用时,都会配置这个参数,有两个好处:

    1. 如果初始化过程失败,则容器会提示启动失败,此时我们能够提前知道相关错误;

    2. 配置该参数相当于将初始化 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. 地址栏不发生变化,显示的是上一个页面的地址。

  2. 请求次数:只有1次请求。

  3. 转发定位的目录:http://localhost:8080/项目名/【包含了项目名】。所以在转发的时候就不用在目标页面路径前面手动加项目名。

  4. 请求域中数据不会丢失,也就是可以将 request作用域中的数据继续往下一个页面传递。


2.2重定向-Response.

2.2.1概念.

  • 响应,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL,不可以将数据带到下一个页面,属于客户端行为。


2.2.2方法-response.sendRedirect().

  • 该方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了"浏览器"。由此可见,重定向的时候,"浏览器"一共发出了两封信和收到了两次回复,“浏览器”也知道他借到的钱出自李四之手。

  • response.sendRedirect()方法调用者与被调用者使用各自的 request对象和 response对象,它们属于两个独立的访问请求和响应过程。


2.2.重定向特点.

  1. 地址栏:显示新的地址。

  2. 请求次数:2次。

  3. 重定向定位的目录:http://localhost:8080/【没有项目的名字】。所以在重定向的时候要在目标页面路径前面加项目名。

  4. 请求域中的数据会丢失,因为是2次请求。


2.3转发和重定向小结.

2.3.1转发和重定向对比.


2.3.2使用的选择.

  1. 重定向的速度比转发慢,因为浏览器还得发出一个新的请求,如果在使用转发和重定向都无所谓的时候建议使用转发。

  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。由于数据会显示在地址栏,不安全,所以不推荐使用。