Servlet

本文详细介绍了Servlet的概念、使用方法及生命周期,包括如何编写、部署Servlet,以及ServletConfig和ServletContext的作用。

1、Servlet简介

Servlet全称Java Servlet。servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
功能:用于交互式地浏览和修改数据,生成动态Web内容。

2、Servlet的使用

1、编写java类实现servlet接口(可以编写一个继承 javax.servlet.GenericServlet 或者 javax.servlet.http.HttpServlet 的servlet)
2、部署到web服务器中

3、在MyEclipse中创建servet

1、创建web project
2、继承servlet

public class MyServlet implements Servlet {
    //只创建一次
    public void init(ServletConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
        System.out.println("Servlet------init()");
    }
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("Servlet------service()");
    }
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }
    public void destroy() {
        // TODO Auto-generated method stub
        System.out.println("Servlet------destory()");
    }

}

3、在web.xml中配置
web.xml其实就是servlet的一个配置文件,通过这个配置文件来寻找对应的servlet处理业务。

sun公司就是这样设计,容器通过配置文件web.xml找相应的servlet这样有助于灵活和可维护性
这里写图片描述

4、Servlet生命周期

这里写图片描述
1、init()方法:服务器调用该方法初始化Servlet
2、service()方法:初始化完毕,服务器调用该方法响应客户的请求
3、destroy()方法:服务器调用该方法消灭servlet对象
其中,init()方法只在Servlet第一次被请求加载的时候被调用一次,当有客户再请求Servlet服务时,Web服务器将启动一个新的线程,在该线程中,调用service方法响应客户的请求
Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。

在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

5、GenericServlet

GenericServlet 是对servlet的封装,它实现 了Servlet 和 ServletConfig 接口。如果我们实现原有的Servlet,要写每一个servlet都要写init(),等生命周期的方法。如果再加上一些都是相同的代码,会有很多不必要的工作。因此GenericServlet 是在Servlet的基础上实现servlet接口,对它进行封装,主要做以下工作:

  1. init()方法,并保存了config对象
  2. 空参init()方法,防止调用原生init()方法
  3. service(),声明抽象(具体业务而定)
  4. 实现getServletInfo,getServletConfig
  5. 实现了servletConfig接口. 接口中的方法直接调用config实现类实现
  6. destory()方法空实现

6、HttpServlet

HttpServlet是在GenericServlet 基础上进行的再一次封装,它是GenericServlet 的子类
在这里它比GenericServlet 又做了一些全局的通用的处理

1、把ServletRequest,ServletResponse强转成HttpServletRequest,HttpServletResponse以为在具体的开发中用到的是ServletRequest封装的HTTP请求

 @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;

        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException("non-HTTP request or response");
        }
        service(request, response);
    }

2、处理用户的不同请求

1、METHOD_GET
2、METHOD_HEAD
3、METHOD_POST
4、METHOD_DELETE
5、METHOD_OPTIONS
6、METHOD_TRACE

 protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if(){
        ......
        }......

}

7、Servlet线程安全问题

从Servlet的生命周期中可以看出,我们调用init()方法只执行一次,当我们再次运行的时候已经不调用init方法
因此,共享引起线程安全。如果使用成员变量来接受线程中的参数,那么就就会出现线程安全问题。

解决办法:把成员变量放到局部变量中

8、Servlet路径配置问题

<servlet>
  <servlet-name>MyServlet</servlet-name>
  <servlet-class>com.example.MyServlet</servlet-class>
  </servlet>

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

在的url-pattern中配置servlet的路径,在这是一个相对路径/表示在我们当前的目录下,在这里相当于http:localhost:8080/ServletDemo

8、ServletConfig

在Servlet的配置文件中,可以使用一个或多个标签为servlet配置一些初始化参数。(配置在某个servlet标签或者整个web-app下)
当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

9、ServletContext

ServletContext,是一个全局的储存信息的空间。
ServletContext定义一组方法,servlet 使用这些方法与其 servlet 容器进行通信,例如,获取文件的 MIME 类型、分发请求或写入日志文件。
比如 Servlet之间传递数据;
通过获取ServletContext对象设置

public void setAttribute(String name, Object object);

通过getAttribute获取

   public Object getAttribute(String name);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值