Servlet的来龙去脉

版权声明:欢迎转载评论~哈哈哈哈请标明出处呀 https://blog.csdn.net/legendaryhaha/article/details/89219565


Servlet简介

Servlet现在挺少人用了,但是在很多地方有它的影子。Tomcat内置了Servlet容器,SpringMVC的Controller也是对Servlet的封装,了解Servlet可以帮助我们更加了解java web框架的运行机制。

Servlet是运行在服务端的程序,用于响应客户端的请求,本质上就是一个Java文件。


Servlet生命周期

Servlet容器启动后,会根据你的XML配置文件,装载你的Servlet,此时调用init方法,整个生命周期就只调用一次。当接收到Web Browser发送的请求时,会调用service()方法,即service方法可以调用多次。destory整个生命周期也只执行一次,譬如:web服务器关闭。

注:Servlet是长期驻留在内存里的,这也就是说destory不是随便就能用的,当Servlet实例被加载,servlet对象就会长期存在于服务器的内存里,直到服务器关闭。

在这里插入图片描述


Servlet 各方法的作用

init方法: 是在servlet实例创建时调用的方法,用于创建或打开任何与servlet相的资源和初始化servlet的状态,Servlet规范保证调用init方法前不会处理任何请求

Service方法:是servlet真正处理客户端传过来的请求的方法,由web容器调用, 根据HTTP请求方法(GET、POST等),将请求分发到doGet、doPost等方法

destory方法:是在servlet实例被销毁时由web容器调用。Servlet规范确保在destroy方法调用之前所有请求的处理均完成,需要覆盖destroy方法的情况:释放任何在init方法中打开的与servlet相关的资源存储servlet的状态

注意:Servlet继承HttpServlet时如何处理父类的service方法(即重载父类的哪些方法),一般我们都是不对service方法进行重载(没有特殊需求的话),而只是重载doGet()之类的doXxx()方法,减少了开发工作量。但如果重载了service方法,doXXX()方法也是要重载的。即不论是否重载service方法,doXXX()方法都是需要重载的。


创建Servlet对象的过程

上面简述了Servlet大致的运行流程后,我们可以知道Servlet是需要依赖Servlet容器的,比较流行的内置Servlet容器的Web容器如Tomcat,它在加载Servlet创建其对象时,流程如下:读取XML中Servl et的配置信息配置,运用Java的反射(什么是反射?这个很经典的建议好好学学)机制创建对象,然后初始化init,有请求时就执行service,最后根据需要销毁destory。

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

具体应用

我是在eclipse中创建的,idea也差不多,创建一个web projiect,然后勾选下面选项,快速生成一个基本web.xml基本模板。
在这里插入图片描述
生成的web.xml的配置文件很简单,需要我们自己添加<servlet><servlet-mapping>节点。
在这里插入图片描述

<servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <!-- 你servlet名称 -->
    <servlet-name>ServiceTest</servlet-name>
    <!-- 你servlet路径 -->
    <servlet-class>com.fang.servlet.ServiceTest</servlet-class>
  </servlet>
  <!-- 把servlet程序映射到一个URL地址上,url可以自定义,只是提供一个让外界访问的路径而已 -->
  <servlet-mapping>
    <servlet-name>ServiceTest</servlet-name>
    <url-pattern>/test.action</url-pattern>
  </servlet-mapping>	

编写servlet,这里很简单的一个例子,没有骚操作,就是在页面输出创建成功,可能会中文乱码,需要response设置一下字体格式,我是GBK,你可能是UTF-8,具体根据自己的项目的字体格式而定。

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServiceTest extends HttpServlet{
   
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.setCharacterEncoding("GBK");
        //创建输出流
        PrintWriter out = resp.getWriter();
        out.print("servlet创建成功");
    }

}

我的Tomcat端口改过,默认为8080,然后是项目名,加你的web.xml中的映射,一个servlet可以有多个映射,具体的做法就是设置多个servlet-mapping
在这里插入图片描述


另外,说一下Tomcat对servlet的装载吧,默认是延迟加载的,简单的测试方法就是在你的servlet中的构造方法输出点东西,然后不加 <load-on-startup>看它有木有输出,经过我测试,发现没有,但当我设置<load-on-startup>0</load-on-startup>时,Tomcat启动后就立即输出了:

(1)第一个是自动装载,如果你有多个servlet,但想要某些Servlet在Servlet容器启动时就先加载,需要在web.xml下它的标签里中,添加优先级代码,其中数字越小表示该servlet的优先级越高,就越会先装载

<Servlet>
    <load-on-startup>0</load-on-startup>
</Servlet>

(2)Servlet容器启动后,直到客户首次向某个Servlet发送请求时,Tomcat容器才会去加载它,即延迟加载,什么都别配置就好,默认的:

(3)Servlet类文件被更新后,重新自动加载,这个要找到Tomcat下的context.xml修改标签:

在这里插入图片描述
默认就是true的,如果你的项目过大,不想修改一点地方,就得等上一杯咖啡的功夫进行初始化,可以把它设置为false。


servlet地址重写

Java Servlet API 中引用 Session 机制来追踪客户的状态。Servlet API 中定义了 javax.servlet. http.HttpSession 接口,Servlet 容器必须实现这个接口。当一个 Session 开始时,Servlet 容器将创建一个 HttpSession 对象,Servlet 容器为 HttpSession 分配一个唯一标识符,称为 Session ID。

Servlet 容器将 Session ID 作为 Cookie 保存在客户的浏览器中(会从服务器发送到浏览器中)。每次客户发出 HTTP 请求时,Servlet 容器可以从 HttpRequest 对象中读取 Session ID,然后根据 Session ID 找到相应的 HttpSession 对象,从而获取客户的状态信息。

当客户端浏览器中禁止 Cookie,Servlet 容器无法从客户端浏览器中取得作为 Cookie 的 Session ID,也就无法跟踪客户状态。 于是,Java Servlet API 中提出了跟踪 Session 的另一种机制,如果客户端浏览器不支持 Cookie,Servlet 容器可以重写客户请求的 URL,把 Session ID 添加到 URL 信息中。

其中,HttpServletResponse 接口提供了重写 URL 的方法:public java.lang.String encodeURL (java.lang.String url) 该方法的实现机制为:

  1. 先判断当前的 Web 组件是否启用 Session,如果没有启用 Session,直接返回参数 url。
  2. 再判断客户端浏览器是否支持 Cookie,如果支持 Cookie,直接返回参数 url;
  3. 如果不支持 Cookie,就在参数 url 中加入 Session ID 信息,然后返回修改后的 url。

JSP页面修改前:

<a href=“maillogin.jsp“>   

修改后:

<a href=“<%=response.encodeURL(“maillogin.jsp“)%>”

ps:[上面这段话忘记copy哪位老哥的,刷题时做错了,看见一位道友的评论就copy保存下了]

 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    		throws ServletException, IOException {
    	// 采用cookie向浏览器端发送账号密码,实现记住密码账号功能
    	String username=req.getParameter("username");
    	String password=req.getParameter("password");
    	
    	Cookie cookie=new Cookie("userinfo", username+"-"+password);
    	resp.addCookie(cookie);
    }

Servlet的线程安全性

Servlet不是线程安全的,这意味着如果你定义全局变量或者静态变量,那么你需要加锁进行安全性的保证,因为当出现并发访问同个Servlet,Tomcat会同时调用service方法的,而service由源码可知是没有进行安全性设置的,此时如果需要访问全局、静态变量,将出现并发访问。

猜你喜欢

转载自blog.csdn.net/legendaryhaha/article/details/89219565