Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

谷哥的小弟学后台(08)——Servlet(1)

$
0
0

探索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–滑动冲突的产生及其处理


版权声明


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了。待程序启动,在浏览器中输入:

http://localhost:8081/TestServlet01/helloServlet

此时,控制台输出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的转发,在此仅仅作一个非常简单的引入,我们会在后续的学习中进一步介绍。

作者:lfdfhl 发表于2017/2/5 22:50:10 原文链接
阅读:97 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>