(二)第一个Servlet

 

一、预备知识

一、Servlet简介

  Servlet是sun公司提供的一门用于开发动态web资源的技术。
  Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
  1、编写一个Java类,实现servlet接口。
  2、把开发好的Java类部署到web服务器中。
  按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet。

二、Servlet的运行过程(生命周期)

Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
  ①Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
  ②装载并创建该Servlet的一个实例对象。
  ③调用Servlet实例对象的init()方法。
  ④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
  ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

 

三、Servlet与普通Java类的区别  

  Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
  针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
  在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

  如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。
    举例:
    <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

  用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。

 

 

四、缺省Servlet

  如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。
  凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。 例如:

复制代码
 1  <servlet>
 2     <servlet-name>ServletDemo2</servlet-name>
 3     <servlet-class>gacl.servlet.study.ServletDemo2</servlet-class>
 4     <load-on-startup>1</load-on-startup>
 5   </servlet>
 6   
 7   <!-- 将ServletDemo2配置成缺省Servlet -->
 8   <servlet-mapping>
 9     <servlet-name>ServletDemo2</servlet-name>
10     <url-pattern>/</url-pattern>
11   </servlet-mapping>
复制代码

  当访问不存在的Servlet时,就使用配置的默认Servlet进行处理,如下图所示:

  

 

 



 

  1. 在myEclipse创建web project
  2. 在src包下编写一个java类。
public class MyServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	
	protected void doGet(HttpServletRequest request,HttpServletResponse response){	
		this.doPost(request, response);	
	}
	
	protected void doPost(HttpServletRequest request,HttpServletResponse response){
	System.out.println("第一个servlet");	
	}
}

 解析:   MyServlet这个类要继承HttpServlet,而HttpServlet必须引入外部的jar包,tomcat服务器里有这个包,我们可以引入或者自己下载导入。   继承HttpServlet之后,一般覆盖其中的doGet()和doPost()方法。


 

 

  3.打开webroot/web-inf里的web.xml,点击source,添加下列:

    <servlet>
  		<servlet-name>hello</servlet-name>
  		<servlet-class>myServlet.MyServlet</servlet-class>    //创建 myServlet包下的MyServlet类的对象 hello
  	</servlet>
  	
  	<servlet-mapping>
  		<servlet-name>hello</servlet-name>   
  		<url-pattern>/servlet</url-pattern>   //在地址栏里输入/servlet的时候调用对象hello
  	</servlet-mapping>

  4.配置好xml文件之后可以初步使用了。结果如图:

 

 



Servlet基础配置

 

  • 配置:1.windows->proference->java->Build path->user library 引入tomcat里的Servletjar包(把开发包和工具关联起来)
     2.右击项目名,properties->java Build path->libraries->add library->user library->用户类库名(将项目和开发包关联起来)
  • 特别注意版本问题,
JAVAEE 6 web3.0 要用tomcat7.0的服务器才能支持,否则不能支持,即在eclipse上JAVAEE 6 web3.0 的项目不能添加到tomcat6.0服务器里.
  • 把文件部署到服务器的三种方法:
1.把class文件直接赋值到tomcat下,再编写.xml文件,
2.在工具如myeclipse里写好后然后导出在tomcat下。
3.在开发工具里把项目与tomcat进行关联 。

 

 

  • init() 方法 
    在 Servlet 的生命期中,仅执行一次 init() 方法。它是在服务器装入 Servlet 时执行的。 可以配置服务器,以在启动服务器或客户机首次访问 Servlet 时装入 Servlet。 无论有多少客户机访问 Servlet,都不会重复执行 init() 。

 

  • service() 方法 
    service() 方法是 Servlet 的核心。每当一个客户请求一个HttpServlet 对象,该对象的service() 方法就要被调用,而且传递给这个方法一个"请求"(ServletRequest)对象和一个"响应"(ServletResponse)对象作为参数。 在 HttpServlet 中已存在 service() 方法。缺省的服务功能是调用与 HTTP 请求的方法相应的 do 功能。例如, 如果 HTTP 请求方法为 GET,则缺省情况下就调用 doGet() 。Servlet 应该为 Servlet 支持的 HTTP 方法覆盖 do 功能。因为 HttpServlet.service() 方法会检查请求方法是否调用了适当的处理方法,不必要覆盖 service() 方法。只需覆盖相应的 do 方法就可以了。
  • destroy() 方法 

    destroy() 方法仅执行一次,即在服务器停止且卸装Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy() 方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy() 方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。 

    当服务器卸装 Servlet 时,将在所有 service() 方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个Servlet 在运行service() 方法时可能会产生其它的线程,因此请确认在调用 destroy() 方法时,这些线程已终止或完成。
  •  当用户第一次访问servlet的时候,容器会根据xml文件中的<url-patting>创建相应的对象,调用的构造方法肯定是无参的构造方法,可是此时如果我们需要向这个对象提供参数呢?所以java在创建对象即调用无参构造方法之后会自动调用init()方法,参数放在web.xml里。当用户请求请求一个HttpServlet 对象的时候,调用service()方法,判断是get还是post,如果是post则调用doPost()方法。对象创建一段时间后,调用destroy()方法销毁对象。


  • 当我们在实际开发的时候,经常改变的常量(比如密码)不能直接写在代码里,否则一旦修改就得修改源代码,可以把这些常量写在配置文件里,然后在我们的源代码读取即可,修改的时候只要修改配置文件就行了。

然后在web.xml配置文件里设置参数:

      <servlet>
  		<servlet-name>hello</servlet-name>
  		<servlet-class>myServlet.MyServlet</servlet-class>
  		
  		<init-param>
  			<param-name>charset</param-name>
  			<param-value>UTF-8</param-value>
  		</init-param>
  		
  	</servlet>

 解析:  在<servlet></servlet>里配置的参数只能在一个servlet里使用,其他的servlet不能使用。

接着在servlet里获取参数:

public class MyServlet extends HttpServlet {

		private String charset="UTF-8";        //设置默认值
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	
	protected void doGet(HttpServletRequest request,HttpServletResponse response){	
		this.doPost(request, response);	
	}
	
	protected void doPost(HttpServletRequest request,HttpServletResponse response){
		response.setContentType("text/html;charset="+charset); 
		
		PrintWriter out=null;
		try {
			out = response.getWriter();
			out.print("你好世界!!");
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			out.close();
		}

	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		String	tmp=config.getInitParameter("charset");      //获取web.xml中的参数charset并赋给tmp
		charset=(tmp!=null)?tmp:charset;              //如果tmp值不是空的,就把tmp值赋给charset,如果是空的就把默认值charset赋给charset
	}
}

 结果:

当我们把web.xml文件里的<param-value>ASCII</param-value>改成这样的时候,结果为:

可以看到我们的配置生效了,以后如果要更改编码只要在xml配置文件修改即可无须修改源代码。

  • 注:  response.setContentType(MIME)的作用是使客户端浏览器,区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。

  • 上例的charset参数只能在一个servlet里使用,而如果一个项目有几十个srevlet每个servlet都要使用到同一个参数,按照上例则需要每个servlet都配置一个参数,这样就太麻烦了,

所以我们可以配置一个“全局参数”,这个参数定义的时候不能放在<servlet></servlet>便签里,要单独定义标签,具体如下:

  设置配置文件:

	<context-param>
  		<param-name>charset</param-name>
  		<param-value>UTF-8</param-value>
  	</context-param>
  
  	<servlet>
  		<servlet-name>hello</servlet-name>
  		<servlet-class>myServlet.MyServlet</servlet-class>	
  	</servlet>

  读取参数:

public class MyServlet extends HttpServlet {

		private String charset="UTF-8";  //设置默认值
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	
	protected void doGet(HttpServletRequest request,HttpServletResponse response){	
		this.doPost(request, response);	
	}
	
	protected void doPost(HttpServletRequest request,HttpServletResponse response){
		response.setContentType("text/html;charset="+charset); 
		
		PrintWriter out=null;
		try {
			out = response.getWriter();
			out.print("你好世界!!");
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			out.close();
		}

	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		//String	tmp=config.getInitParameter("charset");  //获取web.xml中的参数charset并赋给tmp
		String tmp=config.getServletContext().getInitParameter("charset");
		charset=(tmp!=null)?tmp:charset;  //如果tmp值不是空的,就把tmp值赋给charset,如果是空的就把默认值charset赋给charset
	}
}

 结果:

 

posted @ 2017-02-28 19:12  shyroke、  阅读(286)  评论(0编辑  收藏  举报
作者:shyroke 博客地址:http://www.cnblogs.com/shyroke/ 转载注明来源~