第9章 Java Servlet基础

Java Servlet基础

servlet的部署、创建与运行

源文件及字节码文件

  1. servlet类
  • 写一个创建servlet的类就是编写一个特殊类的子类,这个特殊的类就是javax.servlet.http包中的HttpServlet类。HttpServlet实现了Servlet接口,实现了响应用户的方法(这些方法将在后续内容中讲述)。HttpServlet的子类被习惯地称作一个Servlet类,这样的类创建的对象习惯地被称作一个servlet。
  1. 字节码文件的保存
  • 字节码文件按着类的包名对应的目录路径保存到Web服务目录中特定子目录中。包名moon.sun对应的目录路径是moon\sun,因此,保存到:
    \ch6\WEB-INF\classes\moon\sun
    可以事先将Java源文件,按照其包名,比如,包名为moon.sun,保存到
    \ch6\WEB-INF\classes\moon\sun
    然后用命令行进入moon\sun的父目录classes(不要进入moon或sun目录)编译:
    1
    classes> javac -cp servlet-api.jar moon\sun\Example6_1.java

编写部署文件 web.xml

  • Servlet类的字节码文件保存到指定的目录后,必须为Tomcat服务器编写一个部署文件,只有这样,Tomcat服务器才会用Servlet类创建servlet对象。
  • 部署文件是一个XML文件,名字必须是web.xml。
  • web.xml由Tomcat服务器负责管理,Tomcat服务器配有内置的解析器,可以解析XML文件的标记中的数据。
  • 编写的web.xml文件必须保存到Web服务目录的WEB-INF子目录中,比如ch6\WEB-INF中(不要保存在ch6中)。根据例子6_1给出的Servlet类,web.xml文件的内容如下(需要用纯文本编辑器编辑web.xml)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?xml version="1.0" encoding="utf-8" ?>
    <web-app>
    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>moon.sun.Example6_1</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/lookHello</url-pattern>
    </servlet-mapping>
    </web-app>
  • web.xml文件中标记的具体内容及其作用
    • 根标记:
      xml文件必须有一个根标记,web.xml文件的根标记是web-app,根标记web-app的开始标签是< web-app >,结束标签是,开始标签和结束标签之间的内容称作根标记的内容。
    • servlet标记及子标记
      web-app根标记里可以由若干个servlet(称作根标记的子标记,该标记的开始标签是< servlet >,结束标签是< /servlet >,开始标签和结束标签之间是servlet标记的内容)。servlet标记需要两个子标记:servlet-name和servlet-class,其中servlet-name标记的内容是Tomcat服务器创建的servlet的名字,servlet-class标记的内容告知Tomcat服务器用哪个Servlet类来创建servlet。
      web.xml文件可以有若干个servlet标记(一个servlet标记部署一个servlet对象),但要求它们的< servlet-name >子标记的内容互不相同,即服务器可以创建多个servlet,它们的名字必须互不相同。
    • servlet-mapping标记及子标记
      web.xml文件中出现一个servlet标记就会对应地出现一个或多个servlet-mapping标记,该标记和servlet标记都是根标记的直接子标记。不同的是,servlet-mapping标记需要有两个子标记:servlet-name和url-pattern,其中,servlet-name标记的内容是Tomcat服务器创建的servlet的名字(该名字必须和对应的servlet标记的子标记servlet-name的内容相同)。url-pattern标记用来指定用户用怎样的URL格式来请求servlet,例如,url-pattern标记的内容是/lookHello,那么用户必须在浏览器的地址栏中输入:
      1
      http://127.0.0.1:8080/ch6/lookHello
  • Web服务目录的WEB-INF子目录下的web.xml文件负责管理当前Web服务目录下的全部servlet,当该Web服务目录需要提供更多的servlet时,只要在web.xml文件中增加servlet和servlet-mapping子标记即可。
  • 对于webapps下的Web服务目录,如果修改并重新保存web.xml文件,Tomcat服务器就会立刻重新读取web.xml文件,因此,修改web.xml文件不必重新启动Tomcat服务器。但是,如果修改导致web.xml文件出现错误,Tomcat服务器就会关闭当前Web服务目录下的所有servlet的使用权限。所以必须保证web.xml文件正确无误,才能成功启动Tomcat服务器。但是,对于不是webapps下的Web服务目录,如果新建或修改了相应的web.xml文件,需要重新启动Tomcat服务器.

servlet的创建与运行

  • 用户就可以根据web.xml部署文件来请求Tomcat服务器创建并运行一个servlet。
  • 如果Tomcat服务器没有名字为hello的servlet,就会根据web.xml文件中servlet标记的子标记servlet-class指定的Servlet类创建一个名字为hello的servlet。因此,如果名字是hello的servlet被创建之后,又修改Java源文件、编译得到新的Servlet类,并希望Tomcat服务器用新的Servlet类创建servlet,那么就要重新启动Tomcat服务器。根据6.1.2中的web.xml文件,用户需在浏览器输入:
    1
    http://127.0.0.1:8080/ch6/lookHello
    请求Tomcat服务器运行名字是hello的servlet。

向servlet传递参数的值

  • 在请求一个servlet时,可以在请求的url-pattern中额外加入参数及其值,格式是:
    1
    url-pattern?参数1=值&参数2=值…参数n=值
    那么被请求的servlet就可以使用request对象获取参数的值,例如:
    1
    那么被请求的servlet就可以使用request对象获取参数的值,例如:

servlet的工作原理

servlet由Tomcat服务器负责管理,Tomcat服务器通过读取web.xml,然后创建并运行servlet。

servlet 对象的生命周期

  • servlet由Tomcat服务器负责创建并完成初始化工作。当多个用户请求一个servlet时,服务器为每个用户启动一个线程。
  • 一个servlet的生命周期主要有下列三个过程组成:
    • servlet第一次被请求加载时,服务器创建servlet,servlet调用init方法完成必要的初始化工作。
    • 新诞生的servlet再调用service方法响应用户的请求
    • 当服务器关闭时,调用destroy方法销毁servlet。
  • init方法只被调用一次。当后续的用户请求servlet服务时,Tomcat服务器将启动一个新的线程,在该线程中,servlet调用service方法。也就是说,每个用户的每次请求都导致service方法被调用执行,其执行过程分别运行在不同的线程中。

init方法

1
public void init(ServletConfig  config) throws ServletException

servlet第一次被请求加载时,服务器创建一个servlet,这个对象调用init方法完成必要的初始化工作。该方法在执行时,服务器会把一个SevletConfig类型的对象传递给init()方法,这个对象就被保存在servlet中,直到servlet被销毁。

service方法

1
public void service(HttpServletRequest request  HttpServletResponse  response)throw ServletException,IOException

Tomcat服务器将两个参数传递给该方法。和init方法不同的是,init方法只被调用一次,而service方法可能被多次的调用。当后续的用户请求该servlet时,Tomcat服务器将启动一个新的线程,在该线程中servlet调用service方法响应用户的请求,调用过程运行在不同的线程中,互不干扰。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。

destroy方法

1
public destroy()

通过JSP页面访问servlet

  • 按着部署文件web.xml给出的servlet的url-pattern,用户除了可以在浏览器输入url-pattern请求运行一个servlet外,也可以通过JSP页面来请求一个servlet。
    需要特别注意的是,如果web.xml文件中给出的servlet的url-pattern是/lookHello,那么JSP页面请求servlet时,必须要写成 lookHello,不可以写成/lookHello。

通过表单向servlet提交数据

  • 如果web.xml文件中给出的servlet的url-pattern是/computeBill,那么form表单中action给出的值就是computeBill :
    1
    2
    <form  action= "computeBill "  >
    </form>
  • 当请求一个servlet时,也可以在请求的url-pattern中额外加入参数及其值,格式是:
    url-pattern?参数1=值&参数2=值…参数n=值
    例如:
    1
    2
    <form  action= "computeBill?sideA=10.66&sideB=23.9&sideC=897 "  >
    </form>

通过超链接访问servlet

  • JSP页面可以使用超链接去请求某个servlet。如果web.xml文件中给出的请求servlet的url-pattern是/circle,那么超链接标记中href的值是circle(不要写成/circle):
    1
    <a href="circle"></a>

共享变量

  • Servlet类是HttpServlet的一个子类,在编写子类时就可以声明某些成员变量,那么,请求servlet的用户将共享该servlet的成员变量
  • service方法可能被多次的调用。也就是说,当后续的用户请求该servlet时,Tomcat服务器将启动一个新的线程,在该线程中servlet调用service方法响应用户的请求,即每个用户的请求都导致service方法被调用执行,调用过程运行在不同的线程中,互不干扰。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。

doGet和doPost方法

  • HttpServlet类除了init、service、destroy方法外,该类还有两个很重要的方法:doGet和doPost,用来处理用户的请求并作出响应。
  • 实际上HttpServlet类所给出的service方法的功能是检查HTTP请求类型(get、post),并在service方法中根据用户的请求方式,在service方法中对应地再调用doGet或doPost方法。
  • 因此,在编写的Servlet类(HttpServlet类的一个子类)时,也可以不重写service方法来响应用户,直接继承service方法即可。
  • 如果不重写service方法,就需要在Servlet类中重写doPost或doGet方法来响应用户的请求。如果不论用户请求类型是post还是get,Tomcat服务器的处理过程完全相同,那么可以只在doPost方法中编写处理过程,而在doGet方法中再调用doPost方法即可,或只在doGet方法中编写处理过程,而在doPost方法中再调用doGet方法。如果根据请求的类型进行不同的处理,就要在两个方法中编写不同的处理过程(这一点比service方法更为灵活)

重定向和转发

  • 重定向的功能是将用户从当前页面或servlet定向到另一个JSP页面或servlet。转发的功能是将用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet。本节学习在Servlet类中使用HttpServletResponse类的sendRedirect重定向方法,以及RequestDispatcher类的forward转发方法,并指出二者的区别。

sendRedirect方法

  • 重定向方法void sendRedirect(String location)
    将用户重新定向到另一个JSP页面或servlet。重定向方法仅仅是将用户从当前页面或servlet定向到另一个JSP页面或servlet,但不能将用户对当前页面或servlet的请求(HttpServletRequest对象)转发给所定向的资源。即重定向的目标页面或servlet无法使用request获取用户提交的数据。
  • 执行sendRedirect方法(重定向,也见4.2.3)时,Tomcat服务器还是要把当前的servlet代码执行完毕后才实施重定向(跳转)操作,但Tomcat服务器不再给用户看当前servlet代码的执行效果。如果在执行sendRedirect(URL url)方法后,servlet紧接着执行了return返回语句,那么Tomcat服务器会立刻结束当前servlet的执行。

forward方法

  • RequestDispatcher dispatcher =
    request.getRequestDispatcher(JSP页面的URL或servlet的url-pattern);
    例如:
    1
    RequestDispatcher dispatcher = request.getRequestDispatcher("target.jsp");
  • 转发。在步骤(1)中获取的RequestDispatcher对象调用
    void forward(ServletRequest request,ServletResponse response) throws ServletException,ava.io.IOException
    方法可以将用户对当前JSP页面或servlet的请求转发给RequestDispatcher对象所指定的JSP页面或servlet,例如:
    1
    dispatcher.forward (request,response);
  • 把用户对当前JSP页面或servlet的请求转变为对转发到的JSP页面或servlet的请求。
  • RequestDispatcher对象可以把用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet,而且将用户对当前JSP页面或servlet的请求传递给转发到的JSP页面或servlet。也就是说,当前页面所转发到的标页面或servlet可以使用request获取用户提交的数据。

二者的区别

  • 转发(forwar)和重定向方法(sendRedirect)不同的是,用户可以看到转发到的JSP页面或servlet的运行效果,但是,在浏览器的地址栏中不能看到forward方法转发到的JSP页面的地址或servlet的地址,用户在浏览器的地址栏中所看到的仍然是当前JSP页面的URL或servlet的url-pattern。如果此时刷新浏览器,那么请求将是当前的JSP页面或servlet。所转发到的标页面或servlet可以使用request获取用户提交的数据。而重定向的目标页面或servlet无法使用request获取用户提交的数据。
  • 另外,当servlet中执行forward方法实施转发操作时,Tomcat会立刻结速当前servlet的执行。而servlet中执行sendRedirect方法(重定向,也见4.2.3)时,Tomcat服务器还是要把当前的servlet代码执行完毕后才实施重定向(跳转)操作,但Tomcat服务器不再给用户看当前servlet代码的执行效果。如果在执行sendRedirect(URL url)方法后,servlet紧接着执行了return返回语句,那么Tomcat服务器会立刻结束当前servlet的执行。

使用session

-HTTP通信协议是用户与服务器之间一种请求与响应(request/response)的通信协议,属于无状态协议。所谓无状态是指,当用户(浏览器)发送请求给服务器,Tomcat服务器作出响应后,如果同一个用户再发送请求给Tomcat服务器时,Tomcat服务器并不知道就是刚才的那个用户。简单地说,Tomcat服务器不会记录用户的信息。

  • 用户在访问一个Web服务目录期间,Tomcat服务器为该用户分配一个session对象(称为用户的会话),Tomcat服务器可以在各个页面以及servlet中使用这个session记录用户的有关信息,而且Tomcat服务器保证不同用户的session对象互不相同。
  • HttpServletRequest对象request调用getSession方法获取用户的session对象:
    1
    HttpSession session=request.getSession(true);
  • 访问某个Web服务目录的用户,在不同的servlet中获取的session对象是完全相同的,不同的用户的session对象互不相同。

第9章 Java Servlet基础
https://lzyjx.github.io.git/2023/05/27/JavaServlet基础/
作者
六只羊
发布于
2023年5月27日
许可协议