Servlet,JSP(2)(servlet接口和内部对象ServletRequest,ServletResponse,ServletConfig,ServletContext)

1,Servlet API中定义的核心接口和类:

Servlet API有以下4个Java包:
javax.servlet,其中包含定义Servlet和Servlet容器之间契约的类和接口。(契约即规范)
javax.servlet.http,其中包含定义HTTP Servlet和Servlet容器之间契约的类和接口。
javax.servlet.annotation,其中包含标注Servlet、Filter、Listener的标注。它还为被标注元件定义元数据。(标注即注解)
javax.servlet.descriptor,其中包含提供程序化登录web应用程序的配置信息的类型

2,Servlet技术的核心是Servlet:

它是所有Servlet类必须直接或间接实现的一个接口。

Servlet接口定义了Servlet与Servlet容器之间的契约。
这个契约归结起来就是,Servlet容器将Servlet类载入内存,并在Servlet实例上调用具体的方法。
在一个应用程序中,每种Servlet类型只能有一个实例。

用户请求致使Servlet容器调用Servlet的Service方法,并传入一个ServletRequest实例和一个ServletResponse实例。
ServletRequest中封装了当前的HTTP请求,因此,Servlet开发人员不必解析和操作原始的HTTP数据。
ServletResponse表示当前用户的HTTP响应,使得将响应发回给用户变得十分容易。

对于每一个应用程序,Servlet容器还会创建一个ServletContext实例。这个对象中封装了上下文(应用程序)的环境详情。
每个上下文只有一个ServletContext。
每个Servlet实例也都有一个封装Servlet配置的ServletConfig

2.1,Servlet接口中定义了以下5个方法:

1,void init(ServletConfig config) throws ServletException
2,void service(ServletRequest request, ServletResponse response)throws ServletException, java.io.IOException
3,void destroy()
4,java.lang.String getServletInfo()
5,ServletConfig getServletConfig()

补充:编写Java方法签名的惯例是,对于与包含该方法的类型不处于同一个包中的类型,要使用全类名。(如上面的方法2)

init、Service和destroy是生命周期方法。

Servlet容器根据以下规则调用这3个方法:
init,当该Servlet第一次被请求时,Servlet容器会调用这个方法。
这个方法在后续请求中不会再被调用。
我们可以利用这个方法执行相应初始化工作。
调用这个方法时,Servlet容器会传入一个ServletConfig。
一般来说,你会将ServletConfig赋给一个类级变量,因此这个对象可以通过Servlet类的其他点来使用。

Service,每当请求Servlet时,Servlet容器就会调用这个方法。
编写代码时,是假设Servlet要在这里被请求。
第一次请求Servlet时,Servlet容器调用init方法和Service方法。
后续的请求将只调用Service方法。

destroy,当要销毁Servlet时,Servlet容器就会调用这个方法。
当要卸载应用程序,或者当要关闭Servlet容器时,就会发生这种情况。
一般会在这个方法中编写清除代码。

Servlet中的另外两个方法是非生命周期方法,即getServletInfo和getServletConfig

getServletInfo,这个方法会返回Servlet的描述。
你可以返回有用或为null的任意字符串。
getServletConfig,这个方法会返回由Servlet容器传给init方法的ServletConfig。 但是,为了让getServletConfig返回一个非null值,必须将传给init方法的ServletConfig赋给一个类级变量。

2.2,注意线程安全性。

Servlet实例会被一个应用程序中的所有用户共享,因此不建议使用类级变量,
除非它们是只读的,或者是java.util.concurrent.atomic包的成员。

3,编写基础的Servlet应用程序 

要运行Servlets,还需要一个Servlet容器(Tomcat是一个开源的,免费的)

3.1 编写和编译Servlet类

清单1.1 MyServlet类

package app01a;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
@WebServlet(name
= "MyServlet", urlPatterns = { "/my" }) public class MyServlet implements Servlet { private transient ServletConfig servletConfig;
@Override
public void init(ServletConfig servletConfig)throws ServletException { this.servletConfig = servletConfig; }
@Override
public ServletConfig getServletConfig() { return servletConfig; }
@Override
public String getServletInfo() { return "My Servlet"; }
@Override
public void service(ServletRequest request,ServletResponse response) throws ServletException,IOException { String servletName = servletConfig.getServletName(); response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.print("<html><head></head>" + "<body>Hello from " + servletName + "</body></html>"); }
@Override
public void destroy() { } }

上面使用到了注解:

@WebServlet(name = "MyServlet", urlPatterns = { "/my" })
WebServlet标注类型用来声明一个Servlet。
name属性是可选的,如有,通常用Servlet类的名称。
重要的是urlPatterns属性,它也是可选的,但是一般都是有的。
在MyServlet中,urlPatterns告诉容器,/my样式表示应该调用Servlet
注意,URL样式必须用一个正斜杠开头。

补充:编译servlet时开发工具记得导入jar包。

为了编译Servlet,必须将Servlet API中的所有类型都放在你的类路径下
Tomcat中带有servlet-api.jar文件,其中包含了javax.servlet的成员,以及javax.servlet.http包。 这个压缩文件放在Tomcat安装目录下的lib目录中。

运行时却不需要导入,因为是在tomcat中运行。

3.2,应用程序目录结构

主要分为两部分:应用程序目录(源码,网页,图片资源等)和WEB-INF目录。

WEB-INF目录下主要两个目录:classes和lib
1,classes:编译后的字节码
2,lib:存放需要的jar包

ps:因为开发工具的不同,可能生成的目录有所差异!

不同目录的访问差异:

1,放在应用程序目录下的任何资源,用户只要输入资源URL,都可以直接访问到
2,如果想让某一个资源可以被Servlet访问,但不可以被用户访问,那么就要把它放在WEB-INF目录下

部署应用的2种方式:直接部署应用和war包形式。

1,直接部署:
使用Tomcat时,一种部署方法是将应用程序目录复制到Tomcat安装目录下的webapps目录中。 也可以通过在Tomcat的conf目录中编辑server.xml文件实现部署, 或者单独部署一个XML文件,这样就不需要编辑server.xml了。 其他的Servlet容器可能会有不同的部署规则。
2,war部署:
部署Servlet/JSP应用程序时,建议将它部署成一个WAR文件。 WAR文件其实就是以.war作为扩展名的JAR文件。 利用带有JDK或者类似WinZip工具的JAR软件,都可以创建WAR文件。 然后,将WAR文件复制到Tomcat的webapps目录下。 当开始启动Tomcat时,Tomcat就会自动解压这个war文件。 部署成WAR文件在所有Servlet容器中都适用。

4,servlet中的几个重要对象:

4.1,ServletRequest

对于每一个HTTP请求,Servlet容器都会创建一个ServletRequest实例,并将它传给Servlet的Service方法ServletRequest封装了关于这个请求的信息

ServletRequest接口中有一些方法:

public int getContentLength()
返回请求主体的字节数。如果不知道字节长度,这个方法就会返回−1public java.lang.String getContentType()
返回请求主体的MIME类型,如果不知道类型,则返回null。

public java.lang.String getParameter(java.lang.String name)
返回指定请求参数的值public java.lang.String getProtocol()
返回这个HTTP请求的协议名称和版本。

getParameter是在ServletRequest中最常用的方法。该方法通常用于返回HTML表单域的值。

getParameter也可以用于获取查询字符串的值。
例如,利用下面的URI调用Servlet:http://domain/context/servletName?id=123
用下面这个语句,可以通过Servlet内部获取id值:String id = request.getParameter("id");
注意,如果该参数不存在,getParameter将返回null。

除了getParameter外,
还可以使用getParameterNames、getParameterMap和getParameterValues获取表单域名、值以及查询字符串

4.2,ServletResponse

javax.servlet.ServletResponse接口表示一个Servlet响应。
在调用Servlet的Service方法前,Servlet容器首先创建一个ServletResponse,并将它作为第二个参数传给Service方法。
ServletResponse隐藏了向浏览器发送响应的复杂过程。

发送数据的方法:

1,getWriter()
返回了一个可以向客户端发送文本的java.io.PrintWriter。 默认情况下,PrintWriter对象使用ISO
-8859-1编码。
2getOutputStream()
但这个方法是用于发送二进制数据的,因此,大多数情况使用的是getWriter,而不是getOutputStream。

在向客户端发送响应时,大多数时候是将它作为HTML发送。

在发送任何HTML标签前,应该先调用setContentType方法设置响应的内容类型,并将“text/html”作为一个参数传入。
这是在告诉浏览器,内容类型为HTML。
在没有内容类型的情况下,大多数浏览器会默认将响应渲染成HTML。
但是,如果没有设置响应内容类型,有些浏览器就会将HTML标签显示为普通文本

4.3,ServletConfig

当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init方法传入一个ServletConfig。
ServletConfig封装可以通过@WebServlet(注解)或者部署描述符(xml配置)传给Servlet的配置信息。 这样传入的每一条信息就叫一个初始参数。一个初始参数有key和value两个元件。

 为了从Servlet内部获取到初始参数的值,要在Servlet容器传给Servlet的init方法的ServletConfig中调用getInitParameter方法。

java.lang.String getInitParameter(java.lang.String name)
getInitParameterNames方法则是返回所有初始参数名称的一个Enumeration:
java.util.Enumeration<java.lang.String> getInitParameterNames()
例如,获取contactName参数值: String contactName
= servletConfig.getInitParameter("contactName");
ServletConfig还提供了另一个很有用的方法: getServletContext()利用这个方法可以从Servlet内部获取ServletContext

清单1.2 ServletConfigDemoServlet类

ServletConfigDemoServlet
如清单1.2所示,在@WebServlet的initParams属性中,给Servlet传入了两个初始参数(admin和email):
@WebServlet(name = "ServletConfigDemoServlet",
urlPatterns = { "/servletConfigDemo" },
initParams = {
@WebInitParam(name="admin", value="Harry Taciak"),
@WebInitParam(name="email", value="admin@example.com")
})

另一种方法是,在部署描述符中传入初始参数,即xml配置文件。

在这里使用部署描述符,比使用@WebServlet更容易,因为部署描述符是一个文本文件,不需要重新编译Servlet类,就可以对它进行编辑。

4.4,ServletContext

ServletContext表示Servlet应用程序(ps:内部属性整个应用共享)

每个Web应用程序只有一个上下文在将一个应用程序同时部署到多个容器的分布式环境中每台Java虚拟机上的Web应用都会有一个ServletContext对象

通过在ServletConfig中调用getServletContext方法,可以获得ServletContext。

有了ServletContext,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。
对象保存在ServletContext中的一个内部Map中。
保存在ServletContext中的对象被称作属性。

ServletContext中的下列方法负责处理属性:

java.lang.Object getAttribute(java.lang.String name)
java.util.Enumeration<java.lang.String> getAttributeNames()
void setAttribute(java.lang.String name, java.lang.Object object)
void removeAttribute(java.lang.String name)

 

posted @ 2018-10-30 01:06  假程序猿  阅读(197)  评论(0)    收藏  举报