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() 返回请求主体的字节数。如果不知道字节长度,这个方法就会返回−1。 public 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编码。
2,getOutputStream()
但这个方法是用于发送二进制数据的,因此,大多数情况使用的是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)

浙公网安备 33010602011771号