动态资源Servlet接口

1.Servlet接口的作用

Servlet是运行在Web服务器上的应用程序。Servlet本身是一个Java接口,它定义了浏览器访问服务器程序的规则,我们写服务器程序只需要按照需求复写Servlet方法即可

2.Servlet的体系结构

<1>直接继承实现类结构
在这里插入图片描述
<2>其他相关类视图
在这里插入图片描述

<1>实现Servlet接口
重写Servlet生命周期的所有方法

public class ServletDemo1 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //第一次访问的时候创建Servlet调用
        System.out.println("init初始化执行1次");
    }

    @Override
    public ServletConfig getServletConfig() {
        //每一个Servlet对象创建时,会自动创建一个ServletCong对象
        return null;
    }

    //所有的客户端请求都会经过service方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet实现响应");
    }

//获取Servlet信息
    @Override
    public String getServletInfo() {
        return null;
    }

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

<2>继承GenericServlet抽象类
每次写一个Servlet都要复写生命周期的所有方法,比较麻烦。 Servlet提供了一个实现类GenericServlet,它把其他方法已经复写了,我们继承GenericServlet只需要复写service就可以了

public class ServletDemo2 extends GenericServlet {
//不知道是get请求还是post请求
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("GenericServlet实现响应");
    }
}

<3>继承GenericServlet抽象类【最简便也最常用】
如果每次都是继承GenericServlet类,在servlce方法中,不能区分直接是Get请求还是Post请求。需要我们自己求请求方法进行处理,也比较麻烦,所以又提供了一个子类HttpServlet类。
HttpServlet类中会根据不同的请求方式,提供不同的方法,我们只需要复写对应的方法即可

public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HttpServlet实现响应");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
3.Servlet的映射配置

<1>针对上面三种Servlet具体类进行配置
注意:每一个Servlet都需要有一个下面的配置,否则会找不到资源

<?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">
    <!--    修改默认主页 /代表根目录Web-->
    <welcome-file-list>
        <welcome-file>/html/index.html</welcome-file>
    </welcome-file-list>

    <!--    servlet声明-->
    <servlet>
        <servlet-name>ServletDemo1</servlet-name>
        <servlet-class>com.itheima.servlet.ServletDemo1</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>ServletDemo2</servlet-name>
        <servlet-class>com.itheima.servlet.ServletDemo2</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>ServletDemo3</servlet-name>
        <servlet-class>com.itheima.servlet.ServletDemo3</servlet-class>
    </servlet>
    
    <!--servlet映射 -->
   
    <servlet-mapping>
        <servlet-name>ServletDemo1</servlet-name>
        <url-pattern>/Servlet</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>ServletDemo2</servlet-name>
        <url-pattern>/GenericServlet</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>ServletDemo3</servlet-name>
        <url-pattern>/HttpServlet</url-pattern>
    </servlet-mapping>
</web-app>

<2>同一个Servlet多映射处理
针对用户种类对进行多种映射配置

<!--   方式1 -->
    <!--具体名称的方式。访问的资源路径必须和映射配置完全相同-->
    <servlet-mapping>
        <servlet-name>ServletDemo5</servlet-name>
        <url-pattern>/ServletDemo5</url-pattern>
    </servlet-mapping>

    <!--   方式2 -->
    <!--/开头+通配符的方式 不用考虑结尾是什么 -->
    <servlet-mapping>
        <servlet-name>ServletDemo5</servlet-name>
        <url-pattern>/ServletDemo5/*</url-pattern>
    </servlet-mapping>
    <!--   方式3 -->
    <!--通配符+固定格式结尾的方式。只要符合固定结尾格式即可,不用考虑前面的路径-->
    <servlet-mapping>
        <servlet-name>ServletDemo5</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

【注:优先级问题。越是具体的优先级越高,越是模糊通用的优先级越低。第一种->第二种->第三种–>】

<3>从浏览器地址栏,到访问Servlet的过程

Servlet是Web项目中的动态资源(Servlet字节码),访问过程如下
第一步:通过浏览器的ip地址找服务端主机
第二步:通过8080端口号找到tomcat服务器软件
第三步:通过虚拟机路径找到tomcat服务器上发布的web项目包
第四步:通过web.xml<url-pattern>找到Servlet对应的字节码
第五步:Tomcat会根据Servlet的字节码,自动的执行servcie方法

在这里插入图片描述

4.Servlet的加载时机
 <servlet>
        <servlet-name>ServletDemo1</servlet-name>
        <servlet-class>com.itheima.servlet.ServletDemo1</servlet-class>
        <!--Servlet的加载时机配置
        每个Servlet默认是在第一次访问的时候被创建,默认为-1
        但是也可以通过web.xml配置让其在服务器启动的时候创建。
        数字越小,优先级越高-->
  <load-on-startup>1</load-on-startup>  
  </servlet>

<1>第一次访问的时候被创建
优势:减少对服务器内存的浪费。提高了服务器启动的效率。
弊端︰如果有一些要在应用加载时就做的初始化操作,无法完成。
<2>服务器加载时创建
优势∶提前创建好对象,提高了首次执行的效率。可 以完成一些应用加载时要做的初始化操作
弊端∶对服务器内存占用较多,影响了服务器启动的效率

5.Servlet的线程安全问题

<1>问题出现:一个浏览器代表一个线程,多个浏览器代表多个线程。按理说我们期望的应该是每个浏览器查看的都应该是自己的用户名。而现在的结果是浏览器中数据混乱。因此,我们可以认为Servlet是线程不安全的!
<2>分析:多线程使用同一个共享数据
<3>解决:定义类成员要谨慎。如果是共用的,并且只会在初始化时赋值,其他时间都是获取的话,那么是没问题的。如果不是共用的,或者每次使用都有可能对其赋值,那就要考虑线程安全问题了,可以将其定义到doGet 或 doPost方法内或者使用同步功能即可。
a.同步代码块
b…将可能需要重新赋值的值定义在自己的方法体内[推荐]

<4>代码实现

//servlet线程安全问题
public class ServletDemo4 extends HttpServlet {
    private String username;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //2.将可能需要重新赋值的值定义在自己的方法体内[推荐]
        //String username =null;

        //1.同步代码块
        synchronized (this){
            //获取用户名
            username = req.getParameter("username");
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //将用户名响应给浏览器
            PrintWriter pw = resp.getWriter();
            pw.println("welcome:" + username);
            pw.close();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
6.默认Servlet

<1>含义;默认Servlet是由服务器提供的一个Servlet。它配置在Tomcat的conf目录中的web.xml中;
它的映射路径是/,我们在发送请求时,首先会在我们项目中的web.xml中查找映射配置,找到则执行。但是当找不到对应的Servlet路径时,就去找默认的Servlet,由默认Servlet处理。所以,一切都是Servlet。

    <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>

<3>如一些报错信息,如404都是默认Servlet给我们的提示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陪雨岁岁年年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值