真的了解Servlet吗?- Tomcat与Servlet

前言

万丈高楼平地起,学习框架前先将Servlet学好
学习过程中,不断提问自己真的理解了Servlet吗?


目录

  1. Tomcat
  2. Tomcat中的Servlet
  3. 一个Servlet案例
    3.1. XML中的配置
    3.2. Tomcat的运行
  4. Servlet层次
    4.1. Servlet接口
    4.2. GenericServlet类
    4.3. HttpServlet类
  5. Request与Response
    5.1. 一个获得请求与返回响应的案例
    5.2. Request和Response类
  6. 总结

Tomcat

学习JavaWeb,肯定都接触过Tomcat这个轻量级服务器
在这里插入图片描述

也叫Servlet/JSP服务器
对于JavaEE的13种规范:
JDBC,JNDI,EJB,RMI,JSP,Servlets,XML,JMS,JavaIDL,JTS,JTA,JavaMail,JAF
Tomcat只实现了两种:Servlet和JSP,也就是写Servlet和JSP可以不用导Jar包(内置了),而如果写其他规范就需要导jar包

JavaWeb三大组件:Servlet(容器)、Listener(监听器)、Filter(过滤器)

所以说JavaEE和JavaWeb不是一个级别的
在这里插入图片描述

一个JavaWeb程序是怎样运行的呢?

在这里插入图片描述
这些在Tomcat的核心配置文件server.xml中可以看到
tomcat - > conf - > server.xml

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

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>  
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
 
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="GBK" />
    
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"> 
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>

我们前面学习了XML,根据xml的知识:
server.xml中,根目录Server代表服务器
下面有3种子元素:Service、Listener、GlobalNamingResources
其中Service代表服务,真正处理业务,有且仅有一个,Listener代表监听器

Service 服务中有两种子元素:Connector连接器、Engine引擎
Connector负责监听客户端或者其他连接请求,也不会处理业务
Engine是Tomcat引擎,处理业务的地方,Engine下面有host主机(localhost)

host中的appBase属性是不是就是我们的工程目录:webapps

核心配置再对于相关的配置文件与解析器,就做到了对请求响应逻辑的封装,程序员只需写好业务就ok了

Tomcat服务器=Web服务器+Servlet/JSP容器(Web容器)

再将Tomcat抽象一点:
在这里插入图片描述

Tomcat中Web服务器接收、响应客户端请求(静态资源),Web容器装载Servlet/JSP,让它们去处理动态资源

总的来说,Tomcat将各种请求逻辑、响应逻辑都封装好了,我们只需编写静态页面、动态资源和业务(Servlet)


Tomcat中的Servlet

Servlet容器,就是存放着各种Servlet对象的容器,其中可以有自定义的Servlet和内置的Servlet

通过Web服务器映射的URL访问资源,需要接收请求、处理请求、响应请求;接收请求和响应请求由Web服务器处理,我们要做的就是处理请求,通过Servlet容器

Tomcat中,所有的业务都是各种各样的Servlet实现的
我们可以看Tomcat的另一个核心配置文件:web.xml

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

还有很多,全是各种Servlet元素
其中default的匹配路径是"/",也就是默认地址localhsot:8080/,通过DefaultServlet处理
jsp页面的处理方法JspServlet


一个Servlet案例

当然先要配置好Tomcat

在这里插入图片描述

在src/test中,编写一个helloServlet,实现Servlet接口 ,这就是一个Servlet处理程序

package test;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class helloServlet implements Servlet {

    public helloServlet() {
        System.out.println("构造器方法");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init方法");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    	//转型
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        //获得请求方法
        String method = httpServletRequest.getMethod();
        //如果是get
        if (method.equals("GET")) {
            System.out.println("this is servlet: GET");
        }
        //如果是post
        else if (method.equals("POST")){
            System.out.println("this is servlet: POST");
        }
    }


    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("销毁servlet");
    }
}


在web.xml中配置helloServlet的访问

<?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">
    <!--servlet标签给Tomcat配置servlet-->
    <servlet>
        <servlet-name>helloServlet</servlet-name>
        <!--servlet全类名-->
        <servlet-class>test.helloServlet</servlet-class>
    </servlet>
    <!--servlet-mapping配置servlet程序配置访问地址-->
    <servlet-mapping>
        <!--servlet-name告诉服务器,当前地址给该Servlet使用-->
        <servlet-name>helloServlet</servlet-name>
        <!--url配置访问地址-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

这样启动一个Tomcat就可以访问这个helloServlet

输入地址:http://localhost:8080/hello

在这里插入图片描述

XML中的配置

< servlet>< /servlet>:这个之间配置的是Servlet的类信息
< servlet-name>:这是Servlet 的别名,一个名字对应一个Servlet。相当于变量名 < servlet-class>:Servlet 的全类名,服务器会根据全类名找到这个Servlet
< servlet-mapping>< /servlet-mapping>:这个之间配置的是Servlet 的请求映射信息
< servlet-name>:Servlet的别名,说明这个Servlet将会响应下面url-pattern的请求
< url-pattern>:Servlet响应的请求路径。如果访问这个路径,这个Servlet就会响应。这个url-pattern可以配置多个,这时表示的就是访问这些url都会触发这个Servlet进行响应

在这里插入图片描述
对于客户端的请求:http://localhost:8080/hello
Tomcat先查找web.xml中的url配置,存在就继续找到给Servlet(name - > class)
然后运行这个Servlet,返回响应

Tomcat的运行

学到了JavaWeb,发现已经不用写main方法了,启动一下Tomcat就可以实现我们编写的helloServlet

可以想到Tomcat中,应该帮我们定义好了main()方法

tomcat的启动过程(Tomcat源码解析(三))

说实话,看不懂这位大佬的源码解析,但大概可以知道,Tomcat在启动startup时会通过各种反射机制和线程池调用线程,最终达到想要的效果:Tomcat启动后一直等待连接,我们仅需编写好Servlet就可以处理好业务

Tomcat的main方法入口org.apache.catalina.startup.Bootstrap#main


Servlet层次

1)从广义上来讲,Servlet 规范是Sun 公司制定的一套技术标准,包含与Web 应用相关的一系列接口,是Web 应用实现方式的宏观解决方案。而具体的Servlet 容器负责提供标准的实现。
2)从狭义上来讲,Servlet 指的是javax.servlet.Servlet 接口及其子接口,也可以指实现了Servlet 接口的实现类。
3)Servlet 作为服务器端的一个组件,它的本意是“服务器端的小程序”。Servlet 的实例对象由Servlet 容器负责创建;Servlet 的方法由容器在特定情况下用;Servlet 容器会在Web 应用卸载时销毁Servlet 对象的实例

Servlet接口的实现体系:
在这里插入图片描述

Servlet接口

在这里插入图片描述

Servlet接口很简单,仅仅定义了5个方法的规范,是Servlet的规范

这5个方法中,3个是Servlet生命周期的方法:

  1. init(ServletConfig var1):Servlet初始化函数,仅在Servlet创建时调用一次,初始时会传入ServletConfig 配置对象
  2. getServletConfig():获得ServletConfig对象
  3. service(ServletRequest var1, ServletResponse var2):Servlet执行方法,收到客户端请求ServletRequest时,执行该方法
  4. getServletInfo():返回此Servlet 的描述信息
  5. destroy():销毁Servlet前调用该方法

但是如案例中,实现Servlet接口必须要实现5个方法,能不能更简单一点?

GenericServlet类

在这里插入图片描述

GenericServlet抽象类实现了Servlet接口
除了重写的5个方法,还有一些自己的方法

在这里插入图片描述

仅有service方法是抽象的,也就是我们仅需要关注我们要处理的业务(当然,重写其他方法也是可以的)

在这里插入图片描述

为什么GenericServlet是抽象类:

抽象类的作用是什么?

  • 防止实例化
  • 规范实现类

仔细看GeneriServlet源码中对Servlet接口的实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这些方法几乎都没有实际的作用,作者设置抽象类就是认为程序员别实例化GenericServlet,里面的方法没有实际用处

HttpServlet类

GenericServlet几乎没有实现Servlet接口,而且本身也是个抽象类,具体的实现是它的子类HttpServlet
在这里插入图片描述

可以发现HttpServlet中实现了service方法,我们的业务方法
在这里插入图片描述

我们知道Http请求有get方法、post方法等
处理时需要自己通过request.getMethod()得到方法,然后分类处理

它可以判断请求,然后分发到不同方法处理:
get - > doGet ; post - > doPost

它在GenericServlet的基础上再次细化封装,我们连判断客户端访问是什么方法都不需要了

Servlet子类就是不断偷懒的过程

Servlet - > GenericServlet - > HttpServlet


Request与Response

Request:请求信息,客户端发送的请求信息被Tomcat封装到Request中
Response:响应信息,服务器处理完业务后返回给客户端的响应信息

注意:Tomcat连接到客户端后,会创建Request与Response,Request封装各个请求头(Header),请求地址(URL),请求参数(QueryString),Response在Tomcat传给Servlet时是空的
在这里插入图片描述

随着后续的业务处理,会存进response中

在这里插入图片描述

回传用response的getWriter方法获得字符输出流对象,然后通过流可以响应信息

在这里插入图片描述

一个获得请求与返回响应的案例

TestReqResp 类判断登录信息

package test;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class TestReqResp extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        String name = req.getParameter("name");
        String password = req.getParameter("password");
        System.out.println("客户端输入的name:"+name);
        System.out.println("客户端输入的password:"+password);
        PrintWriter writer = resp.getWriter();
        if (name.equals("zhangsan")&&password.equals("123456")){
            writer.println("hello Client");
        }
        else {
            writer.println("登录失败");
        }
    }
}

记得在web.xml中配置Servlet

    <servlet>
        <servlet-name>testReqResp</servlet-name>
        <servlet-class>test.TestReqResp</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>testReqResp</servlet-name>
        <url-pattern>/testReqResp</url-pattern>
    </servlet-mapping>

输入网址:http://localhost:8080/testReqResp?name=zhangsan&password=123456

网址返回了信息:

在这里插入图片描述
控制台也得到了登录信息:
在这里插入图片描述

当然,这是一个通过URL传递参数发方法,可以选择使用HTML的表单登录

Request和Response类

从Servlet接口server方法传递的参数ServeltRqeuset、ServeltResponse
到HttpServlet的HttpServletRequest、HttpServletResponse

ServeltRqeuset:
在这里插入图片描述

由继承图可以看出ServletRquest、HttpServletRequest都是接口
他们规范方法,具体由ServletRequestWrapper和HttpServletRequestWrapper实现

ServletRquest是针对客户端发出的请求信息
HttpServletRequest继承ServletRquest,并添加了一些获得HTTP协议信息的方法

Response和Request类似


总结

  1. Tomcat是一个轻量级的服务器,支持Servlet/JSP
  2. Tomcat服务器=Web服务器+Servlet容器;Web服务器负责连接与响应,Servlet容器中的各种Servlet负责处理业务
  3. Servlet层次:Servlet接口、GenericServlet抽象类、HttpServlet类
  4. Servlet接口定义5种方法,程序员需要重写这些方法;GenericServlet抽象类中帮我们实现了4个,仅剩server抽象方法供我们处理业务;HttpServlet类进一步将server方法细化,对不同的请求分发到对应的方法;越来越便捷
  5. Request和Response在Tomcat连接到服务器就会创建并传递给对应的Servlet;继承了Servlet接口、GenericServlet抽象类是封装得到ServletRequest与ServletResponse,包含了请求信息;继承HttpServlet类是封装成HttpServletRequest和HttpServletResponse,在前者的基础上多包含了Http协议的一些信息
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值