1. 编写一个 Java 类,实现 Servlet 接口。
2. 把开发好的 Java 类部署到 web 服务器中。
3. 编程实例:用 Servlet 向浏览器输出 Hello Servlet。
- <span style="font-family:Microsoft YaHei;font-size:18px;">import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServlet;
- public class OutPrintToClient extends HttpServlet {
- public void service(ServletRequest req, ServletResponse res)
- throws ServletException, IOException {
- res.getOutputStream().write("Hello Servlet".getBytes());
- }
- }</span>
二、Servlet 在 Web 应用中的位置
三、Servlet 程序的运行过程
1、浏览器向 Web 容器发送 HTTP 请求
2、Web 容器从请求中解析出客户机想访问的主机名
3、Web 容器从请求中解析出客户机想访问的 Web 应用
4、Web 容器从请求中解析出客户机想访问的 Web 资源
5、如果Web 容器发现客户机想访问 Servlet,Web 容器就创建 Servlet 实例对象(只有第一次访问某个 Servlet 时,才会创建新的 Servlet)
6、Web 容器调用 Servlet 的 init() 方法,完成 Servlet 的初始化,Web 容器会创建请求和响应对象。(ServletResquest 和 ServletResponse)
7、服务器调用 Servlet 的 service() 方法响应客户端请求
8、执行 service() 方法。------> OutputStream out = res.getOutputStream(); out.write("Hello Servlet".getBytes());
不是直接写给客户机浏览器,而是先写入 response 对象中。
9、写入服务器的 response 域对象
10、服务器发现 response 对象中有数据,则会从 response 中取出向客户机写出的数据,构建一个 HTTP 响应,回写给客户机
11、服务器将 HTTP 响应回送给客户机
12、客户机浏览器解析服务器响应
四、Servlet 细节
1、由于客户机是通过 URL 地址访问 Web 服务器中的资源,所以 Servlet 程序若想被外界访问,必须把 Servlet 程序映射到一个 URI 地址上,这个工作在 web.xml 文件中使用 <servlet> 元素和 <servlet-mapping> 元素完成
2、<servlet> 元素用于注册 Servlet ,它包含两个主要的子元素,<servlet-name> 和 <servlet-class>,分别用于设置 Servlet 的注册名称和 Servlet 的完整类名
3、一个 <servlet-mapping> 元素用于映射一个已注册的 Servlet 的一个对外访问路径,它包含两个子元素 <servlet-name> 和 <url-pattern>,分别用于指定 Servlet 的注册名称和 Servlet 的对外访问路径。如:
<web-app>
<servlet>
<servlet-name>AnyName</servlet-name>
<servlet-class>类的完全路径</servlet-class>
</servlet><servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/DK/Servlet</url-pattern>
</servlet-mapping>
</web-app>
4、同一个 Servlet 可以被映射到多个 URL 地址上,即多个 <servlet-mapping> 元素的 <servlet-name> 的设置可以是同一个 Servlet 注册名,Servlet 映射可以使用 * 通配符,但是只有两种形式:/* 和 *.扩展名。如果有多个地址匹配,则根据就近原则匹配
5、Servlet 是一个供其他 Java 程序(Servlet 引擎)调用的 Java 类,它不能独立运行,它的运行完全由 Servlet 引擎来控制和调度。针对客户端的多次 Servlet 请求,通常情况下服务器只会创建一次,而对一个 Servlet 的每次访问请求都会导致 Servlet 引擎调用一个 Servlet 的 service() 方法,对于每次访问请求 Servlet 引擎都会创建一个新的 HttpServletRequest 请求对象和一个新的 HttpServletResponse 响应对象,然后将这两个对象作为参数传递给它调用的 Servlet 的 service() 方法,service() 方法再根据请求方式分别调用 doXXX() 方法
6、如果在 <servlet> 元素中配置了一个 <load-on-startup> 元素,那么 Web 应用程序在启动时就会装载并创建 Servlet 的实例对象,以及调用 Servlert 对象的 init() 方法
<load-on-startup>1</load-on-startup> 其中 1 代表有多个启动时的加载顺序
7、如果某个 Servlet 的映射路径仅仅为一个正斜杠 / ,那么这个 Servlet就成为当前 Web 应用程序的缺省 Servlet。凡是在 web.xml 中找不到匹配的 <servlet-mapping> 元素的 URL ,它们的访问请求将交给缺省 Servlet 处理,也就是说,缺省 Servlet 用于处理其他 Servlet 都不处理的访问请求。
服务器在该应用的 web.xml 中找,有没有匹配的 <url-pattern> 如果没有,交给服务器的 web.xml 中的缺省 URL ,如果没有则输出错误信息,当访问服务器某个静态文件时(html、图片等)实际上是在访问缺省 Servlet。
五、Servlet 线程安全问题
当多个客户端并发访问同一个 Servlet 时,Web 服务器会为每一个客户端的访问请求创建一个现成,并在这个线程上调用 Servlet 的 service() 方法,因此 service() 方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
在 Servlet 类中实现 SingleThreadModel 接口。SingleThreadModel 接口中没有定义任何方法,只要在 Servlet 类的定义中增加 SingleThreadModel 接口的生命即可(标记接口)
但是如果 Serlvet 实现了 SingleThreadModel 接口以后,就更改了 Servlet 内部机制,如果遇见并发访问时,则会调用 service() 来创建一个新的 Servlet,因此在新的版本中标记为过时的。
六、 ServletConfig 对象
在 Servlet 的配置文件中,可以使用一个或多个 <ini-pargam> 标签,为 Serlvet 配置一些初始化参数。
当 Servlet 配置了初始化参数后, Web 容器在创建 Servlet 对象时,会自动将这些初始化参数封装到 ServletConfig 对象中,并在调用 Servlet 的 init() 地方法时,将 ServletConfig 对象传递给 Servlet 。进而我们可以通过 ServletConfig 来获取 Servlet 的初始化参数信息。
- <span style="font-family:Microsoft YaHei;font-size:18px;">import java.io.IOException;
- import java.util.Enumeration;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class OutPrintToClient extends HttpServlet {
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- String charset = getServletConfig().getInitParameter("charset"); //获取单个参数
- System.out.println(charset);
- Enumeration<String> enumeration = getServletConfig().getInitParameterNames(); //获取全部参数
- while(enumeration.hasMoreElements()){
- String name = enumeration.nextElement();
- System.out.println(name);
- }
- }
- protected void doPost(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- doGet(req, resp);
- }
- }</span>
ServletConfig 对象的常见应用:1、获取字符集编码。2、获得数据库连接信息。3、获得配置文件
七、ServletContext 对象
1、Web 容器在启动时,它会为每个 Web 应用程序都创建一个对应的 ServletContext 对象,它代表当前 Web 应用。ServletConfig 对象中维护了 ServletContext 对象的引用。
2、由于一个 Web 应用中的所有 Servlet 共享同一个 ServletContext 对象,所以多个 Servlet 通过 ServletContext 对象实现数据共享。
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class ServletContextSendData extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- getServletContext().setAttribute("paramater", "DK");
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }</span>
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class ServletContextGetData extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String data = (String)getServletContext().getAttribute("paramater");
- System.out.println(data);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }</span>
3、Servlet 域对象:ServletContext、session、request、page
4、ServletContext 转发
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class ServletDispatcher extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- getServletContext().setAttribute("paragramter", "data");
- RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/index.jsp");
- dispatcher.forward(request, response);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }</span>
- <span style="font-family:Microsoft YaHei;font-size:18px;"><%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- </head>
- <body>
- <%
- String data = (String)pageContext.findAttribute("paragramter");
- %>
- <%=data%>
- </body>
- </html></span>
这样带数据过去不是线程安全的,应该用 request 域带
3、ServletContext 对象读取配置文件
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class GetProperties extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
- // Properties properties = new Properties();
- // properties.load(in);
- // Set set = properties.entrySet();
- // for (Object object : set) {
- // System.out.println(object);
- // }
- // realPath();
- getPropertiesByClassLoaderNew();
- }
- private void realPath() throws FileNotFoundException{
- String path = getServletContext().getRealPath("/WEB-INF/classes/db.properties");
- InputStream in = new FileInputStream(path);
- System.out.println(in);
- }
- //此方法只加载一次,因为类加载器只加载一次字节码到内存,而且文件不能很大
- private void getPropertiesByClassLoader() throws IOException{
- InputStream in = this.getClass().getClassLoader().getResourceAsStream("db.properties");
- Properties properties = new Properties();
- properties.load(in);
- System.out.println(properties.getProperty("driver"));
- }
- private void getPropertiesByClassLoaderNew() throws IOException{
- URL url = this.getClass().getClassLoader().getResource("db.properties");
- String realpath = url.getPath();
- Properties p = new Properties();
- p.load(new FileInputStream(realpath));
- System.out.println(p.getProperty("driver"));
- }
- }</span>
转载自:http://blog.csdn.net/driverking/article/details/6698017