servlet -> (1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/belovehejian/article/details/78681608

servlet是非线程安全的,其内部维护着一个线程池。Servlet并不是单例,只是容器让它只实例化一次,变现出来的是单例的效果而已.如果在配置文件web.xml当中对一个servlet声明了多次,那么将会有多个servlet实例。而且如果servlet实现了SingleThreadModel接口,那么最多会创建20个实例。还有几十如果在分布式环境当中部署的话,也会出现多个实例。所以Servlet并不是单例的。不过一般来说,一个servlet只有一个实例。

servlet运行过程为:

  1. 客户端发送请求至服务端
  2. 服务端根据web.xml的配置,以及请求的路径,找到对应的处理类,将请求的资源进行封装,封装成 HttpServletRequest 然后将其转发至对应的 servlet 处理类.
  3. Servlet 引擎调用指定 servlet 中的 service() 方法处理用户发送过来的,已封装好的 request 中的数据.
  4. 处理好的数据在返回之前会封装成 response 对象.然后将其提交给 servlet 服务器.数据是动态生成的.
  5. 服务器返回数据给客户端呈现

servlet对多线程的处理为:

当接收到请求时,从连接池中获取一个连接,接收该请求,往下执行。请求在执行过程中,若有新的请求过来,那么将再次从池中获取一个连接,往下执行。所以 servlet 中的 service 方法可能会同时在多个线程当中执行。所以在此种请求中尽量避免使用全局变量使用局部变量,避免临界资源的出现。


servlet的生命周期方法

public void init(ServletConfig config) throws ServletException;该方法指挥在第一次初始化的时候被调用一次

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;该方法会在每次调用的时候被调用。

public void destroy();该方法会在销毁servlet实例的时候调用一次

当servlet被部署在sservlet容器当中的时候,由容器来控制servlet的生命周期,除非有特殊限定,否则在容器启动的时候是不会加载servlet的,只有在第一次被调用的时候会进行加载并且实例化,所以一般来说第一次访问所用的时间会稍微大于后续访问的时间。而且一般也不会从容器中删除,只有关闭容器的时候才会进行删除。

servlet的实现有3种方式

  1. 实现 javax.servlet.Servlet 接口
  2. 继承 javax.servlet.GenericServlet类
  3. 继承继承 javax.servlet.HttpServlet类

通常都是以第三种方式来编写我们的servlet类。而且servlet中的大多数方法均不是我们来调用的。而是交由web容器来调用的。如:Tomcat。我们只负责编写该方法的具体实现。


小例子

  1. 利用eclipse创建一个maven工程,导入相应的jar包。
    <dependency>
      		<groupId>javax.servlet</groupId>
      		<artifactId>javax.servlet-api</artifactId>
      		<version>3.1.0</version>
      	</dependency>

  2. 配置文件 web.xml 中做些相应的配置
    <servlet>
    		<servlet-name>myservlet</servlet-name>	<!-- 类的别名 -->
    		<servlet-class>com.xh.servlet.MyServlet</servlet-class>	<!-- 实际处理请求的类 -->
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>myservlet</servlet-name>	<!-- 类的别名,与上面一致 -->
    		<url-pattern>/myservlet</url-pattern>	<!-- 匹配的路径名 -->
    	</servlet-mapping>

  3. 编写实际的类,继承 javax.servlet.HttpServle,重写servlet中的3个生命周期方法,可在方法内做相应的处理
    package com.xh.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyServlet extends HttpServlet {
    
    	@Override
    	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		System.out.println("service()被调用......");
    	}
    
    	@Override
    	public void destroy() {
    		System.out.println("销毁方法 destroy()被调用......");
    	}
    
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		System.out.println("初始化方法 init().....");
    	}
    
    }
  4. 然后启动容器tomcat便可以进行访问,输入访问地址:localhost:8080/servlerTest/myservlet 便可在控制台看到输出。

servlet初始化

servlet第一次被调用的时候,容器会实例化被请求的servlet,并进行初始化(servlet一旦被实例化会立即进行初始化),会调用init(ServletConfig)方法。ServletConfig是Servlet代表当前Servlet在配置文件当中的信息,可获取该Servlet一些相关的信息。初始化也可以在配置文件中配置容器启动的时候进行初始化。只需在配置文件中加上

<load-on-startup>1</load-on-startup>

扫描二维码关注公众号,回复: 4910647 查看本文章

servlet调用

service方法中会接收2个参数HttpServletRequest(请求对象)HttpServletResponse(响应对象),这2个参数是由服务器帮我们创建的。该方法会被多次调用。任何请求过来时,都会经过这个方法的处理。但是又有些不同之处。

原生的service()方法并不会真正的处理业务,而是进行转向功能,它判断接收到的请求是属于哪种类型(POST,GET,或者是其他的。),然后将请求转向到对应的doPost,doGet等一些与请求类型相对应的方法中处理业务。

如果重写service()方法:无论请求类型是什么,都不会进行转向,而是会真正的在我们重写的service()方法中去处理业务逻辑与数据。所以当我们选择重写该方法,那么具体的处理逻辑将在此方法内进行。

如果不重写service()方法:将会调用我们编写的servlet的父类的service()方法进行转向,转向到具体的与请求类型对应的方法处理。所以我们需要要重写doPost或者doGet等一些与请求类型相对应的方法。

Servlet销毁

当关闭web应用的时候会销毁该web应用中的servlet,此时会调用destroy()方法进行销毁。


web.xml配置文件

在应用程序中,我们都会配置一个web.xml配置文件,该配置文件针对该web应用程序作了一些相关的配置。该文件是该web应用程序特有的一些动作。当我们将该web项目部署到tomcat容器当中的时候,该web.xml其实还有一个父配置文件。位于${CATALINA_HOME}\conf\web.xml。它定义了所有部署到该容器当中的web项目动作。该父web.xml配置文件的内容可参考官方文档。

ServletConfig

每一个servlet实例都会有一个与之对应的 servletConfig上下文。描述该servlet的一些基本信息。可以获取与之对应的servlet的一些参数信息。当servlet对象创建的时候该对象也被创建。它与servlet是 1:1的关系。也就是说,一个web应用程序内,有多少个servlet实例,就会有多少个servletConfig。servlet实例销毁时,与之对应的servletConfig也就随之消失。

servletContext 全局对象

每一个web应用都会有一个 servletContext 上下文,不管该web应用程序当中有多少个 servlet实例,该 servletContext 只有一个。可以在该web程序的任何Servlet当中获取到该servletContext 对象,可以在多个servlet当中传递数据。在tomcat启动时,该对象就被创建,tomcat关闭时对象被销毁。可以获取该web应用当中的一些初始化参数。

域对象

域对象必须要有存取数据的功能,域对象内部其实有一个Map对象的功能。ServletContext其实就是4个域对象之一。其余3个为 PageContext、ServletRequest、HttpSession。当假设域对象当中有一个 key 为 A,value为 a 的键值对时,如果在次存入一个 key 为 A,value 为 b 的值,那么本次存入会覆盖已有的值。该存取方法与Map键值对相似。

转发与重定向

转发

  1. 通过运用javax.servlet.ServletContext接口的getRequestDispatcher方法,将一个包含路径的String传递给其它资源。该路径是相对于ServletContext的根路径的。
  2. 通过运用javax.servlet.ServletRequest接口的getRequestDispatcher方法,将一个包含路径的String传递到其它资源。该路径是相对于当前的HTTP请求的。
  3. 通过运用javax.servlet.ServletContext接口的getNamedDispatcher方法,传递一个包含其它资源名字的String。\

但要注意,你只有在客户端没有输出时才可以调用forward方法。如果当前页面的缓冲区(buffer)不是空的,那么你在调用forward方法前必须先清空缓冲区。否则,会抛出一个IllegalStateException。forward方法也可以用来将请求发送到一个静态的页面。

转发是发生在同一个web应用当中,无法转发至其他的应用程序当中,转发不改变浏览器的URL地址,用户无法感知。request与response可以共享。只需请求服务器一次。

重定向

重定向可以定向到外部web应用当中。通过response来进行重定向。当浏览器发起对服务器的请求时,如果有重定向,那么在该servlet当中处理完业务逻辑之后,会返回一个状态码给客户端,告知客户端在发起一次请求到重定向指定的地址,以便进行重定向。所以重定向对于客户端来说会发起2次请求。而且浏览器地址会出现变化。用户能直观的感知到。

















猜你喜欢

转载自blog.csdn.net/belovehejian/article/details/78681608
今日推荐