servlet 订阅
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。最早支持Servlet标准的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。 展开全文
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。最早支持Servlet标准的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。
信息
类    别
程序
平    台
Java Web Server
环    境
Java applet
中文名
小服务程序或服务连接器
外文名
Servlet
servlet历程
Servlet 是在服务器上运行的小程序。这个词是在 Java applet的环境中创造的,Java applet 是一种当作单独文件跟网页一起发送的小程序,它通常用于在客户端运行,结果得到为用户进行运算或者根据用户互作用定位图形等服务。服务器上需要一些程序,常常是根据用户输入访问数据库的程序。这些通常是使用公共网关接口(Common Gateway Interface,CGI)应用程序完成的。然而,在服务器上运行 Java,这种程序可使用 Java 编程语言实现。在通信量大的服务器上,JavaServlet 的优点在于它们的执行速度更快于 CGI 程序。各个用户请求被激活成单个程序中的一个线程,而无需创建单独的进程,这意味着服务器端处理请求的系统开销将明显降低。实现过程最早支持 Servlet 技术的是 JavaSoft 的 Java Web Server。此后,一些其它的基于 Java 的 Web Server 开始支持标准的 Servlet API。Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。这个过程为:Servlet 看起来像是通常的 Java 程序。Servlet 导入特定的属于 Java Servlet API 的包。因为是对象字节码,可动态地从网络加载,可以说 Servlet 对 Server 就如同 Applet对 Client 一样,但是,由于 Servlet 运行于 Server 中,它们并不需要一个图形用户界面。从这个角度讲,Servlet 也被称为 FacelessObject。一个 Servlet 就是 Java 编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然 Servlet 可以对任何类型的请求产生响应,但通常只用来扩展 Web 服务器的应用程序。
收起全文
精华内容
参与话题
问答
  • Servlet

    千次阅读 多人点赞 2018-04-12 20:27:37
    1.1Servlet概述 1.1.1什么是Servlet  由SUN公司提供的动态web资源开发技术,Servlet本质上就是一段Java程序,只不过这段Java程序需要放在容器中, 由容器(比如tomcat服务器)调用才可以执行! 1.1.2如何开...

    1.1Servlet概述

    1.1.1什么是Servlet

      由SUN公司提供的动态web资源开发技术,Servlet本质上就是一段Java程序,只不过这段Java程序需要放在容器中, 由容器(比如tomcat服务器)调用才可以执行!

    1.1.2如何开Servlet程序

      需求:开发一个Servlet程序,当浏览器访问该程序时,可以向浏览器发送当前时间(的字符串)
      步骤:
      1)写一个类,需要实现(直接实现或间接实现)Servlet接口
      2)将编译后Servlet类,放在WEB应用中,并在WEB应用的web.xml文件中配置Servlet对外访问的虚拟路径。
      详细开发步骤
      (1)创建一个FirsServlet.java文件
      这里写图片描述
      (2)编写FirstServlet类,实现Servlet接口(或继承Servlet接口的子类),并添加未实现的方法
      这里写图片描述
      (3)实现Servlet中提供的处理请求的方法service方法,将表示当前时间的字符串响应给浏览器
      这里写图片描述
      (4)细节处理(添加servlet类的包路径和导入依赖包)
      这里写图片描述
      (5)打开CMD窗口,编译FirstServlet类
      通过命令编译会出现如下错误:
      这里写图片描述
      原因是 javax.servlet这个包不存在,所有下面出现了很多找不到符号错误。
      在tomcat服务器的lib目录下有servlet的jar包,可以设置包路径:
      这里写图片描述
      接着再次进行编译:
      这里写图片描述
      (6)将FirstServlet类放在WEB应用中,并在web.xml文件中配置Servlet对外访问的虚拟路径
      将编译好的class文件(包括包路径)放在web应用的classes目录下.
      这里写图片描述
      在WEB应用的web.xml文件中配置servlet对外访问的虚拟路径:
      这里写图片描述
      (7)将WEB应用部署到虚拟主机中,启动服务器,通过浏览器访问FirstServlet
      这里写图片描述
      

    1.2 Sservlet继承关系

      Servlet接口 - 提供了一个Servlet对象应该具有哪些功能
         |--GenericServlet(抽象类)–实现了Servlet接口,并且实现了其中大部分的方法,但是没有实现service方法,这个方法需要开发人员自己去实现
               |
              |--HttpServlet(抽象类)–继承了GenericServlet,并且实现了Service方法,在service方法中根据不同的请求方法,调用不同doXxx方法。因此我们在开发中,只需要写一个类继承HttpServlet,并覆盖doGet和doPost方法分别来处理(GET请求和POST请求即可!)
       这里写图片描述       

    1.3Servlet调用过程

    1.3.1Servlet调用过程

    问题:开发一个Servlet程序,放在WEB应用中,启动服务器,通过浏览器访问这个Servlet,可以在浏览器看到Servlet程序输出的内容,问:Servlet是怎么执行的?又是怎么调用的?
    这里写图片描述
       

    1.3.2Servlet生命周期

       Servlet在第一次被访问时将会创建实例,创建之后(服务器)立即调用init方法进行初始化的操作,此后该Servlet实例会一直驻留在服务器的内存中为后续的请求服务。只要有请求访问这个Servlet,就会调用service方法来进行处理,直到服务器关闭,或者是WEB应用被移出容器,随着WEB应用的销毁,Servlet实例也会跟着销毁,在销毁之前(服务器)会调用destroy方法进行善后的处理。

    1.4Servlet开发细节

    1.4.1Servlet虚拟路径的配置

      开发完Servlet程序后,需要再web.xml文件中配置Servlet对外访问的虚拟路径,其中配置方式有两种:
    1.直接写一个路径: /FirstServlet /SecondServlet
    2.使用星号匹配符写一个路径:
    (1) 以斜杠开头,以斜杠星结尾(比如:/* /servlet/* /a/*)
    (2) 以 .后缀 的形式(比如,.abc .html .action *.do)
      使用星号匹配符可以使得路径变得更加的灵活,但是也可能会造成一个路径会被多个mapping所匹配。那么哪一个mapping会起作用呢?
    路径的优先级:

    (1)哪一个更像(更接近、更精准)哪一个起作用!
    (2)*.后缀的优先级永远最低

    示例:
    Servlet1 映射到 /abc/*
    Servlet2 映射到 /*
    Servlet3 映射到 /abc
    Servlet4 映射到 *.do

      当请求URL为“/abc/a.html”,“/abc/”和“/”都匹配,哪个servlet响应 Servlet1将会匹配
      当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应 Servlet3将会匹配
      当请求URL为“/abc/a.do”时,“/abc/”和“.do”都匹配,哪个servlet响应 Servlet1将会匹配
      当请求URL为“/a.do”时,“/”和“.do”都匹配,哪个servlet响应 Servlet2将会起作用!

    展开全文
  • servlet

    千次阅读 2012-12-06 20:51:32
    我们Servlet解析(一)讨论了ServletServlet容器以及一个Servlet容器-Tomcat(包括安装与配置,目录结构,运行,启动分析,体系结构和如何管理程序)。而本篇,我们继续论述Servlet技术包括Servlet UML 类图结构...

    我们Servlet解析(一)讨论了Servlet、Servlet容器以及一个Servlet容器-Tomcat(包括安装与配置,目录结构,运行,启动分析,体系结构和如何管理程序)。而本篇,我们继续论述Servlet技术包括Servlet UML 类图结构,Servlet容器如何处理请求,如何寻找正确的servlet,为什么要采用映射机制,一个简单的Web程序实例以及Servlet接口。首先,我们介绍一下开发Servlet需要用到的主要接口和类,其UML类图如图1所示。


    图1 Servlet API中主要的接口与类的UML类图

    Servlet容器处理请求的过程

    在开始正文之前,让我们复习并细化一下Servlet容器处理请求的过程。

    1)用户点击一个链接,指向了一个servlet而不是一个静态页面。

    2)容器“看出”这个请求是一个Servlet,所以它创建了两个对象HttpServletRequest和HttpServletResponse。

    3)容器根据请求中的URL找到正确的Servlet,为这个请求创建或分配一个线程,并把请求和响应对象传递给这个Servlet线程。

    4)容器调用Servlet的service()方法。根据请求的不同类型,service()方法会调用doGet()或doPost()方法。这里假设调用doGet()方法。

    5)doGet()方法生成动态页面,并把这个页面“塞到”响应对象里,需要注意的是,容器还有响应对象的一个引用!

    6)线程结束,容器把响应对象转换为一个HTTP响应,并把它发回给客户,然后删除请求和响应对象。

    Servlet为什么可以成为Servlet?

    我们可以通过对一个Servlet的代码进行分析而得出结论。如图2所示。


    图2 一个简单的Servlet实现代码

    Servlet容器如何寻找正确的Servlet?

    我们刚讨论Servlet容器处理请求的过程时曾经讲到过,Servlet容器会寻找正确的Servlet,那么它是如何寻找的呢?

    其实,用户请求的URL会以某种方法映射到服务器上一个特定的Servlet。一个Servlet会有多个名字,,主要针对三个不同的对象。

    1)对于用户来说,他所知道的,是一个公共的URL名。用户看到html中对应一个Servlet的URL,但并不知道这个Servlet名字如何映射到服务器上的目录和文件。这个URL名只是一个虚拟的名字,方便用户使用。
    2)对于部署人员来说,他们可以创建一个名字,这个名字只有他自己以及实际操作环境中的其他人知道。同样的,这也是一个虚拟的名字,只用于部署Servlet。这个内部名字不一定与用户使用的公共URL名匹配,也不必与Servlet类的实际文件和路径名一样。
    3)对于开发人员来说,Servlet类有一个完全限定的名字,其中包括类名和包名。Servlet类文件有一个实际的路径和文件名,这取决于服务器上包目录结构所在的位置。

    为什么要采用映射机制?

    想想看我们都可以采用什么办法让Servlet容器寻找正确的Servlet?有一种办法是把真实路径名和文件名硬编码到所有使用该Servlet的JSP和其他HTML页面中,但如果你重新组织了你的应用,这时候目录改变了怎么办?而如果采用映射的方法,就会有很大的灵活性,如果改变了应用的目录,那么只需要在映射中修改即可。再说基于安全考虑,你总不希望用户对你服务器上的目录了如指掌吧?所以通过映射机制,让用户访问一个虚拟的名字,这样会提高安全性。

    我们通过一个典型的MVC实例来了解一下整个Web开发机制好了。MVC指的是Model,View,Controllre。即模型,视图,控制器。MVC将业务逻辑从Servlet中抽取出来,放到一个模型中(即一个可重用的Java类)。模型是业务数据和方法的组合。视图使用JSP,HTML等实现用户和系统的交互。在MVC中,视图负责表示。它从控制器得到模型的状态(不是真实得到,控制器会把模型数据能找到的一个地方)。另外,视图还要获得用户输入,交给控制器。控制器从请求获得用户输入,并明确这些输入对模型有什么影响,告诉模型自行更新,并且还要让视图(JSP)能得到新的模型状态。模型用于存放实际的业务逻辑和状态。它知道用什么规则来得到和更新状态。另外,模型还负责和数据库通信。

    下面我们看看web应用的开发与部署环境,分别如图3和图4所示。


    图3 Web应用的开发环境


    图4 Web应用的部署环境

    一个简单的Web应用程序

    MyDemo是一个简单的Web应用程序。主要功能是用户选择一个颜色的英文单词,然后“专家”会给出一个对应的中文词语。Servlet即控制器的代码如下:

    1. package com.shan.web;  
    2.   
    3. import com.shan.model.*;  
    4. import java.io.*;  
    5. import javax.servlet.*;  
    6. import javax.servlet.http.*;  
    7.   
    8.   
    9. /** 
    10.  ** A simple Servlet Demo 
    11.  ** @author shan 
    12.  **/  
    13. public class MyDemoServlet extends HttpServlet{  
    14.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {  
    15.         response.setContentType("text/html; charset=UTF-8");  
    16.         PrintWriter out= response.getWriter();  
    17.         String color = request.getParameter("color");  
    18.         out.println("You select color:" + color);  
    19.         Expert expert = new Expert();  
    20.         out.println(expert.getResult(color));  
    21.         out.println("<br/>Expert's result:" + expert.getResult(color));  
    22.     }  
    23. }  
    模型代码如下所示:

    1. package com.shan.model;  
    2.   
    3. import java.util.*;  
    4.   
    5. public class Expert{  
    6.     private Map<String, String> results = new HashMap<String, String>();  
    7.     public Expert() {  
    8.         results.put("White","白色");  
    9.         results.put("Black","黑色");  
    10.         results.put("Blue","蓝色");  
    11.         results.put("Red","红色");  
    12.         results.put("Green","绿色");  
    13.     }  
    14.     public String getResult(String color) {  
    15.         return results.get(color);  
    16.     }  
    17.     public static void main(String[] args) {  
    18.         Expert expert = new Expert();  
    19.         System.out.println(expert.getResult("White"));  
    20.     }  
    21. }  
    部署描述文件(DD)如下所示:

    1. <?xml version='1.0' encoding='utf-8'?>  
    2. <web-app xmlns="http://java.sun.com/xml/ns/javaee"  
    3.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
    5.                       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
    6.   version="3.0"  
    7.   metadata-complete="true">  
    8.   
    9.     <description>  
    10.       My Demo.  
    11.     </description>  
    12.   
    13.     <servlet>  
    14.         <servlet-name>selectServlet</servlet-name>  
    15.         <servlet-class>com.shan.web.MyDemoServlet</servlet-class>  
    16.     </servlet>  
    17.   
    18.     <servlet-mapping>  
    19.         <servlet-name>selectServlet</servlet-name>  
    20.         <url-pattern>/SelectColor.do</url-pattern>  
    21.     </servlet-mapping>  
    22.   
    23. </web-app>  
    有关web.xml文件的具体解释图5所示。

    图5 部署描述文件(DD)
    用作视图的表单页面的HTML源码如下(我命名为form.html):

    1. <html>  
    2.     <head>  
    3.         <title>Form</title>  
    4.     </head>  
    5.     <body>  
    6.         <h1 align="center">Selection Page</h1>  
    7.         <form align="center" method="post" action="SelectColor.do">  
    8.             Select color:  
    9.             <br/>  
    10.             <select name="color" size="1">  
    11.                 <option>White</options>  
    12.                 <option>Black</options>  
    13.                 <option>Blue</options>  
    14.                 <option>Red</options>  
    15.                 <option>Green</options>  
    16.             </select>  
    17.             <input type="submit" value="Submit">  
    18.         </form>  
    19.     </body>  
    20. </html>  
    由于例子简单,在此就不再放运行结果了。有兴趣的话可以按照上面的所讲的开发与部署工程,然后自己运行。运行时需要编译servlet。可以win+r,输入cmd,切换到工程所在目录。输入语句:

    1. javac -d classes src\com\shan\model\Expert.java  
    1. javac -classpath D:\apache-tomcat-7.0.33\lib\servlet-api.jar;classes -d .\classes src\com\shan\web\MyDemoServlet.java  

    编译完成之后,将classes文件夹等文件复制到图4所示的位置,之后输入startup启动Tomcat(注:Tomcat的配置按照上篇所述配置即可)。在浏览器网址栏输入:localhost:8080/MyDemo/form.html,选择一个颜色,点确认即可得到结果。

    好了,讲完了这个简单的例子。让我们继续看看服务器的整个运行过程。

    1)用户(浏览器)请求得到form.html页面2)容器获得form.html页面3)容器把这个页面返回给浏览器,用户在表单上回答问题4)浏览器把请求数据发送给容器5)容器根据URL找到正确的servlet,并把请求传递给这个servlet 6)serlvet调用Expert寻求帮助7)Expert类返回一个回答,servlet将这个回答增加到请求对象8)servlet将请求转发给JSP9)JSP从请求对象得到回答10)JSP为容器生成一个页面11)容器把这个页面(最终结果)返回给用户。

    在本例中,容器寻找正确servlet的过程是这样的:

    1)form.html中给出了调用的方法是post,给出了action是SelectColor.do,所以用户填写了表单后,会生成以下URL:localhost:8080/MyDemo/SelectColor.do,其中SelectColor.do是逻辑资源名。
    2)容器搜索部署描述文件,找到<url-pattern>与/SelectColor.do匹配的一个<servlet-mapping>
    3)容器看到对应的这个<url-pattern>的servlet-name>是SelectServlet,但这不是实际的servlet类文件的名字。SelectServlet只是一个servlet名,不是servlet类的名字。
    4)容器查找servlet-name>是SelectServlet的<servlet>标记。
    5)根据<servlet>标记中的<servlet-class>,容器知道了由哪个servlet类负责处理这个请求,如果这个servlet类还没有初始化,就会加载类,并初始化servlet。
    6)容器开启一个新的线程来处理这个请求,并把请求传递给线程(传递给servlet的service()方法,由于用户发出了一个HTTP post请求,所以service()方法会调用servlet的doPost()方法,把请求和响应对象作为参数传递给它)。
    7)service()方法结束,所以线程要么撤销,要么返回到容器管理的一个线程池。请求和响应对象引用已经出了作用域,所以会被垃圾回收机制回收。容器把响应(通过web服务器)发回给用户。

    Servlet接口

    在Java中我们学过Java Applet即Java小应用程序,它运行在客户端的浏览器中。在此,我们可以类比一下Java Applet与Java Servlet,比较其异同点加深我们对Java Servlet的理解。

    两者的共同点:

    它们都不是独立的应用程序,都没有main()方法。
    它们都不是由用户或程序员直接调用,而是生存在容器中,由容器管理。Applet运行在浏览器中,Servlet运行在Servlet容器中。
    它们都有生命周期,都包含了init()和destroy()方法。

    两者的不同点:

    Java Applet具有图形界面,运行在客户端的浏览器中;Java Servlet没有图形界面,运行在服务器端的Servlet容器中。
    要编写一个Java Applet,需要从java.applet.Applet类派生一个子类;和Java Applet类似,要编写一个Java Servlet,需要实现javax.servlet.Servlet接口。

    javax.servlet.Servlet接口接口定义了如下5个方法:

    1. public void init(ServletConfig config) throws ServletException  
    2. public void service(ServletRequest req, ServletResponse res)throws ServletException, java.io.IOException  
    3. public void destroy()  
    4. public ServletConfig getServletConfig()  
    5. public java.lang.String getServletInfo()  

    下面介绍一下这5个方法的作用。

    init():在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象,主要是为了让Servlet对象在处理客户请求前可以完成一些初始化的工作,例如,建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只能被调用一次。init()方法有一个类型为ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用ServletConfig对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过ServletConfig对象获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的Servlet容器进行通信。

    service():容器调用service()方法来处理客户端的请求。要注意的是,在service()方法被容器调用之前,必须确保init()方法正确完成。容器会构造一个表示客户端请求信息的请求对象(类型为ServletRequest)和一个用于对客户端进行响应的响应对象(类型为ServletResponse)作为参数传递给service()方法。在service()方法中,Servlet对象通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。

    destroy():当容器检测到一个Servlet对象应该从服务中被移除的时候,容器会调用该对象的destroy()方法,以便让Servlet对象可以释放它所使用的资源,保存数据到持久存储设备中,例如,将内存中的数据保存到数据库中,关闭数据库的连接等。当需要释放内存或者容器关闭时,容器就会调用Servlet对象的destroy()方法。在Servlet容器调用destroy()方法前,如果还有其他的线程正在service()方法中执行,容器会等待这些线程执行完毕或等待服务器设定的超时值到达。一旦Servlet对象的destroy()方法被调用,容器不会再把其他的请求发送给该对象。如果需要该Servlet再次为客户端服务,容器将会重新产生一个Servlet对象来处理客户端的请求。在destroy()方法调用之后,容器会释放这个Servlet对象,在随后的时间内,该对象会被Java的垃圾收集器所回收。

    getServletConfig():该方法返回容器调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含了Servlet的初始化参数。

    getServletInfo():返回一个String类型的字符串,其中包括了关于Servlet的信息,例如,作者、版本和版权。该方法返回的应该是纯文本字符串,而不是任何类型的标记(HTML、XML等)。

    每个请求都在一个单独的实例中运行

    由上文我们知道,在servlet实例创建之后,在servlet能为客户请求提供服务之前,容器会在servlet实例上调用init()方法。如果你有初始化代码,就应该覆盖servlet类的init()方法,否则会调用GenericServlet的init()方法。而对应每个客户请求(无论是谁,无论是不是同一个人,只针对请求),容器都会创建一对新的请求和响应对象,创建一个新的线程/栈。任何servlet类都不会有多个实例,除非一种特殊情况(SingleThreadModel,其实很糟糕),我们不讨论这种特殊状况。


    展开全文
  • JavaWeb——Servlet         Tomcat工作机制动画演示(点击动图可全屏观看)   什么是Servlet    Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要...

                                 JavaWeb——Servlet

     

     

     

     

    Tomcat工作机制动画演示(点击动图可全屏观看)


     

    什么是Servlet


        

        Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的,一般情况下,人们将Servlet理解为后者。

        Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议Web服务器

     

     

    Servlet的工作模式


        

    • 客户端发送请求至服务器
    • 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
    • 服务器将响应返回客户端

     

    Servlet API 概览


        Servlet API 包含以下4个Java包:

    1.javax.servlet   其中包含定义servlet和servlet容器之间契约的类和接口。

    2.javax.servlet.http   其中包含定义HTTP Servlet 和Servlet容器之间的关系。

    3.javax.servlet.annotation   其中包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。

    4.javax.servlet.descriptor,其中包含提供程序化登录Web应用程序的配置信息的类型。

     

     

    Servlet 的主要类型


     

     

     

     

     

    Servlet 的使用方法


        

    Servlet技术的核心是Servlet,它是所有Servlet类必须直接或者间接实现的一个接口。在编写实现Servlet的Servlet类时,直接实现它。在扩展实现这个这个接口的类时,间接实现它。

     

    Servlet 的工作原理


     

        Servlet接口定义了Servletservlet容器之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它具体的方法。但是要注意的是,在一个应用程序中,每种Servlet类型只能有一个实例

     

        用户请求致使Servlet容器调用Servlet的Service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使用这两个对象。

        ServletRequest中封装了当前的Http请求,因此,开发人员不必解析和操作原始的Http数据。ServletResponse表示当前用户的Http响应,程序员只需直接操作ServletResponse对象就能把响应轻松的发回给用户。

        对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。

     

     

     

    Servlet 接口中定义的方法


        让我们首先来看一看Servlet接口中定义了哪些方法吧。

     

    public interface Servlet {
        void init(ServletConfig var1) throws ServletException;
    
        ServletConfig getServletConfig();
    
        void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
        String getServletInfo();
    
        void destroy();
    }
    

        

    Servlet 的生命周期


    其中,init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程。Servlet容器(例如TomCat)会根据下面的规则来调用这三个方法:

    1.init( ),当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用,就像人只能“出生”一次一样。我们可以利用init( )方法来执行相应的初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化

    2.service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。就像人一样,需要不停的接受老板的指令并且“工作”。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。

    3.destory,当要销毁Servlet时,Servlet容器就会调用这个方法,就如人一样,到时期了就得死亡。在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。

        首先,我们来编写一个简单的Servlet来验证一下它的生命周期:

     

    public class MyFirstServlrt implements Servlet {
    
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
            System.out.println("Servlet正在初始化");
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            //专门向客服端提供响应的方法
            System.out.println("Servlet正在提供服务");
    
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
            System.out.println("Servlet正在销毁");
        }
    }      

    然后在xml中配置正确的映射关系,在浏览器中访问Servlet,第一次访问时,控制台输出了如下信息:

    然后,我们在浏览器中刷新3遍

    控制台输出的信息变成了下面这样:

    接下来,我们关闭Servlet容器

    控制台输出了Servlet的销毁信息,这就是一个Servlet的完整生命周期。

     

    Servlet 的其它两个方法


        getServletInfo( ),这个方法会返回Servlet的一段描述,可以返回一段字符串。

        getServletConfig( ),这个方法会返回由Servlet容器传给init( )方法的ServletConfig对象。

     

     

    ServletRequset接口


        Servlet容器对于接受到的每一个Http请求,都会创建一个ServletRequest对象,并把这个对象传递给Servlet的Sevice( )方法。其中,ServletRequest对象内封装了关于这个请求的许多详细信息。

    让我们来看一看ServletRequest接口的部分内容:

     

    public interface ServletRequest {
      
    
        int getContentLength();//返回请求主体的字节数
    
        String getContentType();//返回主体的MIME类型
    
        String getParameter(String var1);//返回请求参数的值
    
    }

    其中,getParameter是在ServletRequest中最常用的方法,可用于获取查询字符串的值

     

     

    ServletResponse接口


        javax.servlet.ServletResponse接口表示一个Servlet响应,在调用Servlet的Service( )方法前,Servlet容器会先创建一个ServletResponse对象,并把它作为第二个参数传给Service( )方法。ServletResponse隐藏了向浏览器发送响应的复杂过程。

        让我们也来看看ServletResponse内部定义了哪些方法:

     

    public interface ServletResponse {
        String getCharacterEncoding();
    
        String getContentType();
    
        ServletOutputStream getOutputStream() throws IOException;
    
        PrintWriter getWriter() throws IOException;
    
        void setCharacterEncoding(String var1);
    
        void setContentLength(int var1);
    
        void setContentType(String var1);
    
        void setBufferSize(int var1);
    
        int getBufferSize();
    
        void flushBuffer() throws IOException;
    
        void resetBuffer();
    
        boolean isCommitted();
    
        void reset();
    
        void setLocale(Locale var1);
    
        Locale getLocale();
    }

     

       其中的getWriter方法,它返回了一个可以向客户端发送文本的的Java.io.PrintWriter对象。默认情况下,PrintWriter对象使用ISO-8859-1编码(该编码在输入中文时会发生乱码)。

     

        在向客户端发送响应时,大多数都是使用该对象向客户端发送HTML。

    还有一个方法也可以用来向浏览器发送数据,它就是getOutputStream,从名字就可以看出这是一个二进制流对象,因此这个方法是用来发送二进制数据的。

    在发送任何HTML之前,应该先调用setContentType()方法,设置响应的内容类型,并将“text/html”作为一个参数传入,这是在告诉浏览器响应的内容类型为HTML,需要以HTML的方法解释响应内容而不是普通的文本,或者也可以加上“charset=UTF-8”改变响应的编码方式以防止发生中文乱码现象。

     

     

    ServletConfig接口


        当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象。

    其中几个方法如下:

     

     

    ServletContext对象


        ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。

    通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。

    那么为什么要存在一个ServletContext对象呢?存在肯定是有它的道理,因为有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中。保存在ServletContext中的对象被称作属性。

    ServletContext中的下列方法负责处理属性:

     

    Object getAttribute(String var1);
    
    Enumeration<String> getAttributeNames();
    
    void setAttribute(String var1, Object var2);
    
    void removeAttribute(String var1);

     

     

     

     

     

    GenericServlet抽象类 


        前面我们编写Servlet一直是通过实现Servlet接口来编写的,但是,使用这种方法,则必须要实现Servlet接口中定义的所有的方法,即使有一些方法中没有任何东西也要去实现,并且还需要自己手动的维护ServletConfig这个对象的引用。因此,这样去实现Servlet是比较麻烦的。

    void init(ServletConfig var1) throws ServletException;

        幸好,GenericServlet抽象类的出现很好的解决了这个问题。本着尽可能使代码简洁的原则,GenericServlet实现了Servlet和ServletConfig接口,下面是GenericServlet抽象类的具体代码:

     

    public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
        private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
        private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
        private transient ServletConfig config;
    
        public GenericServlet() {
        }
    
        public void destroy() {
        }
    
        public String getInitParameter(String name) {
            ServletConfig sc = this.getServletConfig();
            if (sc == null) {
                throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
            } else {
                return sc.getInitParameter(name);
            }
        }
    
        public Enumeration<String> getInitParameterNames() {
            ServletConfig sc = this.getServletConfig();
            if (sc == null) {
                throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
            } else {
                return sc.getInitParameterNames();
            }
        }
    
        public ServletConfig getServletConfig() {
            return this.config;
        }
    
        public ServletContext getServletContext() {
            ServletConfig sc = this.getServletConfig();
            if (sc == null) {
                throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
            } else {
                return sc.getServletContext();
            }
        }
    
        public String getServletInfo() {
            return "";
        }
    
        public void init(ServletConfig config) throws ServletException {
            this.config = config;
            this.init();
        }
    
        public void init() throws ServletException {
        }
    
        public void log(String msg) {
            this.getServletContext().log(this.getServletName() + ": " + msg);
        }
    
        public void log(String message, Throwable t) {
            this.getServletContext().log(this.getServletName() + ": " + message, t);
        }
    
        public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
        public String getServletName() {
            ServletConfig sc = this.getServletConfig();
            if (sc == null) {
                throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
            } else {
                return sc.getServletName();
            }
        }
    }
    
        其中,GenericServlet抽象类相比于直接实现Servlet接口,有以下几个好处:
    

     

    1.为Servlet接口中的所有方法提供了默认的实现,则程序员需要什么就直接改什么,不再需要把所有的方法都自己实现了。

    2.提供方法,包围ServletConfig对象中的方法。

     

    3.将init( )方法中的ServletConfig参数赋给了一个内部的ServletConfig引用从而来保存ServletConfig对象,不需要程序员自己去维护ServletConfig了。

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    但是,我们发现在GenericServlet抽象类中还存在着另一个没有任何参数的Init()方法:

     

    public void init() throws ServletException {
    }

    设计者的初衷到底是为了什么呢?在第一个带参数的init()方法中就已经把ServletConfig对象传入并且通过引用保存好了,完成了Servlet的初始化过程,那么为什么后面还要加上一个不带任何参数的init()方法呢?这不是多此一举吗?

        当然不是多此一举了,存在必然有存在它的道理。我们知道,抽象类是无法直接产生实例的,需要另一个类去继承这个抽象类,那么就会发生方法覆盖的问题,如果在类中覆盖了GenericServlet抽象类的init()方法,那么程序员就必须手动的去维护ServletConfig对象了,还得调用super.init(servletConfig)方法去调用父类GenericServlet的初始化方法来保存ServletConfig对象,这样会给程序员带来很大的麻烦。GenericServlet提供的第二个不带参数的init( )方法,就是为了解决上述问题的。

        这个不带参数的init()方法,是在ServletConfig对象被赋给ServletConfig引用后,由第一个带参数的init(ServletConfig servletconfig)方法调用的,那么这意味着,当程序员如果需要覆盖这个GenericServlet的初始化方法,则只需要覆盖那个不带参数的init( )方法就好了,此时,servletConfig对象仍然有GenericServlet保存着。

        说了这么多,通过扩展GenericServlet抽象类,就不需要覆盖没有计划改变的方法。因此,代码将会变得更加的简洁,程序员的工作也会减少很多。

        然而,虽然GenricServlet是对Servlet一个很好的加强,但是也不经常用,因为他不像HttpServlet那么高级。HttpServlet才是主角,在现实的应用程序中被广泛使用。那么我们接下来就看看传说中的HttpServlet到底厉害在哪里吧。

     

     

    javax.servlet.http包内容


        之所以所HttpServlet要比GenericServlet强大,其实也是有道理的。HttpServlet是由GenericServlet抽象类扩展而来的,HttpServlet抽象类的声明如下所示:

     

    public abstract class HttpServlet extends GenericServlet implements Serializable 

    HttpServlet之所以运用广泛的另一个原因是现在大部分的应用程序都要与HTTP结合起来使用。这意味着我们可以利用HTTP的特性完成更多更强大的任务。Javax。servlet.http包是Servlet API中的第二个包,其中包含了用于编写Servlet应用程序的类和接口。Javax.servlet.http中的许多类型都覆盖了Javax.servlet中的类型。

     

     

    HttpServlet抽象类


        HttpServlet抽象类是继承于GenericServlet抽象类而来的。使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象。

    HttpServletRequest接口扩展于javax.servlet.ServletRequest接口,HttpServletResponse接口扩展于javax.servlet.servletResponse接口。

     

    public interface HttpServletRequest extends ServletRequest
    public interface HttpServletResponse extends ServletResponse

    HttpServlet抽象类覆盖了GenericServlet抽象类中的Service( )方法,并且添加了一个自己独有的Service(HttpServletRequest request,HttpServletResponse方法。

    让我们来具体的看一看HttpServlet抽象类是如何实现自己的service方法吧:

        首先来看GenericServlet抽象类中是如何定义service方法的:

     

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    我们看到是一个抽象方法,也就是HttpServlet要自己去实现这个service方法,我们在看看HttpServlet是怎么覆盖这个service方法的:

     

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }
    
        this.service(request, response);
    }

        我们发现,HttpServlet中的service方法把接收到的ServletRequsest类型的对象转换成了HttpServletRequest类型的对象,把ServletResponse类型的对象转换成了HttpServletResponse类型的对象。之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。因此,转换类型当然不会出错了。

        转换之后,service方法把两个转换后的对象传入了另一个service方法,那么我们再来看看这个方法是如何实现的:

     

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if (ifModifiedSince < lastModified) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }
    
    }

     

        我们发现,这个service方法的参数是HttpServletRequest对象和HttpServletResponse对象,刚好接收了上一个service方法传过来的两个对象。

     

        接下来我们再看看service方法是如何工作的,我们会发现在service方法中还是没有任何的服务逻辑,但是却在解析HttpServletRequest中的方法参数,并调用以下方法之一:doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete。这7种方法中,每一种方法都表示一个Http方法。doGet和doPost是最常用的。所以,如果我们需要实现具体的服务逻辑,不再需要覆盖service方法了,只需要覆盖doGet或者doPost就好了。

        总之,HttpServlet有两个特性是GenericServlet所不具备的:

        1.不用覆盖service方法,而是覆盖doGet或者doPost方法。在少数情况,还会覆盖其他的5个方法。

        2.使用的是HttpServletRequest和HttpServletResponse对象。

     

     

    HttpServletRequest接口


        

        HttpServletRequest表示Http环境中的Servlet请求。它扩展于javax.servlet.ServletRequest接口,并添加了几个方法。

     

     

    String getContextPath();//返回请求上下文的请求URI部分
    Cookie[] getCookies();//返回一个cookie对象数组
    String getHeader(String var1);//返回指定HTTP标题的值
    String getMethod();//返回生成这个请求HTTP的方法名称
    String getQueryString();//返回请求URL中的查询字符串
    HttpSession getSession();//返回与这个请求相关的会话对象

    HttpServletRequest内封装的请求


        因为Request代表请求,所以我们可以通过该对象分别获得HTTP请求的请求行,请求头和请求体。

        关于HTTP具体的详细解释,可以参考我的另一篇博文:JavaWeb——HTTP。

     

    通过request获得请求行


     

    假设查询字符串为:username=zhangsan&password=123

    获得客户端的请求方式:String getMethod()

    获得请求的资源:

    String getRequestURI()

    StringBuffer getRequestURL()

    String getContextPath() ---web应用的名称

    String getQueryString() ---- get提交url地址后的参数字符串

     

    通过request获得请求头


    long getDateHeader(String name)

    String getHeader(String name)

    Enumeration getHeaderNames()

    Enumeration getHeaders(String name)

    int getIntHeader(String name)

    referer头的作用:执行该此访问的的来源,做防盗链

     

    通过request获得请求体


    请求体中的内容是通过post提交的请求参数,格式是:

    username=zhangsan&password=123&hobby=football&hobby=basketball

    key ---------------------- value

    username                               [zhangsan]

    password                               [123]

    hobby                                          [football,basketball]                                       

    以上面参数为例,通过一下方法获得请求参数:

    String getParameter(String name)

    String[] getParameterValues(String name)

    Enumeration getParameterNames()

    Map<String,String[]> getParameterMap()

          注意:get请求方式的请求参数 上述的方法一样可以获得。

     

     

    Request乱码问题的解决方法


        在前面我们讲过,在service中使用的编码解码方式默认为:ISO-8859-1编码,但此编码并不支持中文,因此会出现乱码问题,所以我们需要手动修改编码方式为UTF-8编码,才能解决中文乱码问题,下面是发生乱码的具体细节:

     

     

     

    解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");

     解决get提交的方式的乱码:

    parameter = newString(parameter.getbytes("iso8859-1"),"utf-8");

     

    HttpServletResponse接口


     

        在Service API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。    由于HTTP请求消息分为状态行,响应消息头,响应消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法。

     

     

    HttpServletResponse内封装的响应


     

     

     

    通过Response设置响应


     

     

     

    void addCookie(Cookie var1);//给这个响应添加一个cookie
    void addHeader(String var1, String var2);//给这个请求添加一个响应头
    void sendRedirect(String var1) throws IOException;//发送一条响应码,讲浏览器跳转到指定的位置
    void setStatus(int var1);//设置响应行的状态码

    addHeader(String name, String value)

    addIntHeader(String name, int value)

    addDateHeader(String name, long date)

    setHeader(String name, String value)

    setDateHeader(String name, long date)

    setIntHeader(String name, int value)

    其中,add表示添加,而set表示设置

     

    PrintWriter getWriter()

    获得字符流,通过字符流的write(String s)方法可以将字符串设置到response   缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。

    ServletOutputStream getOutputStream()

    获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。

     

     注意:虽然response对象的getOutSream()和getWriter()方法都可以发送响应消息体,但是他们之间相互排斥,不可以同时使用,否则会发生异常。

     

    Response的乱码问题


     

    原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文。所以需要更改response的编码方式:

     

        通过更改response的编码方式为UTF-8,任然无法解决乱码问题,因为发送端服务端虽然改变了编码方式为UTF-8,但是接收端浏览器端仍然使用GB2312编码方式解码,还是无法还原正常的中文,因此还需要告知浏览器端使用UTF-8编码去解码

        上面通过调用两个方式分别改变服务端对于Response的编码方式以及浏览器的解码方式为同样的UTF-8编码来解决编码方式不一样发生乱码的问题。

    response.setContentType("text/html;charset=UTF-8")这个方法包含了上面的两个方法的调用,因此在实际的开发中,只需要调用一个response.setContentType("text/html;charset=UTF-8")方法即可。

     

    Response的工作流程


     

     

    Servlet的工作流程


     

     

    编写第一个Servlet


        首先,我们来写一个简单的用户名,密码的登录界面的html文件:

    <form action="/form" method="get">

    该html文件在最后点击提交按钮时,把表单所有数据通过Get方式发送到/form虚拟路径下:

     

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/form" method="get">
        <span>用户名</span><input type="text" name="username"><br>
        <span>密码</span><input type="password" name="password"><br>
        <input type="submit" name="submit">
    </form>
    
    </body>
    </html>

    访问一下我们刚才写的这个简单的登录界面:

        接下来,我们就开始写一个Servlet用来接收处理表单发送过来的请求,这个Servlet的名称就叫做FormServlet:

     

    public class FormServlet extends HttpServlet {
        private static final long serialVersionUID = -4186928407001085733L;
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             //设置响应的编码格式为UTF-8编码,否则发生中文乱码现象
            response.setContentType("text/html;charset=UTF-8");
            //1.获得请求方式
            String method = request.getMethod();
            //2.获得请求的资源相关的内容
            String requestURI = request.getRequestURI();//获得请求URI
            StringBuffer requestURL = request.getRequestURL();
            String webName = request.getContextPath();//获得应用路径(应用名称)
            String querryString = request.getQueryString();//获得查询字符串
    
            response.getWriter().write("<h1>下面是获得的字符串</h1>");
            response.getWriter().write("<h1>method(HTTP方法):<h1>");
            response.getWriter().write("<h1>"+method+"</h1><br>");
            response.getWriter().write("<h1>requestURi(请求URI):</h1>");
            response.getWriter().write("<h1>" + requestURI + "</h1><br>");
            response.getWriter().write("<h1>webname(应用名称):</h1>");
            response.getWriter().write("<h1>" + webName + "</h1><br>");
            response.getWriter().write("<h1>querrystring(查询字符串):</h1>");
            response.getWriter().write("<h1>" + querryString + "</h1>");
    
    
        }
    }

        该Servlet的作用是,接收form登录表单发送过来的HTTP请求,并解析出请求中封装的一些参数,然后在回写到response响应当中去,最后在浏览器端显示。

        最后一步,我们在XML中配置好这个Servlet的映射关系:

     

    </servlet-mapping>
        <servlet>
            <servlet-name>FormServlet</servlet-name>
            <servlet-class>com.javaee.util.FormServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>FormServlet</servlet-name>
            <url-pattern>/form</url-pattern>
        </servlet-mapping>

        接下来,启动tomcat,在浏览器中输入登录表单的地址:

    填入用户名为:root,密码为:123,最后点击提交:

    提交之后,表单数据将会发送到相应的Servlet进行处理,此时,浏览器的地址变成如下所示:

        我们会发现,在地址栏中,多了后面的“?username=root&password=123&提交=提交”字符串,这其实就是我们开始填写的参数,以Get的方法发送过去,所以查询字符串会直接加在链接后面,如果采用的是Post方式则不会出现在链接中,因此,登录表单为了安全性大多采用Post方式提交。

        我们来看看Servlet给我们返回了什么东西:

        正如我们在Servlet中写的那样,Servlet把HTTP请求中的部分参数给解析出来了。

    因此,可以再翻到上面的Servlet重新去理解一遍Servlet的工作原理,可能会有更清晰的认识。

     

     

    Servlet的局限性


     

        我们已经看到,Servlet如果需要给客户端返回数据,比如像下面这样的一个HTML文件:

     

    Servlet内部需要这样写输出语句:

     

    PrintWriter writer = response.getWriter();
    writer.write("<!DOCTYPE html>\n" +
            "<html>\n" +
            "\t<head>\n" +
            "\t\t<meta charset=\"UTF-8\">\n" +
            "\t\t<title>标题标签</title>\n" +
            "\t</head>\n" +
            "\t<body>\n" +
            "\t\t<!--标题标签-->\n" +
            "\t\t<h1>公司简介</h1><br />\n" +
            "\t\t<h2>公司简介</h2><br />\n" +
            "\t\t<h3>公司简介</h3><br />\n" +
            "\t\t<h4>公司简介</h4><br />\n" +
            "\t\t\n" +
            "\t\t<!--加入一条水平线-->\n" +
            "\t\t<hr />\n" +
            "\t\t\n" +
            "\t\t<h5>公司简介</h5><br />\n" +
            "\t\t<h6>公司简介</h7><br />\n" +
            "\t\t<h100>公司简介</h100>\n" +
            "\t</body>\n" +
            "</html>\n");

        即一行一行的把HTML语句给用Writer输出,早期简单的网页还能应付得住,但是随着互联网的不断发展,网站的内容和功能越来越强大,一个普通的HTML文件可能就达到好几百行,如果在采用使用Servlet去一行一行的输出HTML代码的话,将会非常的繁琐并且浪费大量的时间,且在当时,出现了PHP这种可以内嵌到HTML文件的动态语言,使得制作动态网页变得异常的简单和轻松,因此大量的程序员转上了PHP语言的道路,JAVA的份额急剧减小,当时JAVA的开发者Sun公司为了解决这个问题,也开发出了自己的动态网页生成技术,使得同样可以在HTML文件里内嵌JAVA代码,这就是现在的JSP技术,关于JSP技术的具体内容,我们将留到下一节进行讲解。

     

    ServletContextListener(Servlet全局监听器)


    首先要说明的是,ServletContextListener是一个接口,我们随便写一个类,只要这个类实现了ServletContextListener接口,那么这个类就实现了【监听ServletContext】的功能。那么,这个神奇的接口是如何定义的呢?我们来看一下这个接口的内部情况:

    package javax.servlet;

    import java.util.EventListener;

    public interface ServletContextListener extends EventListener {
       
    void contextInitialized(ServletContextEvent var1);


        void contextDestroyed(ServletContextEvent var1);
    }

    我们发现,在这个接口中只声明了两个方法,分别是void contextInitialized(ServletContextEvent var1)和void contextDestroyed(ServletContextEvent var1)方法,所以,我们很容易的就能猜测到,ServletContext的生命只有两种,分别是:

    1.ServletContext初始化。(应用start时)---------->Servlet容器调用void contextInitialized(ServletContextEvent var1)

    2.ServletContext销毁。(应用stop时)---------->Servlet容器调用 void contextDestroyed(ServletContextEvent var1)

    因此,我们大概能够猜到ServletContextListener的工作机制了,当应用启动时,ServletContext进行初始化,然后Servlet容器会自动调用正在监听ServletContext的ServletContextListener的void contextInitialized(ServletContextEvent var1)方法,并向其传入一个ServletContextEvent对象。当应用停止时,ServletContext被销毁,此时Servlet容器也会自动地调用正在监听ServletContext的ServletContextListener的void contextDestroyed(ServletContextEvent var1)方法。

    为了验证我们的猜测,我们来随便写一个类,并且实现ServletContextListener接口,即实现监听ServletContext的功能:

    import javax.servlet.ServletContextEvent;

    import javax.servlet.ServletContextListener;

    public class MyListener implements ServletContextListener {

        @Override

        public void contextInitialized(ServletContextEvent servletContextEvent) {

            System.out.println("ServletContextListener.contextInitialized方法被调用");

        }

        @Override

        public void contextDestroyed(ServletContextEvent servletContextEvent) {

            System.out.println("ServletContextListener.contextDestroyed方法被调用");

        }

    }

    然后,在web.xml中注册我们自己写的这个MyListener:

    <?xml version="1.0" encoding="UTF-8"?>

    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

             version="4.0">

        <listener>

            <listener-class>MyListener</listener-class>

        </listener>

    </web-app>

    接下来,让我们启动一下Tomcat,看一看会发生什么吧!控制台打印信息如下:

     

    我们发现,当应用启动时,ServletContextListener.contextInitialized()方法被调用了。这其实是Servlet容器偷偷干的事情。那么,当我们停止Tomcat时,按照猜想,Servlet容器应该也会偷偷调用void contextDestroyed(ServletContextEvent var1)方法,来通知ServletContextListener监听器:ServletContext已经被销毁了。那么,事实是不是和我们猜想的一模一样呢?让我们来停止Tomcat的运行,看一看控制台的情况吧:

     

    我们发现,void contextDestroyed(ServletContextEvent var1)方法确实被Servlet容器调用了。因此,我们的猜想得到了证实。

    【进阶】ServletContextListener在Spring中的应用


    如果基础好一点的童鞋,或者已经学过Spring框架的同学,建议阅读下面的内容,没有学过Spring也没有关系,可以先学或者学完之后再回头来看一看,Spring容器是如何借用ServletContextListener这个接口来实例化的。

    首先让我们再来回顾一下ServletContext的概念,ServletContext翻译成中文叫做“Servlet上下文”或者“Servlet全局”,但是这个翻译我认为翻译的实在是有点牵强,也导致了许多的开发者不明白这个变量到底具体代表了什么。其实ServletContext就是一个“域对象”,它存在于整个应用中,并在在整个应用中有且仅有1份,它表示了当前整个应用的“状态”,你也可以理解为某个时刻的ServletContext代表了这个应用在某个时刻的“一张快照”,这张“快照”里面包含了有关应用的许多信息,应用的所有组件都可以从ServletContext获取当前应用的状态信息。ServletContext随着程序的启动而创建,随着程序的停止而销毁。通俗点说,我们可以往这个ServletContext域对象中“存东西”,然后也可以在别的地方中“取出来”。

    我们知道,Spring容器可以通过:

    ApplicationContext ctx=new ClassPathXmlApplicationContext("配置文件的路径");

    显示地实例化一个Spring IOC容器。也可以像下面一样,在web.xml中注册Spring IOC容器:

    <listener>

        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

            classpath:applicationContext.xml

        </param-value>

    </context-param>

    其中的监听器类【org.springframework.web.context.ContextLoaderListener】实现了ServletContextListener接口,能够监听ServletContext的生命周期中的“初始化”和“销毁”。注意,这个【org.springframework.web.context.ContextLoaderListener】监听器类当然不是我们自己写的哦,是人家Spring团队写的,我们只要拿来用就行了。当然,别忘记导入相关的Jar包。(spring-web-4.2.4.RELEASE.jar

    那么,Spring团队给我们提供的这个监听器类是如何实现:当ServletContext初始化后,Spring IOC容器也能跟着初始化的呢?怀着好奇心,让我们再来看一看【org.springframework.web.context.ContextLoaderListener】的内部实现情况吧。

     

     

    package org.springframework.web.context;

    import javax.servlet.ServletContextEvent;

    import javax.servlet.ServletContextListener;

    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {

        public ContextLoaderListener() {

        }

        public ContextLoaderListener(WebApplicationContext context) {

            super(context);

        }

    --------------------------------------------------------重点关注下面这里哦!-----------------------------------------------------------------------

        public void contextInitialized(ServletContextEvent event) {

            this.initWebApplicationContext(event.getServletContext());

        }

    --------------------------------------------------------重点关注上面这里哦!-----------------------------------------------------------------------

        public void contextDestroyed(ServletContextEvent event) {

            this.closeWebApplicationContext(event.getServletContext());

            ContextCleanupListener.cleanupAttributes(event.getServletContext());

        }

    }

    我们发现,【org.springframework.web.context.ContextLoaderListener】这个类实现了ServletContextListener接口中的两个方法,其中,当ServletContext初始化后, public void contextInitialized(ServletContextEvent event)方法被调用,接下来执行initWebApplicationContext(event.getServletContext())方法,但是我们发现这个方法并没有在这个类中声明,因此,我们再看一下其父类中是如何声明的:

     

    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    
        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
    
            throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!");
    
        } else {
    
            Log logger = LogFactory.getLog(ContextLoader.class);
    
            servletContext.log("Initializing Spring root WebApplicationContext");
    
            if (logger.isInfoEnabled()) {
    
                logger.info("Root WebApplicationContext: initialization started");
    
            }
    
    
    
            long startTime = System.currentTimeMillis();
    
    
    
            try {
    
                if (this.context == null) {
    
                    this.context = this.createWebApplicationContext(servletContext);
    
                }
    
    
    
                if (this.context instanceof ConfigurableWebApplicationContext) {
    
                    ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
    
                    if (!cwac.isActive()) {
    
                        if (cwac.getParent() == null) {
    
                            ApplicationContext parent = this.loadParentContext(servletContext);
    
                            cwac.setParent(parent);
    
                        }
    
    
    
                        this.configureAndRefreshWebApplicationContext(cwac, servletContext);
    
                    }
    
                }
    
    
    
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    
                ClassLoader ccl = Thread.currentThread().getContextClassLoader();
    
                if (ccl == ContextLoader.class.getClassLoader()) {
    
                    currentContext = this.context;
    
                } else if (ccl != null) {
    
                    currentContextPerThread.put(ccl, this.context);
    
                }
    
    
    
                if (logger.isDebugEnabled()) {
    
                    logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
    
                }
    
    
    
                if (logger.isInfoEnabled()) {
    
                    long elapsedTime = System.currentTimeMillis() - startTime;
    
                    logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
    
                }
    
    
    
                return this.context;
    
            } catch (RuntimeException var8) {
    
                logger.error("Context initialization failed", var8);
    
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
    
                throw var8;
    
            } catch (Error var9) {
    
                logger.error("Context initialization failed", var9);
    
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9);
    
                throw var9;
    
            }
    
        }
    
    }

     

     

     

     

    分析到这一步,我们发现Spring容器在这个方法中被实例化了。接下来,就让我们整理一下整体的思路:

    当Servlet容器启动时,ServletContext对象被初始化,然后Servlet容器调用web.xml中注册的监听器的

    public void contextInitialized(ServletContextEvent event)

    方法,而在监听器中,调用了this.initWebApplicationContext(event.getServletContext())方法,在这个方法中实例化了Spring IOC容器。即ApplicationContext对象。

    因此,当ServletContext创建时我们可以创建applicationContext对象,当ServletContext销毁时,我们可以销毁applicationContext对象。这样applicationContext就和ServletContext“共生死了”。

     

    参考资料


     

    【1】 维基百科-Servlet

    【2】Servlet、JSP和Spring MVC初学指南 【加】Buid Kurniawan 【美】Paul Deck 著 林仪明 俞黎敏 译 中国工信出版社 

     

    博客文章版权说明


     

     

     

    第一条 本博客文章仅代表作者本人的观点,不保证文章等内容的有效性。

    第二条 本博客部分内容转载于合作站点或摘录于部分书籍,但都会注明作/译者和原出处。如有不妥之处,敬请指出。

    第三条 征得本博客作者同意的情况下,本博客的作品允许非盈利性引用,并请注明出处:“作者:____转载自____”字样,以尊重作者的劳动成果。版权归原作/译者所有。未经允许,严禁转载

    第四条 对非法转载者,“扬俊的小屋”和作/译者保留采用法律手段追究的权利

    第五条 本博客之声明以及其修改权、更新权及最终解释权均属“扬俊的小屋”。

    第六条 以上声明的解释权归扬俊的小屋所有。

     

     

     

     

     

    展开全文
  • JavaWeb-简单学生信息管理系统的实现-Jsp+Servlet+MySql

    万次阅读 多人点赞 2019-04-05 14:58:42
    关注公众号:吾爱代码,回复Java学生管理系统,获取下载链接~ 关注公众号:吾爱代码,回复Java学生管理系统,获取下载链接~ 关注公众号:吾爱代码,回复Java学生管理系统,获取下载链接~

    关注公众号:吾爱代码,回复Java学生管理系统,获取下载链接~

    关注公众号:吾爱代码,回复Java学生管理系统,获取下载链接~

    运行截图:

     

    项目文件结构:

    获取 数据库连接类:

    package db;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    /**
     * @ClassName: DbConnect
     * @Author: Leo
     * @Description:
     * @Date: 2019/3/27 21:36
     */
    public class DbConnect {
        public static Connection connection;
        public static String url = "jdbc:mysql://localhost/stumanage?user=root&password=root"
                + "&useUnicode=true&characterEncoding=utf-8&useSSL=true";
    
        public static Connection getConnection() {
            try {
                Class.forName("com.mysql.cj.jdbc.Driver");
                connection = DriverManager.getConnection(url);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
    }
    

    对应学生的实体类:

    package entity;
    
    
    public class Student {
    
        private long id;
        private String name;
        private String sex;
        private String specialty;
        private String grade;
    
        public Student() {
        }
    
        public Student(long id, String name, String sex, String specialty, String grade) {
            this.id = id;
            this.name = name;
            this.sex = sex;
            this.specialty = specialty;
            this.grade = grade;
        }
    
        public Student(String name, String sex, String specialty, String grade) {
            this.name = name;
            this.sex = sex;
            this.specialty = specialty;
            this.grade = grade;
        }
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
    
        public String getSpecialty() {
            return specialty;
        }
    
        public void setSpecialty(String specialty) {
            this.specialty = specialty;
        }
    
    
        public String getGrade() {
            return grade;
        }
    
        public void setGrade(String grade) {
            this.grade = grade;
        }
    
    }
    

    登录界面jsp:

    <%--
      Created by IntelliJ IDEA.
      User: 24234
      Date: 2019/3/27
      Time: 19:26
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
    <html>
    <head>
        <title>学生管理系统</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">
    </head>
    <body>
    <center>
        <form action="/loginServer" method="post">
            <table>
                <tr>
                    <td>
                        用户名
                    </td>
                    <td>
                        <input type="text" name="admin">
                    </td>
                </tr>
                <tr>
                    <td>
                        密&nbsp&nbsp码
                    </td>
                    <td>
                        <input type="password" name="pwd">
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="center">
                        <input type="submit" value="登录">
                    </td>
                </tr>
    
            </table>
        </form>
    </center>
    </body>
    </html>
    

    登录servlet:(查询所有学生信息显示到主页面jsp)

    package servlet;
    
    import db.DbConnect;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * @ClassName: ${NAME}
     * @Author: Leo
     * @Description:
     * @Date: 2019/3/28 20:29
     */
    @WebServlet(name = "loginServer")
    public class loginServer extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html");
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            String admin = req.getParameter("admin");
            String pwd = req.getParameter("pwd");
            if (admin.equals("admin") && pwd.equals("123")) {
                Connection connection = DbConnect.getConnection();
                String sql = "SELECT * FROM STUDENT";
                PreparedStatement preparedStatement = null;
                ResultSet resultSet = null;
                try {
                    preparedStatement = connection.prepareStatement(sql);
                    resultSet = preparedStatement.executeQuery();
                    HttpSession httpSession = req.getSession();
    //                设置session有效时间为两小时
                    httpSession.setMaxInactiveInterval(7200);
                    httpSession.setAttribute("resultSet", resultSet);
                    resp.sendRedirect("loginAction.jsp");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            } else {
                resp.sendRedirect("index.jsp");
            }
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

    主页面jsp:

    <%@ page import="java.sql.ResultSet" %><%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/3/28
      Time: 14:31
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
    <% ResultSet resultSet = (ResultSet) session.getAttribute("resultSet");%>
    <html>
    <head>
        <title>学生管理系统</title>
        <link rel="stylesheet" type="text/css" href="css/table.css">
    </head>
    <body>
    <center>
        <table class="gridtable">
            <tr>
                <td align="center" colspan="6">学生信息</td>
            </tr>
            <tr>
                <td>姓名</td>
                <td>性别</td>
                <td>专业</td>
                <td>年级</td>
                <td align="center" colspan="2">操作</td>
            </tr>
            <%
                while (resultSet.next()) {
            %>
    
            <tr>
                <td><%=resultSet.getString("name")%>
                </td>
                <td><%=resultSet.getString("sex")%>
                </td>
                <td><%=resultSet.getString("specialty")%>
                </td>
                <td><%=resultSet.getString("grade")%>
                </td>
                <td><a href="selectServlet?id=<%=resultSet.getInt("id")%>">修改</a></td>
                <td><a href="deleteServlet?id=<%=resultSet.getInt("id")%>" onclick="return confirm('确定删除?')">删除</a></td>
            </tr>
            <%}%>
            <tr>
                <td align="center" colspan="6">
                    <a href="stuAdd.jsp">添加</a>
                </td>
            </tr>
        </table>
    </center>
    </body>
    </html>
    

    根据id查询数据库记录:

    package servlet;
    
    import db.DbConnect;
    import entity.Student;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * @ClassName: ${NAME}
     * @Author: Leo
     * @Description:
     * @Date: 2019/3/29 15:20
     */
    @WebServlet(name = "selectServlet")
    public class selectServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
            String id = request.getParameter("id");
            String sql = "SELECT * FROM STUDENT WHERE ID=?";
            Connection connection = DbConnect.getConnection();
            PreparedStatement preparedStatement = null;
            ResultSet resultset = null;
            Student student = null;
            try {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setInt(1, Integer.parseInt(id));
                resultset = preparedStatement.executeQuery();
                while (resultset.next()) {
                    String name = resultset.getString("name");
                    String sex = resultset.getString("sex");
                    String specialty = resultset.getString("specialty");
                    String grade = resultset.getString("grade");
                    student = new Student(Integer.parseInt(id), name, sex, specialty, grade);
                }
                HttpSession httpSession = request.getSession();
                httpSession.setAttribute("student", student);
                response.sendRedirect("stuEdit.jsp");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    

     修改学生信息jsp:

    <%@ page import="entity.Student" %><%--
      Created by IntelliJ IDEA.
      User: 24234
      Date: 2019/3/29
      Time: 14:59
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
    <html>
    <head>
        <title>修改学生信息</title>
        <link rel="stylesheet" type="text/css" href="css/table.css">
    </head>
    <body>
    <%Student student = (Student) session.getAttribute("student");%>
    <form action="/updateServlet" method="post">
        <center>
            <table class="gridtable">
                <tr>
                    <td align="center" colspan="2">
                        修改学生信息
                        <input type="hidden" name="id" value="<%=student.getId()%>">
                    </td>
                </tr>
                <tr>
                    <td>姓名</td>
                    <td><input type="text" name="name" value="<%=student.getName()%>"></td>
                </tr>
                <tr>
                    <td>性别</td>
                    <td><%if (student.getSex().equals("男")) {%>
                        <input type="radio" name="sex" value="男" checked="checked">男
                        <input type="radio" name="sex" value="女">女
                    </td>
                    <%
                    } else {
                    %>
                    <td>
                        <input type="radio" name="sex" value="男">男
                        <input type="radio" name="sex" value="女" checked="checked">女
                    </td>
                    <%}%>
                </tr>
                <tr>
                    <td>专业</td>
                    <td><input type="text" name="specialty" value="<%=student.getSpecialty()%>"></td>
                </tr>
                <tr>
                    <td>年级</td>
                    <td>
                        <%
                            if (student.getGrade().equals("大一")) {
                        %>
                        <select name="grade">
                            <option value="大一" selected="selected">大一</option>
                            <option value="大二">大二</option>
                            <option value="大三">大三</option>
                            <option value="大四">大四</option>
                        </select>
                        <%} else if (student.getGrade().equals("大二")) {%>
                        <select name="grade">
                            <option value="大一">大一</option>
                            <option value="大二" selected="selected">大二</option>
                            <option value="大三">大三</option>
                            <option value="大四">大四</option>
                        </select>
                        <%} else if (student.getGrade().equals("大三")) {%>
                        <select name="grade">
                            <option value="大一">大一</option>
                            <option value="大二">大二</option>
                            <option value="大三" selected="selected">大三</option>
                            <option value="大四">大四</option>
                        </select>
                        <%} else if (student.getGrade().equals("大四")) {%>
                        <select name="grade">
                            <option value="大一">大一</option>
                            <option value="大二">大二</option>
                            <option value="大三">大三</option>
                            <option value="大四" selected="selected">大四</option>
                        </select>
                        <%}%>
                    </td>
                </tr>
                <tr>
                    <td align="center" colspan="2">
                        <input type="submit" value="修改">
                    </td>
                </tr>
            </table>
        </center>
    </form>
    </body>
    </html>
    

    修改学生信息servlet:

    package servlet;
    
    import db.DbConnect;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * @ClassName: ${NAME}
     * @Author: Leo
     * @Description:
     * @Date: 2019/3/29 15:44
     */
    @WebServlet(name = "updateServlet")
    public class updateServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
            String id = request.getParameter("id");
            String name = request.getParameter("name");
            String sex = request.getParameter("sex");
            String specialty = request.getParameter("specialty");
            String grade = request.getParameter("grade");
            Connection connection = DbConnect.getConnection();
            String sql = "UPDATE STUDENT SET name=? , sex=? , specialty=? , grade=? where id=?";
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            try {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setInt(5, Integer.parseInt(id));
                preparedStatement.setString(1, name);
                preparedStatement.setString(2, sex);
                preparedStatement.setString(3, specialty);
                preparedStatement.setString(4, grade);
                int i = preparedStatement.executeUpdate();
                HttpSession httpSession = request.getSession();
                if (i == 1) {
                    String selectAll = "SELECT * FROM STUDENT";
                    preparedStatement = connection.prepareStatement(selectAll);
                    resultSet = preparedStatement.executeQuery();
                    httpSession.setMaxInactiveInterval(7200);
                    httpSession.setAttribute("resultSet", resultSet);
                    response.sendRedirect("loginAction.jsp");
                } else {
                    httpSession.setAttribute("message", "修改失败!");
                    response.sendRedirect("error.jsp");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    添加学生信息jsp:

    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/3/28
      Time: 14:50
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
    <html>
    <head>
        <title>添加学生信息</title>
        <link rel="stylesheet" type="text/css" href="css/table.css">
    </head>
    <body>
    <form action="/addServlet" method="post">
        <center>
            <table class="gridtable">
                <tr>
                    <td align="center" colspan="2">添加学生信息</td>
                </tr>
                <tr>
                    <td>姓名</td>
                    <td><input type="text" name="name"></td>
                </tr>
                <tr>
                    <td>性别</td>
                    <td>
                        <input type="radio" name="sex" value="男" checked="checked">男
                        <input type="radio" name="sex" value="女">女
                    </td>
                </tr>
                <tr>
                    <td>专业</td>
                    <td><input type="text" name="specialty"></td>
                </tr>
                <tr>
                    <td>年级</td>
                    <td><select name="grade">
                        <option value="大一">大一</option>
                        <option value="大二">大二</option>
                        <option value="大三">大三</option>
                        <option value="大四">大四</option>
                    </select></td>
                </tr>
                <tr>
                    <td align="center" colspan="2"><input type="submit" value="添加"></td>
                </tr>
            </table>
        </center>
    </form>
    </body>
    </html>
    

    添加学生信息servlet:

    package servlet;
    
    import db.DbConnect;
    import entity.Student;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * @ClassName: ${NAME}
     * @Author: Leo
     * @Description:
     * @Date: 2019/3/28 20:24
     */
    public class addServlet extends javax.servlet.http.HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html");
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            String name = request.getParameter("name");
            String sex = request.getParameter("sex");
            String specialty = request.getParameter("specialty");
            String grade = request.getParameter("grade");
            Student student = new Student(name, sex, specialty, grade);
            Connection connection = DbConnect.getConnection();
            String sql = "INSERT INTO student(name,sex,specialty,grade) values(?,?,?,?)";
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            try {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, student.getName());
                preparedStatement.setString(2, student.getSex());
                preparedStatement.setString(3, student.getSpecialty());
                preparedStatement.setString(4, student.getGrade());
                int i = preparedStatement.executeUpdate();
                HttpSession httpSession = request.getSession();
                if (i == 1) {
                    String selectSql = "SELECT * FROM STUDENT";
                    preparedStatement = connection.prepareStatement(selectSql);
                    resultSet = preparedStatement.executeQuery();
                    httpSession.setMaxInactiveInterval(7200);
                    httpSession.setAttribute("resultSet", resultSet);
                    response.sendRedirect("loginAction.jsp");
                } else {
                    httpSession.setAttribute("message", "添加失败!");
                    response.sendRedirect("error.jsp");
                }
    
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    

    删除学生信息servlet:

    package servlet;
    
    import db.DbConnect;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * @ClassName: ${NAME}
     * @Author: Leo
     * @Description:
     * @Date: 2019/3/29 16:05
     */
    @WebServlet(name = "deleteServlet")
    public class deleteServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
            String id = request.getParameter("id");
            String sql = "DELETE FROM STUDENT WHERE ID=?";
            Connection connection = DbConnect.getConnection();
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            HttpSession httpSession = request.getSession();
            try {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setInt(1, Integer.parseInt(id));
                int i = preparedStatement.executeUpdate();
                if (i == 1) {
                    String select = "SELECT * FROM STUDENT";
                    preparedStatement = connection.prepareStatement(select);
                    resultSet = preparedStatement.executeQuery();
                    httpSession.setMaxInactiveInterval(7200);
                    httpSession.setAttribute("resultSet", resultSet);
                    response.sendRedirect("loginAction.jsp");
                } else {
                    httpSession.setAttribute("message", "删除失败!");
                    response.sendRedirect("error.jsp");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    

    错误页面:

    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/3/28
      Time: 15:18
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
    <html>
    <head>
        <title>Error</title>
    </head>
    <body>
    <%
        String message = (String) session.getAttribute("message");
        out.print(message);
    %>
    </body>
    </html>
    

    web.xml

    <!DOCTYPE web-app PUBLIC
            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
            "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
        <display-name>Archetype Created Web Application</display-name>
        <servlet>
            <servlet-name>addServlet</servlet-name>
            <servlet-class>servlet.addServlet</servlet-class>
        </servlet>
        <servlet>
            <servlet-name>loginServer</servlet-name>
            <servlet-class>servlet.loginServer</servlet-class>
        </servlet>
        <servlet>
            <servlet-name>selectServlet</servlet-name>
            <servlet-class>servlet.selectServlet</servlet-class>
        </servlet>
        <servlet>
            <servlet-name>updateServlet</servlet-name>
            <servlet-class>servlet.updateServlet</servlet-class>
        </servlet>
        <servlet>
            <servlet-name>deleteServlet</servlet-name>
            <servlet-class>servlet.deleteServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>addServlet</servlet-name>
            <url-pattern>/addServlet</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>loginServer</servlet-name>
            <url-pattern>/loginServer</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>selectServlet</servlet-name>
            <url-pattern>/selectServlet</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>updateServlet</servlet-name>
            <url-pattern>/updateServlet</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>deleteServlet</servlet-name>
            <url-pattern>/deleteServlet</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

     

    展开全文
  • JavaWeb01_Servlet

    万次阅读 2020-09-17 15:08:30
    JavaWeb01_Servlet 入门项目: 创建Maven项目,选择webapp模板。 依赖: <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api<...
  • Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause e 1.controller...
  • javax.servlet jar包---解决找不到javax.servlet.*等问题

    万次下载 热门讨论 2013-07-29 23:17:32
    javax.servlet的jar包,解决找不到javax.servlet.*等问题的!欢迎下载!!
  • Servlet.service() for servlet jsp threw exception java.lang.NullPointerException at org.jaronsource.msneg.domain.SysUserExtend.getServiceExtend(SysUserExtend.java:216) at sun.reflect....
  • servlet api SUN官方网中文版程序文件

    万次下载 热门讨论 2010-08-20 17:33:36
    这个包是我根据sun官方servlet api 在线中文版整理的 api官方地址: http://doc.java.sun.com/DocWeb/#r/Java%20EE%205/javax.servlet/columnMain 该包是html文件类型,本人不会制作chm文件 入口文件是javax.servlet...
  • javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax/servlet/Servlet org.apache.jasper.servlet.JspServlet.service(JspServlet.java:268) javax.servlet.http.HttpServlet.service...
  • jsp+servlet实现简单登录页面功能Demo

    万次阅读 多人点赞 2018-05-28 17:55:16
    小白新路历程-1 [转载请联系本人]实现功能:模拟简单登录功能,登录成功跳转新页面,登录失败在原登录界面提示登录失败信息开发环境:eclipseTomcat-8.0预备知识:HTML标签,Servlet相关知识——请求的转发与重定向...
  • 背景: SpringBoot项目启动成功,访问API...控制台报错:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request 原因: Service层实现类未添加注解@Autowired。 @A...
  • 加入下面代码即可,注意PrintWriter获取输出流得在 request.setCharacterEncoding("UTF-8");//对返回浏览器数据没啥用,不过建议添加 respsonse.setHeader(...charset=UTF-8");//告知浏览器编码方式; response...
  • javax.servlet 的JAR包

    千次下载 热门讨论 2012-10-29 14:12:43
    javax.servlet JAR包,解决找不到 import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; jar包问题
  • 严重: Servlet [SendMailServlet] in web application [/SendMail] threw load() exception java.lang.ClassCastException: com.rl.mail.SendMailTask cannot be cast to javax.servlet.Servlet at org.apache....
  • Servlet 工程 web.xml 中的 servletservlet-mapping 标签

    万次阅读 多人点赞 2013-08-11 10:51:17
    url-pattern 标签中的值是要在浏览器地址栏中输入的 url,可以自己命名,这个 url 访问名为 servlet-name 中值的 servlet,两个 servlet-name 标签的值必须相同,因为通过 servlet 标签中的 servlet-nam...
  • Servlet3与Servlet4

    千次阅读 2019-03-11 09:38:28
    Servlet3 Servlet 3.0 新特性 异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另...
  • Servlet详细教程

    万次阅读 多人点赞 2018-04-15 21:09:44
    Servlet简介 servlet是Server Applet的简称,翻译过来就是服务程序.好吧,这么说你可能还是不太懂,简单的讲,这个servlet是运行在服务器上的一个小程序,用来处理服务器请求的.进一步讲,我们知道,一般的网页...
  • 严重: Allocate exception for servlet [Give Horoscope Servlet] java.lang.ClassNotFoundException: Lab30.HoroscopeServlet at org.apache.catalina.loader.WebappClassLoaderBase.loadClass...
  • JSP + Servlet + JDBC + Mysql 实现增删改查

    万次阅读 多人点赞 2018-04-24 20:56:24
    Servlet是一个特殊的Java程序,它运行于服务器的JVM中,能够依靠服务器的支持...JSP本质上是Servlet的一种简易形式,JSP会被服务器处理成一个类似于Servlet的Java程序,可以简化页面内容的生成。 Servlet和JSP最主...
  • <servlet-name>TwoServlet</servlet-name> <servlet-class>com.fh.TwoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TwoServlet</servlet-name> <url-pattern>/* </servlet-...
  • Java Web图书管理系统总结(jsp+servlet+jdbc+javabean+dao)

    千次阅读 多人点赞 2019-07-06 15:02:48
    这周进行了课程实践,题目是老掉牙的图书管理系统,因为一些原因,原本打算做前端的我做了全栈,虽然最后交的不是我写的,就当练手了。 首先上部分运行截图: 前端部分:采用bootstrap与layui结合,导航栏,...
  • servlet总结

    千次阅读 2016-08-24 00:44:20
    1、把 servlet-api.jar 包拷贝到工程下,servlet-api.jar 在tomcat 安装包bin目录下可以找到。 2、把servlet-api.jar 添加到工程 Java Build Path 中。 3、修改工程编译的class文件存放位置到WEB-INF目录下的...
  • Servlet Faces Servlet is currently unavailable

    千次阅读 2011-11-17 18:25:08
    [11-11-17 18:26:12:937 CST] 0000002f ApplicationDe I ApplicationDeploymentController perform ApplicationDeploymentController: performing appcontexts refresh [11-11-17 18:26:16:437 CST] 0000002f AdminH
  • javax.servlet.ServletException: Error instantiating servlet class servletDemo.demo org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.valves...
  • servlet没有.class文件,我也不知道怎么回事,说要配置web.xml文件的就不要来了 ,因为是servlet3.0不需要配置,唉,直接上图吧,求大神指教 第一张是错误页面 ![图片说明]...
  • Spring Boot Servlet

    万次阅读 多人点赞 2016-01-12 09:19:46
    Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet、Filter、Listener、Interceptor 等等。当使用Spring-Boot时,嵌入式Servlet容器通过扫描注解的方式注册Servlet、Filter和Servlet...
  • servlet-api jar包

    千次下载 热门讨论 2011-08-29 11:16:51
    servlet-api.jar,在java web开发时,如果有用到servlet编程的需要导入的jar包
  • Servlet入门总结及第一个Servlet程序

    万次阅读 多人点赞 2015-04-20 17:26:08
    Servlet定义:Servlet是基于Java技术的Web组件,由容器管理并产生动态的内容。Servlet引擎作为WEB服务器的扩展提供支持Servlet的功能。Servlet与客户端通过Servlet容器实现的请求/响应模型进行交互.

空空如也

1 2 3 4 5 ... 20
收藏数 253,242
精华内容 101,296
关键字:

servlet