Servlet基础

servlet 是运行在 Web 服务器中的小型 Java 程序(即:服务器端的小应用程序)。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。

1、servlet是一个接口,首先浏览器发送请求到服务器,服务器找应用的web.xml。然后寻找来找到实现了servlet这个接口的类,创建类,启动类里面的init()方法,然后调用Service方法完成请求,然后传回到服务器,服务器返回给浏览器
这里写图片描述
创建一个servlet的过程
一:创建一个类实现Servlet,实现相应的方法。如图所示,init()和构造方法只在第一次创建的时候执行,接下来就是调用Service方法,不会执行init(),只会刷新Service方法,当应用被卸载的时候调用destory()方法

public class ServletDemo1 implements Servlet {
    /**
     * 构造方法和init方法都只执行一次,在打开这个页面的时候
     * service打开和刷新的时候都会执行
     * destory方法在应用被卸载的时候调用
     * */
    public ServletDemo1() {
        System.out.println("构造方法执行了");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
    }
    @Override
    public ServletConfig getServletConfig() {
        System.out.println("getServletConfig");
        return null;
    }
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service");
    }
    @Override
    public String getServletInfo() {
        System.out.println("getServletInfo");
        return null;
    }
    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

二:修改WEB-INF当中的web.xml文件,给servlet提供一个可访问的URI地址。

  • 首先服务器通过uri找到应用然后找到与uri对应的< servlet-mapping>这个节点,找打servlet的名字
  • 服务器是通过 < url-pattern>这个节点来匹配来寻找的,这里给的名字是/app
  • 通过< servlet-name>找到实现servlet这个类的名字,然后找到对于的servelt节点,然后找到类的路径。
  • 服务器自己创建对应的类,然后调用service()方法来完成交互
  • service()方法中的参数servletRequest和servletResponse是服务器传递的,一个是请求的信息,一个是返回的消息
  • 访问http://localhost:8080/firstJavaWeb/app就可以得看到控制台的输出
<servlet>
        <servlet-name>servletDemo1</servlet-name>
        <servlet-class>com.yanglin.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
        <servlet-name>servletDemo1</servlet-name>
        <url-pattern>/app</url-pattern>
</servlet-mapping>

2、Servlet的声明周期

实例化–>初始化–>服务->销毁
上类中的已经说明参看类

3、Servlet的三种创建方式

  1. 实现Servlet接口,如上所示
  2. 继承javax.servet.GenericServlet类(适配器模式)
    这里写图片描述
  3. 继承javax.servlet.http.HttpServlet类(模板方法设计模式)设计当中经常使用。

    接下里讲解HttpServlet创建Servlet类,如下所示,需要重写两个方法doPost()和doGet()

public class ServletDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

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

HttpServlet 这个类的使用了多态的机制,我们来看一下其所有的方法。
这里写图片描述
它继承了GenericServlet这个类,所有这里有service(ServletRequest,ServletResponse)这两个方法这个方式是实现Servlet这个接口的。所有当服务器访问这个类的时候是类型是这样的。

Servlet s = new HttpServlet()

这里是父类的引用指向了子类对象,这是这个父类是父类的父类。这里重写的了这个方法,所有动态绑定调用的是HttpServlet()这个类的Service方法。方法的实现源码

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);
    }

从源码中可以看到,HttpServletRequest,HttpServletResponse 是继承了ServletRequest ,ServletResponse 这两个接口,应该是有拓展的。最有调用HttpServlet自己的service(HttpServletRequest,HttpServletResponse )来处理,方法源码:

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 = req.getDateHeader(HEADER_IFMODSINCE);
        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 (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);   

    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req,resp);

    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req,resp);

    } else {
        //
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1];
        errArgs[0] = method;
        errMsg = MessageFormat.format(errMsg, errArgs);

        resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    }
    }

这里这个类处理了请求方式,主要是调用doPost()和doGet()方法。判断方法后分别调用不同的方法来处理。这里给我们封装了一些实用的细节,我们只需要实用这个模板然后重写里面的doPost()和doGet()等方法来实现我们知己的需求就行了。

小技巧:使生成的servlet更清新一些 找到:MyEclipse\Common\plugins目录
把com.genuitec.eclipse.wizards_9.0.0.me201108091322.jar复制到上面目录


3、servet映射细节:处理url的规则

  • servet映射细节: 通配符* 代表任意字符串
  • url-pattern: *.do 以*.字符串的请求都可以访问 注:不要加/
  • url-pattern: /* 任意字符串都可以访问
  • url-pattern: /action/* 以/action开头的请求都可以访问

    优先级:从高到低
    绝对匹配(具体的url)–> /开头匹配(一/开始) –> 扩展名方式匹配(.do或者.action等)

4、线程安全
因为httpServlet的service()方法都是多线程的,所以会导致最好不要有全局变量,引用全局变量会导致变量共享。

5、Servlet获取配置信息

  1. ServletConfig的使用
    1.获取servlet的配置信息,这个配置信息是写在web.xml当中的例如如下,有编码的配置信息,就可以通过ServletConfig获取,而且获取的方式多样,这里说两个看代码。
  2. 获取ServletContext()
<servlet>
        <servlet-name>ServletDemo2</servlet-name>
        <servlet-class>ServletDemo2</servlet-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
</servlet>
//way 1获取ServletConfig来得到局部编码
String s = this.getServletConfig().getInitParameter("encoding");
//way 2能得到全局的配置信息,和这个servlet下面的配置信息
String encoding = this.getInitParameter("encoding");

一般而言使用的是第二个,因为httpServlet继承的GenericServlet实现了getInitParameter()这个方法。但是这个只能获取全局的配置信息,以及这个servlet下面的配置信息。不能获取其他servlet的配置信息。

5、ServletContext
ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。是单实例。

  • 在一定范围内(当前应用),使多个Servlet共享数据。
    在ServletDemo2的service()中写如下
 //通过调用GenerServlet的getServletContext得到ServletContext
ServletContext context = this.getServletContext();
context.setAttribute("name","zeroyoung");

在ServletDemo的service()下可以访问到如下

ServletContext context = this.getServletContext();
String name = (String) context.getAttribute("name");
//String encoding = this.getInitParameter("encoding");
System.out.println(name);
  • 获取全局配置信息
    就是如上一节当中的,this.getInitParameter()这个方法,全局web.xml如下。
<context-param>
        <param-name>encoding</param-name>
        <param-value>GBK</param-value>
</context-param>
<context-param>
        <param-name>encoding</param-name>
        <param-value>GBK</param-value>
    </context-param>
  • 获取资源路径:可以获取这个应用当中所有的资源文件
    方法:getRealPath(String path)
    需要注意的是在src下面的文件,在部署的时候都是放到web-inf这个目录下的classes目录下面的。所有当你在src下面创建一个a.properties文件的时候路径需要些成“/WEB-INF/classes/a.properties”
//获取资源路径,在src路径下面的东西,最后打包到服务器上的时候是在WEB-INF/classes目录下面的
        //其中都得以/开始,因为这个代表对着项目目录下
        String path = this.getServletContext().getRealPath("/WEB-INF/classes/a.properties");
        Properties p = new Properties();
        p.load(new FileInputStream(path));
        System.out.println(p.get("key"));

这里也说明了properties文件读取方式

Properties p = new Properties();
p.load(new FileInputStream(path));
System.out.println(p.get(“key”));

最有给出这些servlet中类的关系图:

这里写图片描述

如果是通过参数调用的就叫依赖,而当时通过方法得到的就叫挂链。

这里里面servlet继承依赖多个接口,从而具备不同的功能,然后通过其他类的实现这个类,从而具备功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值