探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制
Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南
自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理
版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl
Servlet简介
Servlet由Sun公司研发,它是一种运行在Web服务器中的小型Java程序。
Servlet通常通过HTTP接收和响应来自Web客户端的请求。简单地说:Servlet是服务器端的小应用程序。其实,关于Servlet的作用,我们只看它的名字也能知晓一些端倪—let后缀表示”小”的含义;比如:booklet表示小册子,townlet表示小镇,lakelet表示小湖……server表示服务器;所以把-let后缀与server融合在一起就是Servlet表示服务端的小程序。嗯哼,这么说是不是就更形象和便于理解呢?
Servlet之Hello World
开发一个Servlet非常的简单,只需三个步骤:
- 编写一个Java类实现servlet接口
- 修改web.xml配置文件
- 将开发好的Java类部署至web服务器
嗯哼,我们就按照这个步骤来写个简单的示例。
package cn.com;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
public class TestServlet implements Servlet {
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("Hello Servlet");
}
@Override
public void destroy() {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
}
}
在此,定义一个类实现了Servlet接口并重写其service( )方法。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>cn.com.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
在WEB-INF目录下建立配置文件web.xml,内容如上所示。
由于客户端是通过URL地址访问服务器中的资源,若Servlet程序想被外界访问则必须把servlet程序映射到一个URL地址上,这个工作在正是在web.xml文件中配置完成的,详解如下所示:
<servlet>用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,它们分别用于配置Servlet的注册名称和Servlet的完整类名;请参见代码第9-12行
<servlet-mapping>用于映射已注册Servlet的对外访问路径,它包含两个子元素:<servlet-name>和<url-pattern>,它们分别用于指定Servlet的注册名称和Servlet的对外访问路径;请参见代码第15-18行
在完成这些工作,我们就可以将应用部署到Tomcat了。待程序启动,在浏览器中输入:
此时,控制台输出Hello Servlet。嗯哼,部署Servlet到服务端并可被外界访问的小示例就完成了。
Servlet的生命周期
Servlet不能独立运行,它的运行完全由Servlet引擎来控制和调度。
通常情况下,针对客户端的多次Servlet请求,服务器只会创建一个Servlet实例对象且将其驻留在内存中为后续的其它请求服务,直至web容器退出Servlet实例对象才会被销毁。
所以,可将Servlet的生命周期概括为这么几个阶段:实例化,初始化,服务,销毁这几个阶段。
请看如下代码:
package cn.com;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
public class TestServlet implements Servlet {
public TestServlet( ) {
System.out.println("TestServlet( )");
}
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("init( )");
}
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("service( )");
}
@Override
public void destroy() {
System.out.println("destroy( )");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
}
现在,结合这个示例一起分析Servlet的生命周期:
所以,可将Servlet的生命周期概括为这么几个阶段:实例化,初始化,服务,销毁这几个阶段。
代码解析如下:
- Servlet的实例化,请参照代码第15-17行
在该过程中调用Servlet的构造方法 - Servlet的初始化,请参照代码第19-22行
在该过程中会调用Servlet的init( )方法 - Servlet的服务,请参照代码第25-28行
在该过程中会调用Servlet的service( )方法 - Servlet的销毁,请参照代码第30-33行
在该过程中会调用Servlet的destroy( )方法
在Servlet的整个生命周期内,Servlet的构造方法和init()方法只会被调用一次;同理Servlet的destroy()也只执行一次。但对于客户端的每次访问都会导致Servlet引擎调用一次servlet的service()方法。
Servlet的实现方式
常见的Servlet实现方式有三种:实现Servlet接口、继承GenericServlet、继承HttpServlet。现在分别介绍如下所示:
Servlet的第一种实现方式:实现Servlet接口
在该方式下,需要根据业务实现Servlet接口提供的方法,尤其是service( )方法。详情请参照刚才的示例,不再赘述。
Servlet的第二种实现方式:继承GenericServlet
GenericServlet实现了Servlet接口和ServletConfig接口。GenericServlet提供了生命周期方法init()和destroy()以及ServletConfig接口中的方法的简单版本,所以它使编写 Servlet变得更容易。故,若继承GenericServlet一般情况下我们只需重写service()方法即可。
Servlet的第三种实现方式:继承HttpServlet
HttpServlet继承自GenericServlet且实现了Servlet接口和ServletConfig接口。HttpServlet在实现Servlet接口时,覆写了service()方法,该方法会自动判断用户的请求方式,若为GET请求则调用HttpServlet的doGet()方法,若为Post请求则调用doPost()方法,诸如此类。因此,开发人员在编写Servlet时,通常只需要覆写doGet()或doPost()方法而不用覆写service方法()。故,在实际开发中编写Servlet时,通常情况下,应继承HttpServlet而避免直接去实现Servlet接口。
请看如下示例:
package cn.com;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
public class TestHttpServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("---> doGet()");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("---> doPost()");
}
}
在该示例中TestHttpServlet继承自HttpServlet,且覆写了doGet()和doPost()方法。当有Get或者Post的请求到达时就会调用doGet()或者doPost()。
当然,这三种方式都需要都需要我们在web.xml里面配置Servlet。在之前我们已经介绍了Servlet简单的配置,在此再补充一些细节。
- 同一个Servlet可以被映射到多个路径上,即多个<servlet-mapping>元素的<servlet-name>的设置值可以是同一个Servlet的注册名。
- 可用*.扩展名的形式配置url-pattern,其中*表示任意字符串;比如配置<url-pattern>*.do</url-pattern>时可用任意字符串.do组成的url访问该Servlet
- 可用/*配置url-pattern,其中*表示任意字符串;比如配置<url-pattern>/*</url-pattern>时可用/任意字符串组成的url访问该Servlet。
ServletConfig
在Servlet的配置文件web.xml中可使用<init-param>为Servlet配置初始化参数。当servlet配置了初始化参数后Web容器在创建Servlet实例对象时会自动将这些初始化参数封装到ServletConfig对象中并在调用servlet的init()方法时将ServletConfig对象传递给servlet。所以,可通过ServletConfig对象得到当前Servlet的初始化参数信息。
请看如下web.xml配置信息:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>cn.com.TestServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
在此web.xml配置了编码方式(encoding)为UTF-8
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
public class TestServlet implements Servlet {
private ServletConfig mServletConfig;
public TestServlet( ) {
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
mServletConfig=servletConfig;
String encoding=mServletConfig.getInitParameter("encoding");
System.out.println("---> encoding="+encoding);
}
}
在该Servlet中可从init()方法的输入参数中获取到ServletConfig再利用其getInitParameter()方法获取配置信息即可。
GenericServlet实现了Servlet接口和ServletConfig接口,所以在GenericServlet中利用:
this.getServletConfig().getInitParameter(“encoding”);
或者
this.getInitParameter(“encoding”);
这两种方式获取配置信息。
ServletContext
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。在此介绍ServletContext几种常用的应用。
利用ServletContext实现多个Servlet共享数据
public void setAttribute(String name, Object object)
利用setAttribute()方法保存数据
public Object getAttribute(String name)
利用getAttribute()方法获取数据
public void removeAttribute(String name)
利用removeAttribute()方法移除数据
利用ServletContext获取全局配置信息
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
在web.xml中配置如上全局信息
ServletContext servletContext=mServletConfig.getServletContext();
String encoding=servletContext.getInitParameter("encoding");
在Servlet可通过ServletContext获取全局配置信息
利用ServletContext获取获取资源路径
public String getRealPath(String path)
可使用ServletContext的getRealPath(path)方法获取到当前应用任何位置的任何资源,其中参数path路径一般以/WEB-INF开头,斜杠/就表示了当前应用。为什么斜杠/后就是WEB-INF呢?其实之前我们也提到了:应用部署后所有的东西都在WEB-INF路径下。我们也可以打开……tomcat\webapps\应用名\WEB-INF\即可看到与应用有关的所有资源。
现在我们在src的根目录下建立test.properties文件,在该文件中只写入一行简单的测试数据:
username=xiaozemaliya
现在,我们在Servlet中获取该username,如下所示:
mServletConfig=servletConfig;
ServletContext servletContext=mServletConfig.getServletContext();
String path=servletContext.getRealPath("/WEB-INF/classes/test.properties");
Properties properties=new Properties();
properties.load(new FileInputStream(path));
String name=(String) properties.getProperty("username");
在此,再次提醒:src中的代码编译后的class文件存放于……tomcat\webapps\应用名\WEB-INF\classes文件夹中。
利用ServletContext实现Servlet的转发
mServletConfig=servletConfig;
ServletContext servletContext=mServletConfig.getServletContext();
RequestDispatcher requestDispatcher=servletContext.getRequestDispatcher(path);
requestDispatcher.forward(request, response);
关于Servlet的转发,在此仅仅作一个非常简单的引入,我们会在后续的学习中进一步介绍。