浅谈Servlet开发技术基础
一、servlet概述
1.sun公司提供的动态web资源开发技术。本质是上一段java小程序,要求这个小程序必须实现servlet接口,以便服务器能够调用。
2.开发servlet的两个步骤
*实验:servlet的快速入门
(1)步骤一:写一个java程序实现servlet接口(此处直接继承了默认实现类genericservlet)
package cn.itheima; import java.io.*; import javax.servlet.*; public class firstservlet extends genericservlet{ public void service(servletrequest req, servletresponse res) throws servletexception, java.io.ioexception{ res.getoutputstream().write("my firstservlet!".getbytes()); } }
(2)将编译好的带包的.class放到web-inf/classes下以外,还要配置web应用的 web.xml注册servlet
<servlet> <servlet-name>firstservlet</servlet-name> <servlet-class>cn.itheima.firstservlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>firstservlet</servlet-name> <url-pattern>/firstservlet</url-pattern> </servlet-mapping>
3.利用myeclipse开发servlet
二、servlet的详述
1.生命周期:一件事物什么时候生,什么时候死,在生存期间必然会做的事情,所有这些放在一起就是该事物的声明周期。
2.servlet的生命周期:通常情况下,servlet第一次被访问的时候在内存中创建对象,在创建后立即调用init()方法进行初始化。对于每一次请求都掉用service(req,resp)方法处理请求,此时会用request对象封装请求信息,并用response对象(最初是空的)代表响应消息,传入到service方法里供使用。当service方法处理完成后,返回服务器服务器根据response中的信息组织称响应消息返回给浏览器。响应结束后servlet并不销毁,一直驻留在内存中等待下一次请求。直到服务器关闭或web应用被移除出虚拟主机,servlet对象销毁并在销毁前调用destroy()方法做一些善后的事情。
3.servlet接口的继承结构
servlet接口:定义了一个servlet应该具有的方法,所有的servlet都应该直接或间接实现此接口
|
|----genericservlet:对servlet接口的默认实现,通用servlet,这是一个抽象类,其中的大部分方法都做了默认实现,只有service方法是一个抽象方法需要继承者自己实现
|
|----httpservlet:对http协议进行了优化的servlet,继承自genericservlet类,并且实现了其中的service抽象方法,默认的实现中判断了请求的请求方式,并根据请求方式的不同分别调用不同的doxxx()方法。通常我们直接继承httpservlet即可
4.web.xml注册servlet的注意事项
4.1利用<servlet><servlet-mapping>标签注册一个servlet
<servlet> <servlet-name>firstservlet</servlet-name> <servlet-class>cn.itheima.firstservlet</servlet-class>
注意:此处要的是一个servlet的完整类名,不是包含.java或.class扩展的文件路径
</servlet> <servlet-mapping> <servlet-name>firstservlet</servlet-name> <url-pattern>/firstservlet</url-pattern> </servlet-mapping>
4.2一个<servlet>可以对应多个<servlet-mapping>
4.3可以用*匹配符配置<serlvet-mapping>,但是要注意,必须是*.do或者/开头的以/*结束的路径。
~由于匹配符的引入有可能一个虚拟路径会对应多个servlet-mapping,此时哪个最像找哪个servlet,并且*.do级别最低。
4.4可以为<servlet>配置<load-on-startup>子标签,指定servlet随着服务器的启动而加载,其中配置的数值指定启动的顺序
servlet> <servlet-name>invoker</servlet-name> <servlet-class> org.apache.catalina.servlets.invokerservlet </servlet-class> <load-on-startup>2</load-on-startup> </servlet>
4.5缺省servlet:如果一个servlet的对外访问路径被设置为/,则该servlet就是一个缺省servlet,其他servlet不处理的请求都由它来处理
~在conf/web.xml中配置了缺省servlet,对静态资源的访问和错误页面的输出就是由这个缺省servlet来处理的。如果我们自己写一个缺省servlet把爸爸web.xml中的缺省servlet覆盖的话,会导致静态web资源无法访问。所以不推荐配置。
4.6servlet的线程安全问题
4.6.1由于通常情况下,一个servlet在内存只有一个实例处理请求,当多个请求发送过来的时候就会有多个线程操作该servlet对象,此时可能导致线程安全问题。
(1)serlvet的成员变量可能存在线程安全问题
*实验:定义一个成员变量inti=0;在doxxx()方法中进行i++操作并输出i值到客户端,此时由于延迟可能导致线程安全问题
(2)serlvet操作资源文件时,多个线程操作同一文件引发线程安全问题
*实验:请求带着一个参数过来,servlet将请求参数写入到一个文件,再读取该文件,将读取到的值打印到客户端上,有可能有线程安全问题
4.6.2解决方法
(1)利用同步代码块解决问题。缺陷是,同一时间同步代码块只能处理一个请求,效率很低下,所以同步代码块中尽量只包含核心的导致线程安全问题的代码。
(2)为该servlet实现singlethreadmodel接口,此为一个标记接口,被标记的servlet将会在内存中保存一个servlet池,如果一个线程来了而池中没有servlet对象处理,则创建一个新的。如果池中有空闲的servlet则直接使用。这并不能真的解决线程安全问题。此接口已经被废弃。
(3)两种解决方案都不够完美,所以尽量不要在servlet中出现成员变量。
三、servletconfig
1.代表servlet配置的对象,可以在web.xml中<servlet>中配置
<servlet> <servlet-name>demo5servlet</servlet-name> <servlet-class>cn.itheima.demo5servlet</servlet-class> <init-param> <param-name>data1</param-name> <param-value>value1</param-value> </init-param> </servlet>
然后在servlet中利用this.getservletconfig()获取servletconfig对象,该对象提供了getinitparameter()和getinitparameternames()方法,可以遍历出配置中的配置项。
不想在servlet中写死的内容可以配置到此处。
四、servletcontext
1.代表当前web应用的对象。
2.作为域对象使用,在不同servlet之间传递数据,作用范围是整个web应用
生命周期:当web应用被加载进容器时创建代表整个web应用的servletcontext对象。当服务器关闭或web应用被移除出容器时,servletcontext对象跟着销毁。
~域:一个域就理解为一个框,这里面可以放置数据,一个域既然称作域,他就有一个可以被看见的范围,这个范围内都可以对这个域中的数据进行操作,那这样的对象就叫做域对象。
3.在web.xml可以配置整个web应用的初始化参数,利用servletcontext去获得
<context-param> <param-name>param1</param-name> <param-value>pvalue1</param-value> </context-param> this.getservletcontext().getinitparameter("param1") this.getservletcontext().getinitparameternames()
4.在不同servlet之间进行转发
this.getservletcontext().getrequestdispatcher("/servlet/demo10servlet").forward(request, response);
方法执行结束,service就会返回到服务器,再有服务器去调用目标servlet,其中request会重新创建,并将之前的request的数据拷贝进去。
5.读取资源文件
5.1由于相对路径默认相对的是java虚拟机启动的目录,所以我们直接写相对路径将会是相对于tomcat/bin目录,所以是拿不到资源的。如果写成绝对路径,当项目发布到其他环境时,绝对路径就错了。
5.2为了解决这个问题servletcontext提供了this.getservletcontext().getrealpath("/1.properties"),给进一个资源的虚拟路径,将会返回该资源在当前环境下的真实路径。this.getservletcontext().getresourceasstream("/1.properties"),给一个资源的虚拟路径返回到该资源真实路径的流。
5.3当在非servlet下获取资源文件时,就没有servletcontext对象用了,此时只能用类加载器
classloader.getresourceasstream("../../1.properties"),此方法利用类加载器直接将资源加载到内存中,有更新延迟的问题,以及如果文件太大,占用内存过大。
classloader.getresource("../1.properties").getpath(),直接返回资源的真实路径,没有更新延迟的问题。
总结
以上就是本文关于浅谈servlet开发技术基础的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
以及本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
上一篇: MySql5.7.11编译安装及修改root密码的方法小结
下一篇: 最小树形图模板朱刘算法分享
推荐阅读
-
浅谈Servlet开发技术基础
-
Servlet会话技术基础解析
-
浅谈PHP Extension的开发——基础篇_php技巧
-
PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-1 开始了解php_PHP教程
-
PHP和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍_PHP教程
-
PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-3 代码组织和重用2_PHP教程
-
PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-1 开始了解php
-
PHP和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介_PHP
-
浅谈PHP Extension的开发基础篇
-
PHP和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍_php基础