Servlet

什么是servelt

参考javaweb学习总结

servelt是sun公司提供一个接口,但我们日常所说的servelt是实现了servlet接口的java程序,会被放在服务器上运行
编写servlet的时候不需要main函数,因为写完后,就把编写的程序编译成字节码,放到服务器上面。当前发送就一个请求的时候,服务器就会按照一定规则调用编写的代码

servlet的运行流程

Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
  ①Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
  ②装载并创建该Servlet的一个实例对象。
  ③调用Servlet实例对象的init()方法。
  ④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
  ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

在这里插入图片描述

开发一个简单的servlet程序

  1. 新建一个servlet
    直接new出来的servlet实现的是HttpServlet接口
public class Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

  1. 三个方法
    ①doGet()
    当发送get请求时调用

②doPost()
当发送post请求的时候调用

③service()
每一次发送请求的时候就会调用,有该方法就不会调用① ②方法

  1. web.xml中配置映射
    url-pattern是映射到的url地址,即对外访问路径
    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>finalexam.demo.Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/demo/ServletDemo1</url-pattern>
    </servlet-mapping>

映射也可以使用通配符写法

servlet的线程安全问题

为什么会有线程安全问题

在之前的servlet的工作流程中直到在一个web应用程序中,同一个servlet对象只会被创建一次就永远驻留与内存,并且以后的servlet请求调用的都是该servlet对象
在多个客户端并发访问同一个servlet的时候,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用同一个servlet对象的service方法,所以如果service方法内使用了统一资源就会有线程安全问题(如访问同一个全局变量)

public class ServletDemo extends HttpServlet {

     int i=1;
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         
         i++;
         try {
             Thread.sleep(1000*4);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         response.getWriter().write(i+"");
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }

如何解决

① 加锁,为servlet加锁,每次只能一个客户端调用
但是在实际开发中绝对不可能让用户串行等待访问服务端的servlet

public class ServletDemo3 extends HttpServlet {
 
     int i=1;
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         /**
          * 加了synchronized后,并发访问i时就不存在线程安全问题了,
          * 为什么加了synchronized后就没有线程安全问题了呢?
          * 假如现在有一个线程访问Servlet对象,那么它就先拿到了Servlet对象的那把锁
          * 等到它执行完之后才会把锁还给Servlet对象,由于是它先拿到了Servlet对象的那把锁,
          * 所以当有别的线程来访问这个Servlet对象时,由于锁已经被之前的线程拿走了,后面的线程只能排队等候了
          * 
          */
         synchronized (this) {//在java中,每一个对象都有一把锁,这里的this指的就是Servlet对象
             i++;
             try {
                 Thread.sleep(1000*4);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             response.getWriter().write(i+"");
         }
         
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }

**② 让Servlet去实现一个SingleThreadModel接口 **

针对Servlet的线程安全问题,Sun公司是提供有解决方案的:让Servlet去实现一个SingleThreadModel接口,如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
  查看Sevlet的API可以看到,SingleThreadModel接口中没有定义任何方法和常量,在Java中,把没有定义任何方法和常量的接口称之为标记接口,经常看到的一个最典型的标记接口就是"Serializable",这个接口也是没有定义任何方法和常量的,标记接口在Java中有什么用呢?主要作用就是给某个对象打上一个标志,告诉JVM,这个对象可以做什么,比如实现了"Serializable"接口的类的对象就可以被序列化,还有一个"Cloneable"接口,这个也是一个标记接口,在默认情况下,Java中的对象是不允许被克隆的,就像现实生活中的人一样,不允许克隆,但是只要实现了"Cloneable"接口,那么对象就可以被克隆了。

让Servlet实现了SingleThreadModel接口,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。
  对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。
  实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet
API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

ServletConfig

在web.xml中,可以使用一个或多个标签为servlet配置一些初始化参数。web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,我们通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

web.xml

 <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>finalexam.demo.Servlet</servlet-class>
         <init-param>
            <param-name>name</param-name>
            <param-value>servletname</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>servletpassword</param-value>
        </init-param>
        <init-param>
            <param-name>charset</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>

servlet

public class Servlet extends HttpServlet {
    //定义ServletConfig对象来接收配置的初始化参数
    private ServletConfig servletConfig;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //将ServletConfig对象传递给servlet
        this.servletConfig = servletConfig;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = this.servletConfig.getInitParameter("name");
        System.out.println(name);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }


}

Servelt三大域对象

Servelt三大域对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值