当前位置: 移动技术网 > IT编程>开发语言>Jsp > servlet详解(第一篇)

servlet详解(第一篇)

2018年10月03日  | 移动技术网IT编程  | 我要评论

servlet基本概述

生命周期方法:

void init(servletconfig):出生之后(1次);
void service(servletrequest request, servletresponse response):每次处理请求时都会被调用;
void destroy():临死之前(1次);

特性:

单例,一个类只有一个对象;当然可能存在多个servlet类!
线程不案例的,所以它的效率是高的!
servlet类由我们来写,但对象由服务器来创建,并且由服务器来调用相应的方法。

1 什么是servlet

    ?接收请求数据;
    ?处理请求;
    ?完成响应。

例如:客户端发出登录请求,或者输出注册请求,这些请求都应该由servlet来完成处理!servlet需要我们自己来编写,每个servlet必须实现javax.servlet.servlet接口。

2 实现servlet的方式(由我们自己来写!)

实现servlet有三种方式:
实现javax.servlet.servlet接口;
继承javax.servlet.genericservlet类;
继承javax.servlet.http.httpservlet类;

  通常我们会去继承httpservlet类来完成我们的servlet,但学习servlet还要从javax.servlet.servlet接口开始学习

public interface servlet [servlet中的方法大多数不由我们来调用,而是由tomcat来调用。并且servlet的对象也不由我们来创建,由tomcat来创建!]{
    public void init(servletconfig 
    public servletconfig getservletcconfig) throws servletexception;onfig();
    public void service(servletrequest req, servletresponse res)
            throws servletexception, ioexception;
    public string getservletinfo();
    public void destroy();
}

3 创建helloservlet应用

我们开始第一个servlet应用吧!首先在webapps目录下创建helloservlet目录,它就是我们的应用目录了,然后在helloservlet目录中创建准备javaweb应用所需内容:
?创建/helloservlet/web-inf目录;
?创建/helloservlet/web-inf/classes目录;
?创建/helloservlet/web-inf/lib目录;
  创建/helloservlet/web-inf/web.xml文件;
  接下来我们开始准备完成servlet,完成servlet需要分为两步:
?编写servlet类;
?在web.xml文件中配置servlet;
helloservlet.java
public class helloservlet implements servlet {
    public void init(servletconfig config) throws servletexception {}
    public servletconfig getservletconfig() {return null;}
    public void destroy() {}
    public string getservletinfo() {return null;}

    public void service(servletrequest req, servletresponse res)
            throws servletexception, ioexception {
        system.out.println("hello servlet!");
    }
}
web.xml
    
        hello
        cn.itcast.servlet.helloservlet
    
    
        hello
        /helloworld
      

web.xml中配置servlet详解

在web.xml中配置servlet的目的其实只有一个,就是把访问路径与一个servlet绑定到一起,上面配置是把访问路径:“/helloworld”与“cn.itcast.servlet.helloservlet”绑定到一起。
?:指定helloservlet这个servlet的名称为hello;
?:指定/helloworld访问路径所以访问的servlet名为hello。
和通过这个元素关联在一起了!
接下来,我们编译helloservlet,注意,编译helloservlet时需要导入servlet-api.jar,因为servlet.class等类都在servlet-api.jar中。
javac -classpath f:/tomcat6/lib/servlet-api.jar -d . helloservlet.java
然后把helloservlet.class放到/helloworld/web-inf/classes/目录下,然后启动tomcat,在浏览器中访问:http://localhost:8080/helloservlet/helloworld即可在控制台上看到输出!
?/helloservlet/web-inf/classes/cn/itcast/servlet/helloservlet.class;

servlet接口详解

1servlet的生命周期

所谓xxx的生命周期,就是说xxx的出生、服务,以及死亡。servlet生命周期也是如此!与servlet的生命周期相关的方法有:

?void init(servletconfig);
?void service(servletrequest,servletresponse);
?void destroy();

1.1 servlet的出生

服务器会在servlet第一次被访问时创建servlet,或者是在服务器启动时创建servlet。如果服务器启动时就创建servlet,那么还需要在web.xml文件中配置。也就是说默认情况下,servlet是在第一次被访问时由服务器创建的。
而且一个servlet类型,服务器只创建一个实例对象,例如在我们首次访问时,服务器通过“/helloworld”找到了绑定的servlet名称为cn.itcast.servlet.helloservlet,然后服务器查看这个类型的servlet是否已经创建过,如果没有创建过,那么服务器才会通过反射来创建helloservlet的实例。当我们再次访问时,服务器就不会再次创建helloservlet实例了,而是直接使用上次创建的实例。
在servlet被创建后,服务器会马上调用servlet的void init(servletconfig)方法。请记住, servlet出生后马上就会调用init()方法,而且一个servlet的一生。这个方法只会被调用一次。这好比小孩子出生后马上就要去剪脐带一样,而且剪脐带一生只有一次。
我们可以把一些对servlet的初始化工作放到init方法中!

1.2 servlet服务

  当服务器每次接收到请求时,都会去调用servlet的service()方法来处理请求。服务器接收到一次请求,就会调用service() 方法一次,所以service()方法是会被调用多次的。正因为如此,所以我们才需要把处理请求的代码写到service()方法中!

1.3 servlet的离去

  servlet是不会轻易离去的,通常都是在服务器关闭时servlet才会离去!在服务器被关闭时,服务器会去销毁servlet,在销毁servlet之前服务器会先去调用servlet的destroy()方法,我们可以把servlet的临终遗言放到destroy()方法中,例如对某些资源的释放等代码放到destroy()方法中。

2 servlet接口相关类型

在servlet接口中还存在三个我们不熟悉的类型:

servletrequest:service() 方法的参数,它表示请求对象,它封装了所有与请求相关的数据,它是由服务器创建的;
servletresponse:service()方法的参数,它表示响应对象,在service()方法中完成对客户端的响应需要使用这个对象;
servletconfig:init()方法的参数,它表示servlet配置对象,它对应servlet的配置信息,那对应web.xml文件中的元素。

2.1 servletrequest和servletresponse详解

servletrequest和servletresponse是servlet#service() 方法的两个参数,一个是请求对象,一个是响应对象,可以从servletrequest对象中获取请求数据,可以使用servletresponse对象完成响应。你以后会发现,这两个对象就像是一对恩爱的夫妻,永远不分离,总是成对出现。
servletrequest和servletresponse的实例由服务器创建,然后传递给service()方法。如果在service() 方法中希望使用http相关的功能,那么可以把servletrequest和servletresponse强转成httpservletrequest和httpservletresponse。这也说明我们经常需要在service()方法中对servletrequest和servletresponse进行强转,这是很心烦的事情。不过后面会有一个类来帮我们解决这一问题的。

httpservletrequest方法:

string getparameter(string paramname):获取指定请求参数的值;

string getmethod():获取请求方法,例如get或post;

string getheader(string name):获取指定请求头的值;

void setcharacterencoding(string encoding):设置请求体的编
码!因为get请求没有请求体,所以这个方法只只对post请求有效。当调用request.setcharacterencoding(“utf-8”)之后,再通过getparameter()方法获取参数值时,那么参数值都已经通过了转码,即转换成了utf-8编码。所以,这个方法必须在调用getparameter()方法之前调用!

httpservletresponse方法:
printwriter getwriter():获取字符响应流,使用该流可以向客户端输出响应信息。例如response.getwriter().print(“hello javaweb!”);

servletoutputstream getoutputstream():获取字节响应流,当需要向客户端响应字节数据时,需要使用这个流,例如要向客户端响应图片;

void setcharacterencoding(string encoding):用来设置字符响应流的编码,例如在调用setcharacterencoding(“utf-8”);之后,再response.getwriter()获取字符响应流对象,这时的响应流的编码为utf-8,使用response.getwriter()输出的中文都会转换成utf-8编码后发送给客户端;

void setheader(string name, string value):向客户端添加响应头信息,例如setheader(“refresh”, “3;url=”),表示3秒后自动刷新到;

void setcontenttype(string contenttype):该方法是setheader(“content-type”, “xxx”)的简便方法,即用来添加名为content-type响应头的方法。content-type响应头用来设置响应数据的mime类型,例如要向客户端响应jpg的图片,那么可以setcontenttype(“image/jepg”),如果响应数据为文本类型,那么还要台同时设置编码,例如setcontenttype(“text/html;chartset=utf-8”)表示响应数据类型为文本类型中的html类型,并且该方法会调用setcharacterencoding(“utf-8”)方法;

void senderror(int code, string errormsg):向客户端发送状态码,以及错误消息。例如给客户端发送404:response(404, “您要查找的资源不存在!”)。

2.2 servletconfig

servletconfig对象对应web.xml文件中的元素。例如你想获取当前servlet在web.xml文件中的配置名,那么可以使用servletconfig.getservletname()方法获取!
这里写图片描述

servletconfig对象是由服务器创建的,然后传递给servlet的init()方法,你可以在init()方法中使用它!

string getservletname():获取servlet在web.xml文件中的配置名称,即指定的名称;
servletcontext getservletcontext():用来获取servletcontext对象,servletcontext会在后面讲解;
string getinitparameter(string name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;
enumeration getinitparameternames():用来获取在web.xml中配置的所有初始化参数名称;

genericservlet

genericservlet是servlet接口的实现类,我们可以通过继承genericservlet来编写自己的servlet。下面是genericservlet类的源代码:

genericservlet.java
public abstract class genericservlet implements servlet, servletconfig,
        java.io.serializable {
    private static final long serialversionuid = 1l;
    private transient servletconfig config;
    public genericservlet() {}
    @override
    public void destroy() {}
    @override
    public string getinitparameter(string name) {
        return getservletconfig().getinitparameter(name);
    }
    @override
    public enumeration getinitparameternames() {
        return getservletconfig().getinitparameternames();
    }
    @override
    public servletconfig getservletconfig() {
        return config;
    }
    @override
    public servletcontext getservletcontext() {
        return getservletconfig().getservletcontext();
    }
    @override
    public string getservletinfo() {
        return "";
    }
    @override
    public void init[实现了servlet的init(servletconfig)方法,把参数config赋给了本类的成员config,然后再调用本类自己的无参的init()方法。](servletconfig config) throws servletexception {
        this.config = config;
        this.init();
    }
    public void init[这个方法是genericservlet自己的方法,而不是从servlet继承下来的。当我们自定义servlet时,如果想完成初始化作用就不要再重复init(servletconfig)方法了,而是应该去重写init()方法。因为在genericservlet中的init(servletconfig)方法中保存了servletconfig对象,如果覆盖了保存servletconfig的代码,那么就不能再使用servletconfig了。]() throws servletexception {}
    public void log(string msg) {
        getservletcontext().log(getservletname() + ": " + msg);
    }
    public void log(string message, throwable t) {
        getservletcontext().log(getservletname() + ": " + message, t);
    }
    @override
    public abstract void service(servletrequest req, servletresponse res)
            throws servletexception, ioexception;
    @override
    public string getservletname() {
        return config.getservletname();
    }
}

2 genericservlet的init()方法

在genericservlet中,定义了一个servletconfig config实例变量,并在init(servletconfig)方法中把参数servletconfig赋给了实例变量。然后在该类的很多方法中使用了实例变量config。
如果子类覆盖了genericservlet的init(stringconfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说genericservlet的实例变量config的值为null,那么所有依赖config的方法都不能使用了。如果真的希望完成一些初始化操作,那么去覆盖genericservlet提供的init()方法,它是没有参数的init()方法,它会在init(servletconfig)方法中被调用。

3 实现了servletconfig接口

  genericservlet还实现了servletconfig接口,所以可以直接调用getinitparameter()、getservletcontext()等servletconfig的方法。

httpservlet(从事javaweb开发的重点)

上面说了servlet接口和genericservlet都只是httpservlet的父类和父接口,从事web网站开发的人大部分用到的是httpservlrt这个类,下面是这个类的详解

1 httpservlet概述

httpservlet类是genericservlet的子类,它提供了对http请求的特殊支持,所以通常我们都会通过继承httpservlet来完成自定义的servlet。

2 httpservlet覆盖了service()方法

httpservlet类中提供service(httpservletrequest,httpservletresponse)方法,这个方法是httpservlet自己的方法,不是从servlet继承来的。在httpservlet的service(servletrequest,servletresponse)方法中会把servletrequest和servletresponse强转成httpservletrequest和httpservletresponse,然后调用service(httpservletrequest,httpservletresponse)方法,这说明子类可以去覆盖service(httpservletrequest,httpservletresponse)方法即可,这就不用自己去强转请求和响应对象了。

3 doget()和dopost()

在httpservlet的service(httpservletrequest,httpservletresponse)方法会去判断当前请求是get还是post,如果是get请求,那么会去调用本类的doget()方法,如果是post请求会去调用dopost()方法,这说明我们在子类中去覆盖doget()或dopost()方法即可。

public class aservlet extends httpservlet {
    public void doget(httpservletrequest request, httpservletresponse response)
            throws servletexception, ioexception {
        system.out.println("hello doget()...");
    }
}
public class bservlet extends httpservlet {
    public void dopost(httpservletrequest request, httpservletresponse response)
            throws servletexception, ioexception {
        system.out.println("hello dopost()...");
    }
}

servlet其他细节

不要在servlet中创建成员!创建局部变量即可!

可以创建无状态成员!

可以创建有状态的成员,但状态必须为只读的!

1 servlet与线程安全

因为一个类型的servlet只有一个实例对象,那么就有可能会现时出一个servlet同时处理多个请求,那么servlet是否为线程安全的呢?答案是:“不是线程安全的”。这说明servlet的工作效率很高,但也存在线程安全问题!
所以我们不应该在servlet中便宜创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

2 让服务器在启动时就创建servlet

默认情况下,服务器会在某个servlet第一次收到请求时创建它。也可以在web.xml中对servlet进行配置,使服务器启动时就创建servlet。

        hello1
        cn.itcast.servlet.hello1servlet
        0[在中配置,其中给出一个非负整数!]
    
    
        hello1
        /hello1
    
    
        hello2
        cn.itcast.servlet.hello2servlet
        1
    
    
        hello2
        /hello2
    
    
        hello3
        cn.itcast.servlet.hello3servlet
        2
    
    
        hello3
        /hello3
    
在元素中配置元素可以让服务器在启动时就创建该servlet,其中元素的值必须是大于等于的整数,它的使用是服务器启动时创建servlet的顺序。上例中,根据的值可以得知服务器创建servlet的顺序为hello1servlet、hello2servlet、hello3servlet。

3url-pattern>

是的子元素,用来指定servlet的访问路径,即url。它必须是以“/”开头!

1)可以在中给出多个,例如:
  
    aservlet
    /aservlet
    /bservlet
    

那么这说明一个servlet绑定了两个url,无论访问/aservlet还是/bservlet,访问的都是aservlet。

2)还可以在中使用通配符,所谓通配符就是星号“*”,星号可以匹配任何url前缀或后缀,使用通配符可以命名一个servlet绑定一组url,例如:
?/servlet/*[路径匹配]:/servlet/a、/servlet/b,都匹配/servlet/*;
?*.do[扩展名匹配]:/abc/def/ghi.do、/a.do,都匹配*.do;
?/*[啥都匹配]:匹配所有url;

请注意,通配符要么为前缀,要么为后缀,不能出现在url中间位置,也不能只有通配符。例如:/.do就是错误的,因为星号出现在url的中间位置上了。.*也是不对的,因为一个url中最多只能出现一个通配符。

4 web.xml文件的继承(了解)

 在${catalina_home}\conf\web.xml中的内容,相当于写到了每个项目的web.xml中,它是所有web.xml的父文件。
每个完整的javaweb应用中都需要有web.xml,但我们不知道所有的web.xml文件都有一个共同的父文件,它在tomcat的conf/web.xml路径。

conf/web.xml



     
        default[它的优先级最低,如果一个请求没有人处理,那么它来处理!它显示404。]
        org.apache.catalina.servlets.defaultservlet[当访问路径不存在时,会执行该servlet!其实我们在访问时也是在执行这个servlet。 ]
        
            debug
            0
        
        
            listings
            false
        
        1


    
        jsp
        org.apache.jasper.servlet.jspservlet
        
            fork
            false
        
        
            xpoweredby
            false
        
        3
    

    
        default
        /[匹配所有url,也就是说用户访问的url路径没有匹配的页面时,那么执行的就是名为default的servlet,即org.apache.catalina.servlets.defaultservlet]
    

    
        jsp
        *.jsp[任何url后缀为jsp的访问,都会执行名为jsp的servlet,即org.apache.jasper.servlet.jspservlet]
        *.jspx
    

    
        30[session的默认超时时间为30分钟,后面讲session时再深入。]
    

    
    
        bmp
        image/bmp
    
    
        htm
        text/html
    [mime类型用来标识网络上资源的媒体类型,这里举例为bmp和html两种mime类型。]

    
        
        index.htm
        index.jsp
    [在应用的web.xml中如果没有对进行覆盖,那么默认主页为、、index.jsp]

servletcontext(重要)

一个项目只有一个servletcontext对象!
我们可以在n多个servlet中来获取这个唯一的对象,使用它可以给多个servlet传递数据!
与天地同寿!!!这个对象在tomcat启动时就创建,在tomcat关闭时才会死去!

1 servletcontext概述

服务器会为每个应用创建一个servletcontext对象:

servletcontext对象的创建是在服务器启动时完成的;
servletcontext对象的销毁是在服务器关闭时完成的。
  servletcontext对象的作用是在整个web应用的动态资源之间共享数据!例如在aservlet中向servletcontext对象中保存一个值,然后在bservlet中就可以获取这个值,这就是共享数据了。

2 获取servletcontext

?servletconfig#getservletcontext();
?genericservlet#getservletcontext();
?httpsession#getservletcontext()
?servletcontextevent#getservletcontext()
在servlet中获取servletcontext对象:
?在void init(servletconfig config)中:servletcontext context = config.getservletcontext();,servletconfig类的getservletcontext()方法可以用来获取servletcontext对象;
在genericeservlet或httpservlet中获取servletcontext对象:
?genericservlet类有getservletcontext()方法,所以可以直接使用this.getservletcontext()来获取;
public class myservlet implements servlet {
public void init(servletconfig config) {
    servletcontext context = config.getservletcontext();
}
…
}
public class myservlet extends httpservlet {
public void doget(httpservletrequest request, httpservletresponse response) {
    servletcontext context = this.getservletcontext();
}
}

3 域[域对象就是用来在多个servlet中传递数据

?域对象必须有要存数据功能
?域对象必须要有取数据功能
域对象内部其实有一个map]对象的功能
servletcontext是javaweb四大域对象之一:
?pagecontext;
?servletrequest;
?httpsession;
?servletcontext;
所有域对象都有存取数据的功能,因为域对象内部有一个map,用来存储数据,下面是servletcontext对象用来操作数据的方法:
?void setattribute(string name, object value):用来存储一个对象,也可以称之为存储一个域属性,例如:servletcontext.setattribute(“xxx”, “xxx”),在servletcontext中保存了一个域属性,域属性名称为xxx,域属性的值为xxx。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与map相同;
?object getattribute(string name):用来获取servletcontext中的数据,当前在获取之前需要先去存储才行,例如:string value = (string)servletcontext.getattribute(“xxx”);,获取名为xxx的域属性;
?void removeattribute(string name):用来移除servletcontext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
?enumeration getattributenames():获取所有域属性的名称;

4 获取应用初始化参数

?servlet也可以获取初始化参数,但它是局部的参数;也就是说,一个servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个servlet准备!
?可以配置公共的初始化参数,为所有servlet而用!这需要使用servletcontext才能使用!
还可以使用servletcontext来获取在web.xml文件中配置的应用初始化参数!注意,应用初始化参数与servlet初始化参数不同:
servletcontext context = this.getservletcontext();[获取servletcontext对象]
        string value1 = context.getinitparameter("paramname1");
        string value2 = context.getinitparameter("paramname2");
[通过参数名,获取参数值]       system.out.println(value1 + ", " + value2);

        enumeration names = context.getinitparameternames();[获取所有应用初始化参数名称]
        while(names.hasmoreelements()) {
            system.out.println(names.nextelement());
        }

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网