Servlet基础

来源:互联网 发布:深入浅出数据分析阅读 编辑:程序博客网 时间:2024/04/30 10:27

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得到ServletContextServletContext 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
原创粉丝点击