day09:Servlet详解runningto

Servlet类由我们来写,但对象由服务器来创建,并且由服务器来调用相应的方法。

Servlet是JavaWeb的三大组件之一,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:

实现Servlet有三种方式:

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

Servlet.java

publicinterfaceServlet{

publicvoidinit(ServletConfigconfig)throwsServletException;

publicServletConfiggetServletConfig();

publicvoidservice(ServletRequestreq,ServletResponseres)

throwsServletException,IOException;

publicStringgetServletInfo();

publicvoiddestroy();

}

我们开始第一个Servlet应用吧!首先在webapps目录下创建helloservlet目录,它就是我们的应用目录了,然后在helloservlet目录中创建准备JavaWeb应用所需内容:

接下来我们开始准备完成Servlet,完成Servlet需要分为两步:

HelloServlet.java

publicclassHelloServletimplementsServlet{

publicvoidinit(ServletConfigconfig)throwsServletException{}

publicServletConfiggetServletConfig(){returnnull;}

publicvoiddestroy(){}

publicStringgetServletInfo(){returnnull;}

throwsServletException,IOException{

System.out.println("helloservlet!");

我们暂时忽略Servlet中其他四个方法,只关心service()方法,因为它是用来处理请求的方法。我们在该方法内给出一条输出语句!

web.xml(下面内容需要背下来)

hello

cn.itcast.servlet.HelloServlet

/helloworld

在web.xml中配置Servlet的目的其实只有一个,就是把访问路径与一个Servlet绑定到一起,上面配置是把访问路径:"/helloworld"与"cn.itcast.servlet.HelloServlet"绑定到一起。

通过这个元素关联在一起了!

接下来,我们编译HelloServlet,注意,编译HelloServlet时需要导入servlet-api.jar,因为Servlet.class等类都在servlet-api.jar中。

javac-classpathF:/tomcat6/lib/servlet-api.jar-d.HelloServlet.java

1.1Servlet的出生

服务器会在Servlet第一次被访问时创建Servlet,或者是在服务器启动时创建Servlet。如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置。也就是说默认情况下,Servlet是在第一次被访问时由服务器创建的。

在Servlet被创建后,服务器会马上调用Servlet的voidinit(ServletConfig)方法。请记住,Servlet出生后马上就会调用init()方法,而且一个Servlet的一生。这个方法只会被调用一次。这好比小孩子出生后马上就要去剪脐带一样,而且剪脐带一生只有一次。

我们可以把一些对Servlet的初始化工作放到init方法中!

1.2Servlet服务

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

1.3Servlet的离去

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

1.4测试生命周期方法

publicvoidinit(ServletConfigconfig)throwsServletException{

System.out.println("Servlet被创建了!");

publicvoiddestroy(){

System.out.println("Servlet要离去了!");

在首次访问HelloServlet时,init方法会被执行,而且也会执行service方法。再次访问时,只会执行service方法,不再执行init方法。在关闭Tomcat时会调用destroy方法。

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

2.1ServletRequest和ServletResponse(第五天会详细讲解这两个对象)

ServletRequest和ServletResponse是Servlet#service()方法的两个参数,一个是请求对象,一个是响应对象,可以从ServletRequest对象中获取请求数据,可以使用ServletResponse对象完成响应。你以后会发现,这两个对象就像是一对恩爱的夫妻,永远不分离,总是成对出现。

HttpServletRequest方法:

HttpServletResponse方法:

2.1ServletConfig

ServletConfig对象对应web.xml文件中的元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取!

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

元素中还可以配置初始化参数:

One

cn.itcast.servlet.OneServlet

paramName1

paramValue1

paramName2

paramValue2

在OneServlet中,可以使用ServletConfig对象的getInitParameter()方法来获取初始化参数,例如:

Stringvalue1=servletConfig.getInitParameter("paramName1");//获取到paramValue1

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

GenericServlet.java

publicabstractclassGenericServletimplementsServlet,ServletConfig,

java.io.Serializable{

privatestaticfinallongserialVersionUID=1L;

privatetransientServletConfigconfig;

publicGenericServlet(){}

@Override

publicStringgetInitParameter(Stringname){

returngetServletConfig().getInitParameter(name);

publicEnumerationgetInitParameterNames(){

returngetServletConfig().getInitParameterNames();

publicServletConfiggetServletConfig(){

returnconfig;

publicServletContextgetServletContext(){

returngetServletConfig().getServletContext();

publicStringgetServletInfo(){

return"";

this.config=config;

this.init();

publicvoidinit()throwsServletException{}

publicvoidlog(Stringmsg){

getServletContext().log(getServletName()+":"+msg);

publicvoidlog(Stringmessage,Throwablet){

getServletContext().log(getServletName()+":"+message,t);

publicabstractvoidservice(ServletRequestreq,ServletResponseres)

publicStringgetServletName(){

returnconfig.getServletName();

在GenericServlet中,定义了一个ServletConfigconfig实例变量,并在init(ServletConfig)方法中把参数ServletConfig赋给了实例变量。然后在该类的很多方法中使用了实例变量config。

如果子类覆盖了GenericServlet的init(StringConfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说GenericServlet的实例变量config的值为null,那么所有依赖config的方法都不能使用了。如果真的希望完成一些初始化操作,那么去覆盖GenericServlet提供的init()方法,它是没有参数的init()方法,它会在init(ServletConfig)方法中被调用。

GenericServlet还实现了ServletConfig接口,所以可以直接调用getInitParameter()、getServletContext()等ServletConfig的方法。

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

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

其实子类也不用去覆盖service(HttpServletRequest,HttpServletResponse)方法,因为HttpServlet还要做另一步简化操作,下面会介绍。

HttpServlet.java

publicabstractclassHttpServletextendsGenericServlet{

protectedvoidservice(HttpServletRequestreq,HttpServletResponseresp)

……

HttpServletRequestrequest;

HttpServletResponseresponse;

try{

request=(HttpServletRequest)req;

response=(HttpServletResponse)res;

}catch(ClassCastExceptione){

thrownewServletException("non-HTTPrequestorresponse");

service(request,response);

在HttpServlet的service(HttpServletRequest,HttpServletResponse)方法会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即可。

publicclassAServletextendsHttpServlet{

publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)

System.out.println("hellodoGet()...");

publicclassBServletextendsHttpServlet{

publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)

System.out.println("hellodoPost()...");

因为一个类型的Servlet只有一个实例对象,那么就有可能会现时出一个Servlet同时处理多个请求,那么Servlet是否为线程安全的呢?答案是:"不是线程安全的"。这说明Servlet的工作效率很高,但也存在线程安全问题!

所以我们不应该在Servlet中随便创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

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

hello1

cn.itcast.servlet.Hello1Servlet

0

/hello1

hello2

cn.itcast.servlet.Hello2Servlet

1

/hello2

hello3

cn.itcast.servlet.Hello3Servlet

2

/hello3

元素中配置元素可以让服务器在启动时就创建该Servlet,其中元素的值必须是大于等于的整数,它的使用是服务器启动时创建Servlet的顺序。上例中,根据的值可以得知服务器创建Servlet的顺序为Hello1Servlet、Hello2Servlet、Hello3Servlet。

的子元素,用来指定Servlet的访问路径,即URL。它必须是以"/"开头!

AServlet

/AServlet

/BServlet

那么这说明一个Servlet绑定了两个URL,无论访问/AServlet还是/BServlet,访问的都是AServlet。

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

注意,通配符是一种模糊匹配URL的方式,如果存在更具体的,那么访问路径会去匹配具体的。例如:

/servlet/hello1

/servlet/*

在${CATALINA_HOME}\conf\web.xml中的内容,相当于写到了每个项目的web.xml中,它是所有web.xml的父文件。

每个完整的JavaWeb应用中都需要有web.xml,但我们不知道所有的web.xml文件都有一个共同的父文件,它在Tomcat的conf/web.xml路径。

conf/web.xml

version="3.0">

default

org.apache.catalina.servlets.DefaultServlet

debug

0

listings

false

jsp

org.apache.jasper.servlet.JspServlet

fork

xpoweredBy

3

/

*.jsp

*.jspx

30

bmp

image/bmp

htm

text/html

index.html

index.htm

index.jsp

一个项目只有一个ServletContext对象!

我们可以在N多个Servlet中来获取这个唯一的对象,使用它可以给多个Servlet传递数据!

与天地同寿!!!这个对象在Tomcat启动时就创建,在Tomcat关闭时才会死去!

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

ServletContext对象的作用是在整个Web应用的动态资源之间共享数据!例如在AServlet中向ServletContext对象中保存一个值,然后在BServlet中就可以获取这个值,这就是共享数据了。

在Servlet中获取ServletContext对象:

在GenericeServlet或HttpServlet中获取ServletContext对象:

publicclassMyServletimplementsServlet{

publicvoidinit(ServletConfigconfig){

ServletContextcontext=config.getServletContext();

publicclassMyServletextendsHttpServlet{

publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse){

ServletContextcontext=this.getServletContext();

ServletContext是JavaWeb四大域对象之一:

所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,下面是ServletContext对象用来操作数据的方法:

还可以使用ServletContext来获取在web.xml文件中配置的应用初始化参数!注意,应用初始化参数与Servlet初始化参数不同:

web.xml

...

Stringvalue1=context.getInitParameter("paramName1");

Stringvalue2=context.getInitParameter("paramName2");

System.out.println(value1+","+value2);

Enumerationnames=context.getInitParameterNames();

while(names.hasMoreElements()){

System.out.println(names.nextElement());

5.1获取真实路径(*****)

还可以使用ServletContext对象来获取Web应用下的资源,例如在hello应用的根目录下创建a.txt文件,现在想在Servlet中获取这个资源,就可以使用ServletContext来获取。

5.2获取资源流

不只可以获取资源的路径,还可以通过ServletContext获取资源流,即把资源以输入流的方式获取:

5.3获取指定目录下所有资源路径

还可以使用ServletContext获取指定目录下所有资源路径,例如获取/WEB-INF下所有资源的路径:

Setset=context.getResourcePaths("/WEB-INF");

System.out.println(set);

[/WEB-INF/lib/,/WEB-INF/classes/,/WEB-INF/b.txt,/WEB-INF/web.xml]

注意,本方法必须以"/"开头!!!

一个项目中所有的资源被访问都要对访问量进行累加!

创建一个int类型的变量,用来保存访问量,然后把它保存到ServletContext的域中,这样可以保存所有的Servlet都可以访问到!

相信各位一定见过很多访问量统计的网站,即"本页面被访问过XXX次"。因为无论是哪个用户访问指定页面,都会累计访问量,所以这个访问量统计应该是整个项目共享的!很明显,这需要使用ServletContext来保存访问量。

ServletContextapplication=this.getServletContext();

Integercount=(Integer)application.getAttribute("count");

if(count==null){

count=1;

}else{

count++;

response.setContentType("text/html;charset=utf-8");

response.getWriter().print("

本页面一共被访问"+count+"次!

");

application.setAttribute("count",count);

获取类路径资源,类路径对一个JavaWeb项目而言,就是/WEB-INF/classes和/WEB-INF/lib/每个jar包!

这里要讲的是获取类路径下的资源,对于JavaWeb应用而言,就是获取classes目录下的资源。

InputStreamin=this.getClass().getResourceAsStream("/xxx.txt");

System.out.println(IOUtils.toString(in));

InputStreamin=this.getClass().getClassLoader().getResourceAsStream("xxx.txt");

THE END
1.八字算命精准测算方法免费算命免费算命姓名姻缘配对八字算命是中华传统文化中的一种古老方法,通过分析一个人的出生年、月、日、时四个要素来预测其命运和性格。随着科技的发展,现在也有很多八字算命软件和网站可以进行精准测算。下面就让我们一起来了解一下八字算命精准测算方法吧! 八字算命中最重要的就是“八字排盘”。在八字排盘过程中,需要根据用户的出生年月日时等http://www.zgxwzx.com.cn/mfsm/33882.html
2.如何测什么命最准的测命方法如何测什么命 最准的测命方法 在这个瞬息万变的时代,很多人都渴望了解自己的命运,以便做出更好的决策,追寻理想的生活。命理学,作为一门古老而神秘的学问,给了我们洞察自我的机会。那么,如何测什么命?本文将带您深入探讨这个引人入胜的话题。 命运的起源:了解命理学http://www.juicychina.net/view/57483
3.测命运最准的方法,网上名字测分准不准每个人都想知道自己的命运,了解自己的性格特点和未来的走向。现在,有很多方法可以帮助我们了解自己的命运,其中一种比较流行的方法是测名字。但网上名字测分到底准不准呢?本文从四个方面详细阐述了测命运最准的方法,让读者更加了解这个话题。 一、姓名学基础 http://www.yisuanyuan.com/a/254113.html
4.来看看印度人是如何测命的提起印度,除了扑面而来的咖喱味儿,你还会想到什么? 重新加载 挂满了人的火车? 重新加载 还是全民开挂的种族天赋? 讲真的,每次一听到有关隔壁三哥的故事,身处在东方小孟买的鲲都会被强制刷新一波三观。 而作为一名职业命理师,鲲当然也会时不时地去了解一些来自世界各地不同的占卜测命方法。这不,最近印度玄学又成功https://www.douban.com/note/736249501/
5.生辰八字算命八字算命八字预测八字算命可以算什么 批八字算命一生命运 八字看命中注定的配偶 八字算命2022年流年运势 八字算命婚姻免费测试 生辰八字喜用神查询表 八字看十大贵命命格 八字测你命带多少桃花 免费八字测姻缘何时到 八字测未来另一半的长相性格 生辰八字一生事业算命 起名字2024免费八字起名 https://bz.99166.com/
6.文献阅读笔记:SmartHomesthatMonitorBreathingandHeartRateVR是无线系统,需要最小信噪比SNR来从噪声中提取信号。最大距离为8m,距离越远,信噪比越低 3.准静态需求 全身运动引起的信号变化会覆盖生命体征引起的微小变化 4.非人类的运动 风扇不会影响,宠物会被识别为受测者 9. Conclusion and Future Opportunitieshttps://blog.csdn.net/chiyue_mio/article/details/120761775
7.真正的免费测名字八字最准,免费算命姓名测试打分真正的免费测名字八字最准 2021年姓名八字评分测算,名字测试打分最准确生辰八字 2024-11-17 提起2021年姓名八字评分测算,大家都知道,有人问名字测试打分最准确生辰八字,另外,还有人想问八字测测2021年运势?你知道这是怎么回事?其实汪志达 姓名八字吉凶评分测算,下面就一起来看看名字测试打分最准确生辰八字,希望能够帮助http://www.jsfctech.com/yx/7558u/
8.预测命运最准的方法理想股票技术论坛想要找到最准确的方法来预测自己的命运吗?我们提供一系列科学有效的方法,帮助您选择合适的方法,并准确地预测自己的命运。不管是通过基于股票技术分析的指标公式,还是借助精通股票基本面的知识,我们都将为您提供有关命运预测的专业指导和建议。立即开始,掌握预测命运的https://www.55188.com/tag-02357901.html
9.姓名测试打分免费测名字打分起名字测试打分算命姓名测试打分 (姓名网 xingming.com),最准的名字打分免费测试,内容包括:名字测试打分,生辰八字算命,姓名打分,姓名缘分配对,宝宝起名打分测试,姓名爱情测试,生肖运程等,周易姓名测分,名字打分100等测算内容。https://m.xingming.com/
10.生命体征的测量方法及注意事项合集(一)测体温的注意事项: 欧阳历创编 2021..02.09 欧阳历创编 2021..02.09 1、根据病人的病情、自理程度选择合适的测温方法及 部位。婴幼儿,昏迷、精神异常、口鼻手术、不合作者、 呼吸困难不用口表测量温度;测腋表时要擦干腋窝,极度 消瘦的病人不用腋表测温;腹泻、直肠或肛门手术,心肌 梗死患者不宜用直肠测温法。https://wenku.baidu.com/aggs/eba5a50216fc700abb68fca5.html
11.公开2024龙年清宫图正版生男生女表!超准的性别计算公式详解测量孩子出生最准确的科学方法 民间流传的各种测胎儿性别的方法,很多都是从前人的经验中总结出来的,并没有经过科学的验证,所以不可信,只有用科学的方法来鉴定胎儿的性别,才是最准确可靠的。目前我国禁止医院鉴定胎儿性别,其实生男生女都是好的,宝宝的健康才是最重要的。 https://www.snsnb.com/zt/show-2522.html
12.崇道命理网算命大师真人在线算命生辰八字算命崇道命理网,算卦街真人算命一条街,算命大师,在线算命,网上算命,网络算命,网上算卦,周易算命网,天地和命理网,易灵,真人算命,免费算命网,算命网,算命最准的网站,算命网站,最准算命网,周易算命网,算命大师在线咨询,命理网,每日财运。https://www.ffxlzx.com/
13.寿命检测范文7篇(全文)3.2 预测方法 3.2.1 最小允许壁厚确定 根据美国ASME锅炉压力容器N-480《管道腐蚀减薄验收准则》进行评定。该准则规定对腐蚀管道评定的范围必须满足以下条件:0.3t≤tp≤0.875t式中[2], t为正常时管道的壁厚, 即原设计时无腐蚀的壁厚;tp为评定寿命时的最大腐蚀坑深度剩余壁厚, 即最小允许壁厚。 https://www.99xueshu.com/w/ikeyqd7dj8c3.html