servlet学习(一)

本文介绍了Java Servlet的基础知识,包括Servlet的定义、Servlet容器的作用、Servlet的生命周期和主要方法。Servlet是单实例多线程的,运行在服务器端,依赖于Servlet容器。文中详细讲解了Servlet的init(), service(), destroy()等方法,以及ServletConfig接口和ServletContext对象的作用。最后讨论了Servlet的简单实例和生命周期,并对比了请求转发与重定向的区别。" 111747776,10295343,使用Swiper实现移动端触屏滑动选项卡,"['移动端开发', 'JavaScript库', '触摸交互', '前端框架', 'UI设计']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java Servlet(Java服务器小程序)是一个基于java技术的Web组件,运行在服务器端,由servlet容器所管理,用于生成动态的内容。

Servlet容器也称Servlet引擎,是Web服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务。

Servlet不能独立运行,它必须被部署到Servlet容器中,由容器来实例化和调用Servlet的方法,Servlet容器在Servlet的生命周期内包容和管理Servlet。

用户通过在浏览器的地址栏输入URL来访问Servlet,Web服务器接收到该请求后,并不是将请求直接交给Servlet,而是交给Servlet容器。Servlet容器实例化Servlet,调用Servlet的一个特定方法对请求进行处理,并产生一个响应。这个响应由Servlet容器返回给Web服务器,服务器包装这个响应,以HTTP响应的形式发送给Web浏览器。
这里写图片描述

Servlet是单实例多线程的运行方式,每个请求在一个独立的线程中运行,而提供服务的Servlet实例只有一个。
Servlet不是独立的应用程序,都没有main()方法;不是由用户或程序员直接调用,而是生存在容器中,由容器管理;具有生命周期,包括init()方法和destroy()方法。

Servlet接口
编写一个servlet,要实现javax.servlet.Servlet接口,该接口定义了5个方法:

1、public void init(ServletConfig config) throws ServletException
在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象。主要是为了让Servlet对象在处理客户请求前可以完成一些初始化的工作,例如,建立数据库的连接,获取配置信息等。
对于每一个Servlet实例,init()方法只能被调用一次。方法有一个ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。

2、public void service(ServletRequest req,ServletResponse res)throws ServletException,IOException
容器调用service()方法来处理客户端的请求,在service()方法被容器调用之前,必须确保init()方法正确完成。Servlet对象通过ServletRequest对象得到客户端的相关信息和请求信息;在对请求处理后,调用ServletResponse对象的方法设置响应信息。

3、public void destroy()
当容器检测到一个servlet对象应该从服务器中被移除的时候,容器会调用该对象的destroy()方法,以便让servlet对象可以释放它所使用的资源,保存数据到持久存储设备中。
一旦destroy()方法被调用,容器不会再把其他的请求发送给该对象。容器会释放这个servlet对象,在随后的时间内,该对象会被垃圾回收器所回收。如果需要该servlet再次为客户端服务,容器会重新产生一个servlet对象来处理客户端的请求。

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

5、public String getServletInfo()
返回一个包括关于servlet信息的字符串。

一个简单的servlet实例

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>

1、HelloWorldServlet类

//实现Servlet接口
public class HelloWorldServlet implements Servlet {
    private ServletConfig servletConfig;
    public void destroy(){}

    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    public String getServletInfo(){
        return null;
    }

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

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //得到PrintWriter对象,Servlet使用输出流产生响应
        PrintWriter out= servletResponse.getWriter();

        out.println("hello ");
        out.close();
    }
}

2、部署HelloWorldServlet
Servlet是Web应用程序中的一个组件,一个Web应用程序是由一组Servlet、HTML、类以及其他资源组成的运行在Web服务器上的完整的应用程序,以一种结构化的有层次的目录形式存在。

组成Web应用程序的这些资源文件要部署在相应的目录层次中,根目录代表了整个Web应用程序的根。

将Web应用程序的目录放到tomcat的webapps目录下,在该目录下的每一个子目录都是一个独立的Web应用程序,子目录的名字就是Web应用程序的名字,也称为Web应用程序的上下文根。用户通过Web应用程序的上下文根来访问Web应用程序中的资源。
这里写图片描述
在WEB-INF目录下的classes和lib目录都可以存放java的类文件,在Servlet容器运行时,Web应用程序的类加载器将首先加载classes目录下的,其次才是lib目录下的类。如果这两个目录下存在同名的类,起作用的将是classes目录下的类。

WEB-INF目录并不属于Web应用程序可以访问的上下文路径的一部分,对客户端来说,这个目录是不可见的。但是WEB-INF目录下的内容对于Servlet代码是可见的。

Web应用程序的配置和部署是通过web.xml文件来完成的。web.xml文件被称为web应用程序的部署描述符。它可以包含如下的配置和部署信息:
1、servletContext的初始化参数
2、session的配置
3、servlet/jsp的定义和映射
4、监听器类
5、其他一些配置

<web-app>
  <!--可以包含多个servlet和servlet-mapping元素,用于部署多个servlet-->
  <servlet>
    <!--在同一个Web应用程序中,每一个servlet的名字必须唯一,该元素内容不能为空-->
      <servlet-name>HelloWorldServlet</servlet-name>
    <!--用于指定servlet类的完整限定名,提示给出包名-->
      <servlet-class>org.wdz.test.servlet.HelloWorldServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <!--必须与servlet中指定的名字相同-->
    <servlet-name>HelloWorldServlet</servlet-name>
    <!--指定对应于servlet的URL路径,该路径是相对于上下文的根路径-->
    <url-pattern>/jsp/index.jsp</url-pattern>
  </servlet-mapping>
</web-app>

3、访问HelloWorldServlet
直接通过浏览器进行访问,输入地址:
http://localhost:8080/servletTest/jsp/index.jsp
在访问Servlet和jsp的时候,Servlet和jsp的文件名都是区分大小写的。

ServletConfig
一个servlet只有一个servletConfig对象,Servlet容器使用servletConfig对象在servlet初始化期间向它传递配置信息。它定义了四个方法:
1、public String getInitParameter(String name)
返回名字为name的初始化参数的值。初始化参数的值在web.xml中进行配置,如果不存在,则返回null。

2、public Enumeration getInitParameterNames()
返回servlet所有初始化参数的名字的枚举集合。否则返回空枚举集合。

3、public ServletContext getServletContext()
返回servlet上下文对象的引用。

4、public String getServletName()
返回servlet的名字,这个名字在web.xml 中指定的。否则返回的将是servlet的类名。

GenericServlet
通过实现Servlet接口来编写的servlet类,需要实现servlet接口中定义的5个方法。为了简化servlet的编写,可以使用GenericServlet。它给出了除service()方法外的其他4个方法的简单实现。它定义了一个通用的、不依赖于具体协议的servlet。它实现了servlet接口和servletConfig接口。
如果要编写一个通用的Servlet,只需要从GenericServlet类继承。并实现其中的抽象方法service()。
在GenericServlet类中,定义了点歌重载的init()方法:
1、public void init(ServletConfig config)throws ServletException
2、public void init()throws ServletException
第一个方法是servlet接口中的实现。在这个方法中,先将ServletConfig 对象保存在一个transient实例变量(transient的用途在于:阻止实例中那些用此关键字声明的变量持久化)中,然后调用第二个无参的init()方法。
通常只需要重写第二个不带参数的init()方法就可以了。

HttpServlet
绝大多数的网络应用中,都是客户端通过HTTP协议去访问服务器端的资源,所编写的servlet也主要是应用于HTTP协议的请求和响应。可以使用HttpServlet,它继承自GenericServlet类,用于创建适合Web站点的Http Servlet。

在HttpServlet类中提供两个重载的service()方法
1、public void service(ServletRequest req,ServletResponse res)throws ServletException,IOException
2、protected void service(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException

当容器接受到一个针对HttpServlet对象的请求时,调用该对象的顺序是:
1、调用公共的public service()方法
2、在公共的service方法中,首先将参数类型转换为HttpServletRequest和HttpServletResponse。然后调用保护protected service方法,将转换后的参数类型传递进去。
3、在保护protected service方法中,首先调用httpservletRequest对象的getMethod方法,获取HTTP请求方法的名字,然后根据请求方法的类型,调用相应的doXxx方法。

因此,在编写HttpServlet的派生类时,不需要覆盖service()方法,只需要重写相应的doXxx()方法就行。
HttpServlet虽然是抽象类,但是在这个类中没有抽象的方法,其中所有的方法都是已经实现的。

HttpServlet提供的7中处理方法:doGet、doPost、doHead、doPut、doDelete、doTrace、doOptions

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        .........
        }
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException

通常在提交表单时,如果数据量小,而又没有安全性的考虑,可以采用get提交表单,提交的数据会被附加到请求URL的末端,作为查询字符串发送到服务器端。这和直接在浏览器中输入附加查询字符串的URL的效果是一样的。
反之,数据量大,有安全考虑,应该采用post提交。

简单实例(一)
1、html页面

<body>
    <!--action的值,可以是绝对 URL - 指向其他站点(比如 src="www.example.com/example.htm")-->
    <!--也可以是 相对 URL - 指向站点内的文件(比如 src="example.htm")-->
    <!--在这里该路径是相对于根路径,要与配置文件中对应-->
    <!-- <form action="jsp/index.jsp" method="get"> -->
      <form action="welcome" method="get">
         用户名:<input type="text" name="username"><br>
         <input type="submit" value="提交">
     </form>
</body>

2、WelcomeServlet

public class WelcomeServlet extends HttpServlet {
    //用于接收初始化参数
    private String greeting;
    //重写无参的init方法
    public void init(){
        //获取web.xml中配置的参数
        greeting=getInitParameter("greeting");
    }
    public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException,IOException{
        //设置请求编码
        req.setCharacterEncoding("gb2312");
        //获取请求中参数的值,必须和表单中文本输入控件的名字保持一致
        String username=req.getParameter("username");
        //设置响应文本类型,这个方法在getWrite之前调用,若是在之后设置,那么设置无效
        res.setContentType("text/html;charset=UTF-8");
        PrintWriter out=res.getWriter();
        out.print(greeting+","+username);
        out.close();
    }
    public void doPost(HttpServletRequest req,HttpServletResponse res)throws ServletException,IOException{
        doGet(req,res);
    }
}

3、web.xml配置文件

 <servlet>
    <servlet-name>WelcomeServlet</servlet-name>
    <servlet-class>org.wdz.test.servlet.WelcomeServlet</servlet-class>
    <init-param>
      <param-name>greeting</param-name>
      <param-value>welcome you</param-value>
    </init-param>
  </servlet>

<servlet-mapping>
    <servlet-name>WelcomeServlet</servlet-name>
    <url-pattern>/welcome</url-pattern>
  </servlet-mapping>

Servlet生命周期
Servlet运行在Servlet容器中,其生命周期由容器来管理。
(一)加载和实例化
Servlet容器负责加载和实例化Servlet。当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求,创建Servlet实例。容器是通过反射机制来创建Servlet实例,调用的是Servlet的默认构造方法,因此在编写servlet类的时候,不应该提供带参数的构造方法。
(二)初始化
在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet在处理客户端请求前完成一些初始化的工作。对于每一个Servlet实例,init()方法只会被调用一次。
(三)请求处理
Servlet容器调用Servlet的service()方法对请求进行处理。在service()方法调用之前,init()方法必须成功执行。
(四)服务终止
当容器检测到一个Servlet实例应该从服务中被移除的时候,容器会调用实例的destroy()方法。以便让该实例可以释放它所使用的资源。之后容器会释放这个Servlet实例,该实例会被垃圾回收器所回收。如果需要再次使用该Servlet处理请求,那就要重新创建一个Servlet实例。

在整个Servlet的生命周期过程中,创建Servlet实例、调用实例的init()方法和destroy()方法都只进行一次。

Servlet上下文
一个Web应用程序只有一个ServletContext对象,而且该对象可以被Web应用程序中的所有Servlet所访问,因此可以使用ServletContext对象来保存一些需要在Web应用程序中共享的信息。

        //统计页面的访问量
        ServletContext context=getServletContext();
        Integer count=null;
        synchronized (context){
            count=(Integer) context.getAttribute("counter");
            if(count==null){
                count=new Integer(1);
            }else{
                count=new Integer(count.intValue()+1);
            }
            context.setAttribute("counter",count);
        }

请求转发
RequestDispatcher对象由Servlet容器创建,用于封装一个由路径所标识的服务器资源。利用RequestDispatcher对象,可以把请求转发给其他的Servlet或JSP页面。RequestDispatcher接口定义了两种方法:

1、public void forward(ServletRequest req,ServletResponse res)throws ServletException,IOException
该方法用于将请求从一个Servlet传递给服务器上的另外的Servlet、JSP页面或HTML文件。这个方法必须在响应被提交给客户端之前调用。在forward方法被调用后,原先在响应缓存中的没有提交的内容会被自动清除。
froward()方法将请求转发给其他的Servlet,将由被调用的Servlet负责对请求作出响应,而原先的Servlet的执行则终止。

2、public void include(ServletRequest req,ServletResponse res)throws ServletException,IOException
与forward方法的区别是:利用include()方法将请求转发给其他的Servlet,被调用的Servlet对该请求作出的响应将并入原先的响应对象中,原先的Servlet还可以继续输出响应信息。

获得RequestDispatcher对象的方式:
1、利用ServletRequest接口
//路径参数既可以是相对于上下文根路径,也可以是相对于当前Servlet的路径
public RequestDispatcher getRequestDispatcher(String path)
2、利用ServletContext接口
//路径必须以斜杠(/)开始,相对于当前上下文根的路径
public RequestDispatcher getRequestDispatcher(String path)
public RequestDispatcher getNamedDispatcher(String name)

public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException,IOException{
        res.setContentType("text/html;charset=UTF-8");
        PrintWriter out=res.getWriter();
        out.println("<html><head><title>");
        out.println("登录页面");
        out.println("</title></head><body>");

        String name=req.getParameter("name");
        String pass=req.getParameter("password");

        if("zhansan".equals(name)&&"123456".equals(pass)){
            ServletContext context=getServletContext();
            //以斜杠开头,相对于当前上下文的根路径
            RequestDispatcher rd=context.getRequestDispatcher("/jsp/index.jsp");
            //forward执行后,控制权转移,之前的登录页面的输出代码将自动被清除,剩余的代码不再执行
            rd.forward(req,res);
        }else{
            //相对于当前servlet的路径
            RequestDispatcher rd=req.getRequestDispatcher("welcome");
            //include执行后,控制权暂时转移,新的Servlet的输出会合并到本次输出之中。
            //因此新的servlet输出中就不要包括<html><body>等元素
            rd.include(req,res);
        }
        out.print("</body></html>");
        out.close();
    }

sendRedirect()和forward()的区别
HttpServletResponse接口的sendRedirect()方法和RequestDispatcher接口的forward()方法都可以利用另外的资源(Servlet/JSP/HTML页面)来为客户端进行服务。但是两种方法有本质区别:
这里写图片描述
可以看出,调用sendRedirect()方法,实际上是告诉浏览器Servlet2的所在位置,让浏览器重新访问Servlet2。浏览器地址栏中显示的URL是重定向之后的URL。
这里写图片描述
交互过程如下:
1、浏览器访问Servlet1。
2、Servlet1想让Servlet2对客户端的请求进行响应,于是调用forward()方法,将请求转发给Servlet2进行处理。
3、Servlet2对请求作出响应。
在浏览器地址中,显示的URL始终是原始请求的URL。
sendRedirect()方法不但可以在位于同一主机上的不同Web应用程序之间进行重定向,而且还可以将客户端重定向到其他服务器上的Web应用程序资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值