JavaWeb三大组件之Servlet详解

Servlet

1.1 Servlet整体结构

  图解可以看到SevletConfig和Servlet都是顶层接口类,而GenericServlet实现了这两个顶层类,然后HttpServlet实现了GenericServlet类,所以要实现一个Servlet直接就可以继承HttpServlet

1.2 Servlet接口

源码如下

public interface Servlet {
    public void init(ServletConfig config) throws ServletException;
    
    public ServletConfig getServletConfig();
    
    public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
    
    public String getServletInfo();
    
    public void destroy();
}
复制代码

依次解析这五个方法

  • init()方法接收一个ServletConfig参数,由容器传入,ServletConfig就是Servlet的配置,在web.xml中定义Servlet时通过init-param标签配置的参数由ServletConfig保存

  • init()方法Servlet创建时执行,且只会被调用一次
  • getServletConfig()方法获取Servlet配置
  • service()处理具体请求
  • getServletInfo()获取Servlet的相关信息
  • destroy()销毁对象,服务器关闭时执行

总结

init(ServletConfig config)这个参数是ServletConfig类型的
ServletConfig这个接口的方法都可以使用
所以能用这个引用参数下的方法
    getInitParameterNames()获取init-param标签下的键值对
    getServletName()获取servlet-name里自定义的值
    getServletContext()获取context-param标签下的东西
复制代码

1.3 ServletConfig接口

源码如下

public interface ServletConfig {
    //用于获取Servlet名,web.xml中定义的servlet-name
    public String getServletName();
    //获取应用本身(非常重要)
    public ServletContext getServletContext();
    //获取init-param中的配置参数
    public String getInitParameter(String name);
    //获取配置的所有init-param名字集合
    public Enumeration getInitParameterNames();
}
复制代码

ServletConfig接口下可获取web.xml的参数
首先看下web.xml配置

 
    
    Servlet1
    com.breeze.servlet.Servlet1
    
    	a
    	96
    
    
    	b
    	97
    
  
  
    Servlet1
    /servlet
  
复制代码

接下来获取这些参数

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("ServletName-----------------------");
		String name=getServletName();
		System.out.println(name);
		
		System.out.println("第一种方式获得init-param--------------");
		//通过键获得值
		String initParameter = getInitParameter("a");
		System.out.println(initParameter);
		
		System.out.println("第二种方式获得init-param---------------");
		Enumeration parameterNames =getInitParameterNames();
		while(parameterNames.hasMoreElements()) {
			String key = parameterNames.nextElement();
			String value = getInitParameter(key);
			System.out.println(key+"----"+value);
		}
	}
复制代码

1.4 GenericServlet抽象类

GenericServlet是Servlet的默认实现,与具体协议无关的
GenericServlet主要做了三件事
  1,实现了ServletConfig的接口,可以调用ServletConfig里面的方法,不需要获取getServletConfig对象。获取ServletContext可以直接调用getServletContext,不用getServletConfig().getServletContext()
  用init()把ServletConfig变成内部变量引用,然后重写ServletConfig接口的所有方法,用这个变量调用

public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
但是我们可以看到追根溯源getServletContext()还是由getServletConfig()调用的


public ServletConfig getServletConfig() {
        return config;
    }
getServletConfig()方法返回了config,config是从init()方法拿到的ServletConfig
复制代码

  2,提供了无参init()方法,

public void init() throws ServletException {}

public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
复制代码

  3,提供了两个log()方法,一个记录日志,一个记录异常,其具体实现是通过传给ServletConfig的日志实现的

    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }
    
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
复制代码

GenericServlet源码总结

tomcat会执行init()有参方法
init()有参方法
    参数是web.xml,也就是ServletConfig,把ServletConfig这个参数指向内部变量config
    然后调用了init()无参方法
init()无参方法是空的,方便你自己实现类去重写初始化

GenericServlet重写了接口ServletConfig的所有方法,用config这个内部变量调用
所以我们在实现类就不用去关心config,只需要执行自己的逻辑即可
在重写init()方法时,也不需要调用super.init(config)

所以在实现类去调用ServletConfig的方法时,可以直接写接口类的方法即可,因为GenericServlet重写了
比如用getInitParameterNames()
不需要在实现类去定义ServletConfig,也不用去this.getServletConfig().getInitParameterNames();
可以直接getInitParameterNames()
复制代码

1.5 HttpServlet类

  HttpSerVlet是基于Http协议实现的Servlet基类,我们刚开始写Servlet的时候是实现Servlet接口,后面在写Servlet的时候直接继承HttpServlet类就可以了

  HttpServlet处理请求主要是通过重写父类的service()来完成具体请求的,在第一个service里是把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用第二个service()方法

  第二个service则根据http不同的请求,调用相应的方法处理,如doGet,doPost,所以我们代码也可以写在doGet,doPost里

在html界面中,要是没有设定提交的方法,servlet默认以doGet的方法进行处理。


执行流程

客户端发送请求,通过web.xml的url匹配跳转到到实现类servlet
而实现类继承HttpServlet,所以先说父类
HttpServlet执行service接受请求进行强转,调用第二个service判断时什么方式请求
如判断的时doGet请求,则执行doGet方法
但我们重写了doGet方法,所以将请求发送到了我们重写的doGet方法中
如果我们重写的不是doGet而是service则一样,因覆盖了父类的service则将请求发送到我们重写的sercvice
复制代码
复制代码

你可能感兴趣的:(JavaWeb三大组件之Servlet详解)