Servlet详解(一)

什么是Servlet

Servlet(Server Applet),全称Java Servlet。一个Java Servlet就是一个小型Java应用程序,它可以继承HttpServlet实现,运行在Web服务器中。Servlet 会接收并响应来自浏览器的请求,通常是基于Http协议的请求。

如下图:

创建Servlet

实现Servlet或者继承Servlet的实现类:

方法一:实现Servlet接口

1> 实现接口Servlet并实现以下几个 生命周期 方法:

  • init(ServletConfig config):当Servlet被创建时,将会使用此方法对自己初始化

  • service(ServletRequest req,ServletResponse res):当浏览器对服务器发出请求后,servlet会使用该方法处理请求

  • destory():当Servlet处理完请求后,在销毁前会调用此方法,然后GC会将它回收掉

生命周期:

当client访问Servlet时,创建并初始化Servlet, 在服务器中只有一个Servlet实例,当服务器被关闭时,Servlet才会被销毁。

2> 在 web.xml 中注册Servlet,告诉服务器有这么一个Servlet

什么?太麻烦了?还好我们有注解 @WebServlet

使用java注解注册Servlet

启动服务器,访问此Servlet:

在tomcat中的项目结构:

我们可以看到,Java编译的class文件全部被eclipse放置到WEB-INF—> classes目录下了。

输出:

生命周期时序图:

服务器是如何查找Servlet的?

我们看到,通过 <url-pattern> 访问servlet,最后访问到他的class文件。

首先根据 <url-pattern> 找到它的name,然后根据name找到 <servlet> <name> 相同的servlet标签,根据name找到 <servlet-class> class路径,使用找到的class生成servlet实例到服务器内存中。

ServletConfig接口:

servlet容器使用servlet配置对象,该对象在初始化期间将信息传递给ServletConfig。

  • String getInitParamter(String name):根据初始化参数名称获取初始化参数的值,如果没有此参数,返回null

  • Enumeration getInitParamterNames():获取所有初始化参数名称,以枚举方式返回,如果没有参数,返回一个空的枚举

web.xml 中初始化参数:

在Servlet service()中对初始化参数进行处理:

请求结果如下:

  • getServletName():获取Servlet的名称 <servlet-name>

  • getServletContext():获取ServletContext上下文对象

点击form表单提交,跳转servlet

方法二、继承GenericServlet

所谓的GenericServlet只是一个Servlet的实现类,因为用户每次使用Servlet接口自定义一个Servlet都会进行许多不必要的操作,所以就封装了一个GenericServlet以方便程序员使用,

使用方法:在方法service()中进行请求的处理,具体请查看源码。

下面是它的源码:

方法三、继承HttpServlet

HttpServlet继承自GenericServlet,是针对Http协议的Servlet,是进一步的封装,

使用只需要继承HttpServlet,重写doGet或doPost方法即可,doGet用来处理get请求,而doPost方法用来进行post请求处理。

源码如下:

Servlet线程安全问题:

Servlet存在这线程安全的问题,

假设在Servlet中放置一个成员变量name,用来接受用户的表单信息。当多个用户访问Servlet时,会对name进行多次赋值,那么用户得到的结果就很有可能出错,因为多个用户共用一块内存。

解决办法也很简单,让每个用户都有一块内存保存自己的name值,只需要将name值保存在方法中,建立一个局部变量即可。因为java方法在被调用时,每次被调用,都会开辟一个新的方法区。

修改Servlet创建时机

通常情况下,servlet在被用户第一次调用时创建,如果servlet要进行非常耗时的创建操作,用户就会等待很久,影响用户体验,所以,我们可以将servlet设置在服务器启动之后,解决这类问题:

web.xml 中,添加加载时间标签:

Servlet访问路径配置

相对路径:

/ 代表 项目路径

/AServlet => http://localhost:8080/ServletDemo/Aservlet

/File/* => /File/ => http://localhost:8080/ServletDemo/File/sfsdfdsfsdfe 匹配任意

匹配范围越大,优先级越低:

两个配置 /File/AServlet/File/*

访问: http://localhost:8080/ServletDemo/File/AServlet

则会访问AServlet,而不会访问第二个路径,因为第一个优先级高。

后缀名匹配:

*.dohttp://localhost:8080/ServletDemo/sfdsfds.do

该方式不常用,Filter过滤器常用

注意:不能同时使用 后缀名 匹配和 相对路径。例如: /File/*.do

ServletContext

项目级别的对象,一个Web项目,有且只有一个ServletContext对象,在项目启动时创建,到项目关闭时销毁,可以理解为这个类集合了项目所有的功能方法,代表了项目,所以这个类非常强大。

我们使用 ServletConfig.getServletContext() 获得这个对象。

功能如下:

获取项目参数

配置项目初始化参数:

获取项目初始化参数:

getServletContext().getInitParamter(String name)

getServletContext().getInitParamterNames()

ServletContext 域

域是服务器两个组件之间的通讯,比如两个Servlet之间通讯。

Application域

在ServletContext中,有一个 Map<String,Object> 集合,用来保存信息,这个Map集合就是ServletContext的域。

AServlet获取ServletContext对象,向域中添加信息,BServlet也可以获取Servlet,然后从ServletContext域中获取AServlet填入的信息。

这样,每个Servlet之间就可以共享信息了。

同样存在线程不安全的问题。

ServletContext获取项目内的资源

获取WebRoot/WebContent下的 user.xml 文件:

获取class资源:

最后更新于

这有帮助吗?