Bluetooth LE for iOS demo. LightBlue like demo.

一、Servlet概述

      1) java web目录结构

Bluetooth LE for iOS demo. LightBlue like demo.        

        2)Tomcat 目录结构

Bluetooth LE for iOS demo. LightBlue like demo.

          3)Servlet 接口

                Servlet 是一种实现了 javax.servlet.Servlet 接口的类。

                Servlet 接口规定了特定的方法来处理特定的请求,开发者只需要实现 Servlet的相关方法,用户访问

                              Web 程序的时候,Tomcat会调用这些方法完成业务处理

二、编写及部署Servlet


       【具体开发方式见:4、开发 Servlet 的方式 ,

         下面的具体代码可在阅读完后面的内容后再回头来看】

       1)简介

             直接实现 Servlet 接口来编写 Servlet 很不方便,需要实现的方法太多。

             在 JDK中 javax.servlet.*,javax.servlet.http.*包下提供了对 Servlet 的支持。

             如 javax.servlet.http.HttpServlet 类已经实现了 Servlet 接口的所有方法。

             编写 Servlet时直接继承 HttpServlet,并覆盖需要的方法即可,一般只覆盖 doGet()与 doPost()方法

        2)实现Servlet

              在 MyEclipse中新建 Web Project,取名servlet,新建 Servlet,取名 FirstServlet。

              FirstServlet.java 文件:

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstServlet extends HttpServlet {
	
	private static final long serialVersionUID = 2386052823761867369L;
	
	/**
	 * 以 GET 方式访问页面时执行该函数。
	 * 执行 doGet 前会先执行 getLastModified, 如果浏览器发现 getLastModified 返回的数值
	 * 与上次访问时返回的数值相同,则认为该文档没有更新,浏览器采用缓存而不执行 doGet。
	 * 如果 getLastModified 返回 -1,则认为是时刻更新的,总是执行该函数。
	 */ 
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 调用 HttpServlet 自带的日志函数输出信息到控制台
		this.log("执行 doGet 方法... ");

		// 处理 doGet
		this.execute(request, response);
	}

	/**
	 * 以 POST 方式访问页面时执行该函数。
	 */ 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		this.log("执行 doPost 方法... ");
		
		// 处理 doPost
		this.execute(request, response);
	}
	
	/**
	 * 返回该 Servlet 生成的文档的更新时间。对 Get 方式访问有效。
	 * 返回的时间为相对于 1970年1月1日08:00:00 的毫秒数。
	 * 如果为 -1 则认为是实时更新。默认为 -1。
	 */
	@Override
	public long getLastModified(HttpServletRequest request) {
		
		this.log("执行 getLastModified 方法... ");
		
		return 0;
	}

	private void execute(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException{

		response.setCharacterEncoding("UTF-8");//设置 request,response 编码方式
		request.setCharacterEncoding("UTF-8");
		
		// 访问该 Servlet 的 URI
		String requestURI = request.getRequestURI();
		// 访问该 Servlet 的方式,是 GET 还是 POST
		String method = request.getMethod();
		// 客户端提交的参数 param 值
		String param = request.getParameter("param");
		
		response.setContentType("text/html"); //设计文档类型
		PrintWriter out = response.getWriter(); //获取 out 对象
                //输出到客户端浏览器
                out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
		out.println("<HTML>");
		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
		out.println("  <BODY>");
		out.println("	以 " + method + " 方式访问该页面。取到的 param 参数为:" + param + "<br/>");
		
		out.println("	<form action=‘" + requestURI + "‘ method=‘get‘><input type=‘text‘ name=‘param‘ value=‘‘><input type=‘submit‘ value=‘以 GET 方式访问 RequestServlet‘></form>");
		out.println("	<form action=‘" + requestURI + "‘ method=‘post‘><input type=‘text‘ name=‘param‘ value=‘‘><input type=‘submit‘ value=‘以 POST 方式访问 RequestServlet‘></form>");
		
		// 由客户端浏览器读取该文档的更新时间
		out.println("	<script>document.write(‘本页面最后更新时间:‘ + document.lastModified + ‘<br />‘); </script>");
		out.println("	<script>document.write(‘本页面URL:‘ + location + ‘<br/>‘ ); </script>");
		
		out.println("  </BODY>");
		out.println("</HTML>");
		out.flush();
		out.close();
		
	}

}


         3)配置 <servlet>、<servlet-mapping>

               一个完整的 Servlet 包括 Servlet 类、<servlet> 配置、<servlet-mapping> 配置,缺一不可,

                   利用 MyEclipse 向到新建 Servlet,MyEclipse 会自动完成 <servlet>、<servlet-mapping> 等配置

               web.xml 配置文件:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    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_3_0.xsd">
  <servlet>
   
    <!--下面两行可以省略 -->
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>

    <servlet-name>FirstServlet</servlet-name> <!-- Servlet的注册名,必须配置的属性,可自己定义,默认使用该Servletde的名字 [3]-->
    <servlet-class>servlet.FirstServlet</servlet-class> <!-- Servlet类的全路径(包名+类名),必须配置的属性 [4]-->
  </servlet>

  <servlet-mapping> <!-- 对一个已经注册的 Servlet的映射 -->
    <servlet-name>FirstServlet</servlet-name> <!-- Servlet的注册名 [2]-->
    <url-pattern>/servlet/FirstServlet</url-pattern> <!--指明访问该 Servlet的访问路径 [1]-->
  </servlet-mapping>

</web-app>

<!-- 服务器调用流程:http://localhost:8080/ABC --[1]--[2]--[3]--[4]  -->


        4)部署 Web 程序

              a)手工部署:  在 Tomcat 目录 的 webapps下面新建文件夹,命名为 firstWeb,然后找到刚才 MyEclipse 的工作目录,将该目录下的

servlet工程下的 WebRoot 下的所有内容复制到 刚才在 Tomcat目录下建好的 webapps\firstWeb 下,启动 Tomcat,浏览器输入:

http://localhost:8080/firstWeb/servlet/FirstServlet,即可访问上面新建的 Servlet了

Bluetooth LE for iOS demo. LightBlue like demo.



Bluetooth LE for iOS demo. LightBlue like demo.

        b)MyEclipse 自动部署

           Bluetooth LE for iOS demo. LightBlue like demo.

              MyEclipse菜单中选择 Window |Preferences ,找到 Tomcat6.x,进行配置如下:

Bluetooth LE for iOS demo. LightBlue like demo.

            配置完毕后,下面进行部署 servlet:

Bluetooth LE for iOS demo. LightBlue like demo.

     部署后效果如下:

     (在需要时,可以点击 Redeploy  来 reload 应用,

     也可以登录Tomcat 管理 应用 http://localhost:8080/,在相应的应用后点击 reload)

Bluetooth LE for iOS demo. LightBlue like demo.

     下面 在 MyEclipse 下 启动 Tomcat

Bluetooth LE for iOS demo. LightBlue like demo.


   此时,部署完成,在浏览器输入地址即可访问 建立的 Servlet了(也可以在 MyEclipse内集成的浏览器打开)

Bluetooth LE for iOS demo. LightBlue like demo.

          5)测试

               分别以 GET 和 POST 方式访问,查看不同之处

              (下面是手动部署的地址,MyEclipse部署的地址应该是:http://localhost:8080/servlet/servlet/FirstServlet):

Bluetooth LE for iOS demo. LightBlue like demo.

Bluetooth LE for iOS demo. LightBlue like demo.

Bluetooth LE for iOS demo. LightBlue like demo.

  

        6)get 提交 和 post 的提交的区别

             (1)post提交数据是隐式的,get是通过在url里面传递的(可以看一下你浏览器的地址栏),用来传递一些不需要保密的数据。post比get安全

             (2)从速度看 get > post

             (3)用get时,传输数据的大小有限制 (注意不是参数的个数有限制),一般不要大于2K;而post理论上无限制,实际开发中,建议不要大于64K。

             (4)还有用GET的时候在SERVLET中要用DOGET方法,用POST就要用DOPOST方法。这是JSP在处理GET和POST的时候在JAVA 角度看的不同。

             (5)还有一点需要注意哦,通过get方式来获取参数用的方法和通过post方式有些区别:

                     post:request.getParameter("");

                     get: request.QueryString("");


        7)容易出错的地方

            注意默认情况下,建立 Servlet 文件时,Servlet 的 URL 前会自动添加一个 /servlet 目录(跟工程名无关),(所以 web.xml 下的路径也是:

            /sevlet/FirstServlet,这样的话,在运行时,浏览器输入的路径应该是:localhost:8080/工程名/url ,即http://localhost:8080/servlet/servlet/FirstServlet

            而不是:http://localhost:8080/servlet/FirstServlet(注意,凑巧这里的工程名也是servlet),否则会报404错误 :

                                                                                           The requested resource (Servlet action is not available) is not available.

            若想使用后者,可以在建立servlet文件时将 URL前面的默认的 /servlet 删除即可。


Bluetooth LE for iOS demo. LightBlue like demo.


           7)实例:response 生成图片验证码

           服务器对客户端浏览器做出的响应被封装成一个 HttpServletResponse 对象。

           要对浏览器进行操作,只需要操作 HttpServletResponse 对象就可以了。通过HttpServletResponse.getWriter()

获得一个 PrintWrite() 对象,该对象为 OutputStream 的子类。然后使用该对象输出信息就可以了。

          通过 HttpServletResponse 获取的 PrintWrite 对象只能写字符型的数据,如果需要在客户端写二进制数据,

可以使用HttpServletResponse.getOutputStream()。方法 getWrite() 可以看做是方法getOutputStream() 的一个封装。

           IdentityServlet,java文件:

package servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class IdentityServlet extends HttpServlet {

	private static final long serialVersionUID = -479885884254942306L;
        //随机字符字典,不包含 O、0、1、I 等难辨认的字符
	public static final char[] CHARS = { ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘,
			‘9‘, ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘,
			‘N‘, ‘P‘, ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘, ‘X‘, ‘Y‘, ‘Z‘ };

	public static Random random = new Random();  //随机数

	public static String getRandomString() {   //获取6位随机数
		StringBuffer buffer = new StringBuffer(); //字符串缓存
		for (int i = 0; i < 6; i++) {                   //循环6次
			buffer.append(CHARS[random.nextInt(CHARS.length)]); //每次取一个随机字符
		}
		return buffer.toString();
	}

	public static Color getRandomColor() {      //获取随机的颜色
		return new Color(random.nextInt(255), random.nextInt(255), random
				.nextInt(255));
	}

	public static Color getReverseColor(Color c) { //返回某颜色的反色
		return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c
				.getBlue());
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException { //GET方法

		response.setContentType("image/jpeg"); //设置输出类型

		String randomString = getRandomString(); //随机字符串
		request.getSession(true).setAttribute("randomString", randomString); //放到 session 中

		int width = 100;  //图片宽度
		int height = 30;  //图片高度

		Color color = getRandomColor(); //随机颜色,用于背景色
		Color reverse = getReverseColor(color); //反色,用于前景色

		BufferedImage bi = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB); //创建一个彩色图片
		Graphics2D g = bi.createGraphics(); //获取绘图对象
		g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));//设置字体
		g.setColor(color);           //设置颜色
		g.fillRect(0, 0, width, height); //绘制背景
		g.setColor(reverse);//设置颜色
		g.drawString(randomString, 18, 20); //绘制随机字符
		for (int i = 0, n = random.nextInt(100); i < n; i++) { //画最多100个噪音点
			g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1); //随机噪音点
		}

		
		ServletOutputStream out = response.getOutputStream(); // 转成JPEG格式	
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); //编码器
		encoder.encode(bi);   //对图片进行编码
		out.flush();  //输出到客户端
	}

	public static void main(String[] args) {
		System.out.println(getRandomString());
	}
}

    上面程序中,

在Eclipse中处理图片,需要引入两个包:
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

若有报错

Access restriction:The type JPEGCodec is not accessible due to restriction on required library 

Access restriction: The type JPEGImageEncoder is not accessible due to restriction on required library

解决方法:Project -> Properties,先remove掉JRE System Library,然后再Add Library重新加入。

Bluetooth LE for iOS demo. LightBlue like demo.

           运行结果:

Bluetooth LE for iOS demo. LightBlue like demo.

      为了方便演示,在 WebRoot 下建立一个 identity.html 文件引用这个图片验证码:

<!DOCTYPE html>
<html>
  <head>
    <title>identity.html</title>
	
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html; charset=GB2312">
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

  </head>
  
  <body>
    <script>
	function reloadImage() {
		document.getElementById(‘btn‘).disabled = true;
		document.getElementById(‘identity‘).src=‘servlet/IdentityServlet?ts=‘ + new Date().getTime();
	}
	</script>

		<img src="servlet/IdentityServlet" id="identity" onload="btn.disabled = false; " />
		<input type=button value=" 换个图片 " onclick="reloadImage()" id="btn">
  </body>
</html>

    运行如下:


Bluetooth LE for iOS demo. LightBlue like demo.


三、Servlet生命周期

      

              1.      当serlvet 第一次被调用的时候,会触发init函数,该函数会servlet实例装载到内存.init函数只会被调用一次

              2.      然后去调用servlet  的 service函数

              3.      当第二次后访问该servlet 就直接调用 service 函数.

              4.      当 web应用 reload 或者关闭 tomcat 或者关机 都会去调用destroy函数,该函数就会去销毁serlvet

           Servlet的生命周期

                         当客户端第一次向web服务器发出一个servlet请求时,web服务器将会创建一个该servlet的实例,

并且调用servlet的init()方法;如果当服务器已经存在了一个servlet实例,那么,将直接使用此实例;然后再调用service()方法,

service()方法将根据客户端的请求方式来决定调用对应的doXXX()方法;当 web应用reload 或者关闭tomcat 或者关机

web服务器将调用destroy()方法,将该servlet从服务器内存中删除。

           生命全过程:

              1.加载

              2.实例化

              3.初始化

              4.处理请求

              5.退出服务

简述servlet的生命周期(工作流程)?

标准版本:

①WEB服务器首先会检查是否已经装载并创建了该servlet实例对象。如果是直接进行第④步,否则执行第②步。

②装载并创建该Servlet的一个实例对象。

③调用Servlet实例对象的init()方法。

④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用service()方法并将请求和响应作为参数传递进去。

⑤WEB应用被停止或重启之前,Servlet引擎将卸载Servlet,在卸载之前调用Servlet的destroy()方法


四、开发 Servlet 的方式

      开发 Servlet 有三种方法:(1)实现 Servlet 接口

                                                 (2)通过继承 GenericServlet

                                                 (3)通过继承 HttpServlet

        1)实现 Servlet 接口的方式

             新建  Web Object,命名为 ooo ,新建 Servlet,命名为,MyServlet,url 路径为  /MyServlet

             MyServlet.java 代码

package ooo;

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;  

public class MyServlet implements Servlet
{
    //该函数用于初始化servlet,就是把该servlet装载到内存中
    //该函数只会被调用一次
    public void init(ServletConfig config)
          throws ServletException{
        System.out.println("init it"); 
        
    }

    //得到ServletConfig对象
    public ServletConfig getServletConfig(){
        return null;
    }
    
    //该函数是服务函数,我们的业务逻辑代码就是写在这里
    //该函数每次都会被调用
    public void service(ServletRequest req,
                    ServletResponse res)
             throws ServletException,
                    java.io.IOException{
        System.out.println("service it"); 
        PrintWriter printWriter=res.getWriter();  
        printWriter.println("<h1>"+"hello,world"+"</h1>");      
    }
    //该函数时得到servlet配置信息
    public java.lang.String getServletInfo(){
        return null;
    }
    //销毁该servlet,从内存中清除,该函数被调用一次
    public void destroy(){
        System.out.println("destroy it"); 
    }
} 

部署完成后,在浏览器中输入:http://localhost:8080/ooo/MyServlet

Bluetooth LE for iOS demo. LightBlue like demo.


 刷新一下,最后用 Tomcat Manager 停止 ooo 应用,对应的 Tomcat 服务器的显示如下:


Bluetooth LE for iOS demo. LightBlue like demo.


  

        2)使用 GenericServlet 开发 servlet(了解即可)

              通过 GenericServlet 去开发 servlet,只需要重写 service 方法,相对来讲简单一些。

              在 ooo 工程中,建立 Servlet 命名为:MyGenericServlet

              MyGenericServlet.java 代码

package ooo;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class MyGenericServlet extends GenericServlet
{
	public  void service(ServletRequest req,
                             ServletResponse res)
                      throws ServletException,
                             java.io.IOException{
		res.getWriter().println("hello,world,i am geneirc servlet");
	}
}


          部署,浏览器运行:


Bluetooth LE for iOS demo. LightBlue like demo.

         3)使用继承 HttpServlet 的方法开发 Servlet

               这个是目前最常用的方式。

               在 ooo 工程中,建立 Servlet 命名为:MyHttpServlet

              MyHttpServlet.java 代码如下:

package ooo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyHttpServlet extends HttpServlet
{
	//在HttpServlet 中,设计者对post 提交和 get提交分别处理
	//回忆 <form action="提交给?" method="post|get"/>,默认是get
	//其实 doGet()/ doPost() 最终也去调用 service 方法

	protected void doGet(HttpServletRequest req,
                     HttpServletResponse resp)
              throws ServletException,
                     java.io.IOException{
		resp.getWriter().println("i am httpServet doGet()");
		
	}
	protected void doPost(HttpServletRequest req,
                      HttpServletResponse resp)
               throws ServletException,
                      java.io.IOException{ 
		resp.getWriter().println("i am httpServet doPost() post name="+req.getParameter("username"));
	}
}

          运行结果:


Bluetooth LE for iOS demo. LightBlue like demo.


五、Servlet的细节问题

      (1)一个已经注册的Servlet可以被多次映射即:

 <servlet>
   
    <!--下面两行可以省略 -->
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>

    <servlet-name>MyServlet</servlet-name> <!-- Servlet的注册名,必须配置的属性,可自己定义,默认使用该Servletde的名字 -->
    <servlet-class>ooo.MyServlet</servlet-class> <!-- Servlet类的全路径(包名+类名),必须配置的属性 -->
  </servlet>

<servlet-mapping> <!--映射1-->
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/MyServlet1</url-pattern>
  </servlet-mapping>
  <servlet-mapping> <!--映射2-->
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/MyServlet2</url-pattern>
  </servlet-mapping> 


测试:使用http://localhost:8080/ooo/MyServlet1 与 http://localhost:8080/ooo/MyServlet2  效果一样


Bluetooth LE for iOS demo. LightBlue like demo.


     (2)当映射一个 servlet 时候,可以多层,可以随意后缀(因此:后缀名是可能是假象),如:再添加一个映射


   <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/My/abc.html</url-pattern> </servlet-mapping>

        

   使用  http://localhost:8080/ooo/My/abc.html 测试,效果一样


Bluetooth LE for iOS demo. LightBlue like demo.


    

      (3)使用通配符在 servlet 映射到 URL 中

 

              有两种格式:

                第一种格式:   *.扩展名  比如 *.do  *.ss

                第二种格式:    以 / 开头 同时以 /* 结尾    比如     /*      /news/*

                通配符练习题:

                        Servlet1映射到 /abc/*

                        Servlet2映射到 /*

                        Servlet3映射到 /abc

                        Servlet4映射到 *.do

            问题(面试题):

            当请求URL为“/abc/a.html”:  “/abc/*”和“/*”都匹配,哪个servlet响应Servlet引擎将调用Servlet1。

            当请求URL为“/abc”时:“/abc/*”和“/abc”都匹配,哪个servlet响应Servlet引擎将调用Servlet3。

            当请求URL为“/abc/a.do”时:“/abc/*”和“*.do”都匹配,哪个servlet响应 Servlet引擎将调用Servlet1

            当请求URL为“/a.do”时:“/*”和“*.do”都匹配,哪个servlet响应Servlet引擎将调用Servlet2。

            当请求URL为“/xxx/yyy/a.do”时:“/*”和“*.do”都匹配,哪个servlet响应?Servlet引擎将调用Servlet2。

         

             在匹配的时候,要参考的标准:

             1、看谁的匹配度高,谁就被选择

             2 、 *.do 的优先级最低

     (4)Servlet 单例问题

              当 Servlet 被第一次访问后,就被加载到内存,以后该实例对各个请求服务。即在使用中是单例。

              因为 Servlet 是单例,因此会出现线程安全问题,比如,售票系统,如果不加同步机制,则会出现问题。

              解决原则:1)如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制

                                      synchronized(对象) { //同步代码  }

                                2) 如果一个变量不需要共享,则直接在 doGet() 或者 doPost()定义.这样不会存在线程安全问题


       (5)servlet 中的 <load-on-stratup> 配置

                需求: 当我们的网站启动的时候,可能会要求初始化一些数据,(比如创建临时表), 在比如:

                我们的网站有一些要求定时完成的任务[ 定时写日志,定时备份数据.. 定时发送邮件..]

                 解决方法: 可以通过<load-on-startup> 配合 线程知识搞定.

              

               

                 先说明<load-on-startup>: 通过配置<load-on-startup> 我们可以指定某个Servlet 自动创建.

 

                 下面模拟一个定时发送电子邮件的功能:

                  实现思路:

                  sendEmailTable(表)

                  id                  content                 sendtime

                  1                   “hello”                  2011-11-1120:11

                  2                   “hello2”                2012-11-1110:00


                 看看如何线程去完成任务:新建 SendMailTread.java 类


package ooo;

public class SendEmailThread extends Thread{
	@Override
	public void run() {
		int i=0;
		try {
			while(true){
				//每休眠一分钟(这里为了方便演示,写的是10秒),就去扫表sendmail, 看看那份信件应当被发出
				Thread.sleep(10*1000);
				System.out.println("发出 第"+(++i)+"邮件");//javamail
			}
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}
	}
}

                新建 Servlet 命名:MyInitServlet


package ooo; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; public class MyInitServlet extends HttpServlet { public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here System.out.println("MyInitServlet1 的init被调用.."); //完成一些初始化任务 System.out.println("创建数据库,表,读取参数"); //创建一个线程 SendEmailThread sendEmailThread=new SendEmailThread(); sendEmailThread.start(); } }


                配置 web.xml

               1)删除下面的映射


  <servlet-mapping>
    <servlet-name>MyInitServlet</servlet-name>
    <url-pattern>/MyInitServlet</url-pattern>
  </servlet-mapping>


              2)在 servlet 中添加<load-on-startup>:


<servlet> <servlet-name>MyInitServlet</servlet-name> <servlet-class>ooo.MyInitServlet</servlet-class> <!-- 1表示该servlet被 init的顺序 --> <load-on-startup>1</load-on-startup> </servlet>


             配置之后,就无法直接从浏览器访问,通过后台运行:每隔10秒模拟发送一次邮件:


Bluetooth LE for iOS demo. LightBlue like demo.


六、ServletConfig 对象

      该对象只要用于 读取 servlet 的配置信息

      实例:新建 Servlet 命名:ServletConfigTest

     web.xml 中添加 以下配置信息:


  <servlet>

    <servlet-name>ServletConfigTest</servlet-name>
    <servlet-class>ooo.ServletConfigTest</servlet-class>
    
    <init-param> <!-- 这里可以给servlet配置信息,这里配置的信息,只能被该servlet 读取 -->
    <param-name>enconding</param-name>
    <param-value>gb2312</param-value>
    </init-param>
    
    <!--  可以配置很多信息 -->
    <init-param> 
    <param-name>version</param-name>
    <param-value>1.0</param-value>
    </init-param>
    <init-param> 
    <param-name>author</param-name>
    <param-value>wtfmonking</param-value>
    </init-param>
    
  </servlet>
  
  <!-- 如果这里配置参数,可被所有servlet读取 -->
 <!--  
 <context-param>
 <param-name></param-name>
 <param-value></param-value>
 </context-param>
-->

 

     ServletConfigTest.java 代码


package ooo; import java.io.IOException; import java.io.PrintWriter; 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 ServletConfigTest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); //这里可以通过读取 ServletConfig 里的数据 进行设置 Enconding response.setCharacterEncoding(this.getServletConfig().getInitParameter("enconding")); PrintWriter out = response.getWriter(); out.println("Enconding :"+this.getServletConfig().getInitParameter("enconding")+"......"); //如果要把所有的参数都读取,则使用 如下方法 : Enumeration<String> names=this.getServletConfig().getInitParameterNames(); while(names.hasMoreElements()) { String name=names.nextElement(); out.println(name+" is :"); out.println(this.getServletConfig().getInitParameter(name)+"......"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }


      浏览器输出结果:

Bluetooth LE for iOS demo. LightBlue like demo.

七、http 协议 (后续再讲)


八、HttpServletResponse的再说明 

   

       getWriter() 与 getOutputStream()  的区别

             1)getWriter() 用于向客户机回送字符数据

             2)getOutputStream() 返回的对象,可以回送字符数据,也可以回送字节数据(二进制数据)

                        

OutputStream os=response.getOutputStream();os.write("hello,world".getBytes());


             如何选择:

             如果我们是回送字符数据,则使用  PrintWriter对象 ,效率高

             如果我们是回送字节数据(binarydate) ,则只能使用 OutputStream

             注意:

             这两个流不能同时使用,如下,则会报错



OutputStream os=response.getOutputStream();
os.write("hello,world".getBytes());
PrintWriter out=response.getWriter();
out.println("abc");


   

        原因分析:

Bluetooth LE for iOS demo. LightBlue like demo.

           

           从图中可以看出,web 服务器会自动关闭流(当然,最好是在程序中主动关闭流)


九、参数的传递方式sendRedirect()和session()


        需求:当用户登录成功后,把该用户名字显示在登录成功页面;

        解决思路:

                    a、使用java基础 static

                    b、使用sendRedirect()

                    c、使用session 传递

       1、使用sendRedirect()来传递字符参数


             基本格式: response.sendRedirect(“servlet的地址?参数名=参数值&参数名=参数值...”);

             参照值是String , 参数名应当使用 字母组合

             接收数据:String 参数=request.getParameter(“参数名”);

             实例:


response.sendRedirect("/UsersManager/MainFrame?uname="+username+"&pwd="+password);

//另一个 servlet中:

String username=request.getParameter("uname");
String upwd=request.getParameter("pwd");
out.println(username+" pwd="+upwd);


        2、使用session()来传递字符参数和对象

             1)传递字符串


request.getSession().setAttribute("loginuser",username); //放入session

//另一个 Servlet中:

String username2=(String) request.getSession().getAttribute("loginuser");//取出session


             2)传递对象

               建立一个 User 对象,包含用户名和密码

            User user= new User();

            user.setName("wtf");

            user.setPassWord("123");

request.getSession().setAttribute("userobj",user); //放入session   

//另一个 Servlet中:

User user=(User)request.getSession().getAttribute("userObj");//取出session



十、中文乱码处理

      (1)表单 form

                a)post 方式提交

                      在服务器端设置成浏览器端的编码方式。

                      解决方法:  request.setCharacterEncoding("utf-8"); //gbk gb2312

                b)get 方式提交

                      解决方法:

String username=new String(request.getParameter("username").getBytes("iso-8859-1"),"utf-8");// 把iso-8859-1 转换成 utf-8

                     或直接写一个工具类

package com.wtf;
public class MyTools {
	public static String getNewString(String str) {
		String newString="";
		try {
			newString=new String(str.getBytes("iso-8859-1"),"utf-8");
		} catch (Exception e) {
			e.printStackTrace();
			// 把iso-8859-1 转换成 utf-8
		} 
		return newString;
	}
}



(2) 超链接

                    <a href=”http://www.baidu.com?name=汉字”>测试</a>

                    解决:该方法和get处理方法一样.因为超链接是使用 get 提交

          (3)sendRedirect() 发生乱码

                    response.sendRedirect(“servlet地址?username=汉字”);

                    解决:该方法和get处理方法一样.


           说明: 我们应当尽量使用post 方式提交;

   

           (4)返回浏览器显示乱码

           在服务端是中文,在response的时候,也要考虑浏览器显示是否正确,一般我们通过

           response.setContentType(“text/html;charset=utf-8”); 解决

          (5)下载提示框中文乱码

                     当我们下载文件的时候,可能提示框是中文乱码

                     解决方法:Stringtemp=java.net.URLEncoder.encode("传奇.mp3","utf-8");

                  

                    response.setHeader("Content-Disposition","attachment;filename="+temp);



十一、HttpServletRequest对象的详解

        

            该对象表示浏览器的请求(http请求), 当web 服务器得到该请求后,会把请求信息封装成一个HttpServletRequest 对象

           (1) getRequestURL方法返回客户端发出请求时的完整URL。

           (2) getRequestURI方法返回请求行中的资源名部分。

           (3) getQueryString 方法返回请求行中的参数部分(参数名+值)。

                     准确的说就是接收以 get 方式提交的 参数=参数值

                     该函数可以获取请求部分的数据比如:

                                http://localhost/web名?username=abc&pwd=123

                                request.getQueryString();就会得到 username=abc&pwd=123

                     (可以使用split将参数按&分隔)

          (4)getRemoteAddr方法返回发出请求的客户机的IP地址

          (5)getRemoteHost方法返回发出请求的客户机的完整主机名

          (5)getRemotePort方法返回客户机所使用的网络端口号,客户机的端口号是随机选择的,web服务器的端口号是一定的

          (6)getLocalPort方法返回web服务器所使用的网络端口号

          (7)getLocalAddr方法返回WEB服务器的IP地址。

          (8)getLocalName方法返回WEB服务器的主机名

          (9)url 和 uri 的区别

                     Url=http://localhost:8088/ooo/MyServlet  完整的请求

                     Uri=/ooo/GetinfoServlet      web应用的名称+资源的名称


十二、表单实例:如何获取用户提交的内容(通过表单提交的内容)


           表单 Servlet:FormServlet.java  


package ooo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FormServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<form action=‘/ooo/ClServlet‘ method=‘post‘><br/>");
		out.println("<input type=‘hidden‘ value=‘这里是隐藏的内容‘ name=‘hidden1‘/>");
		out.println("用户名:<input type=‘text‘ name=‘username‘/><br/>");
		out.println("密 码:<input type=‘password‘ name=‘pwd‘/><br/>");
		out.println("性 别:<input type=‘radio‘ name=‘sex‘ value=‘男‘/>男 <input type=‘radio‘ name=‘sex‘ value=‘女‘/>女<br/>");
		out.println("你的爱好:<input type=‘checkbox‘ name=‘hobby‘ value=‘音乐‘>音乐 <input type=‘checkbox‘ name=‘hobby‘ value=‘体育‘>体育 <input type=‘checkbox‘ name=‘hobby‘ value=\"旅游\">旅游<br/>");
		out.println("所在城市:<select name=‘city‘><option value=‘bj‘>北京</option><option value=‘cq‘>重庆</option></select><br/>");
		out.println("你的介绍:<textarea cols=‘20‘ rows=‘10‘ name=‘intro‘ >请输入介绍..</textarea><br/>");
		out.println("提交照片:<input type=‘file‘ name=‘photo‘><br/>");
		//什么时候使用hidden传输数据 1.不希望用户看到该数据 2. 不希望影响节目,同时使用该数据
		
		out.println("<input type=‘submit‘ value=‘提交信息‘/>");
		out.println("</form>");

	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		this.doGet(request, response);
	}

}


处理表单的 Servlet:ClServlet.java


package ooo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ClServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String u=request.getParameter("username");
		String p=request.getParameter("pwd");
		String sex=request.getParameter("sex");
		//如果接受复选框的内容,则使用getparameterValues
		String [] hobbies=request.getParameterValues("hobby");
		String city=request.getParameter("city");
		String intro=request.getParameter("intro");
		String hidden1=request.getParameter("hidden1");
		out.println("用户名="+u+"<br/>");
		out.println("密 码="+p+"<br/>");
		out.println("性  别="+sex+"<br/>");
		if(hobbies!=null){
			for(int i=0;i<hobbies.length;i++){
				out.println("爱好:"+hobbies[i]);
			}
		}else{
			out.println("你没有爱好");
		}
		out.println("<br/>所在城市:"+city);
		out.println("<br/>个人介绍:"+intro);
		out.println("<br/>隐藏控件数据:"+hidden1);
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}
}  

   


           效果:


Bluetooth LE for iOS demo. LightBlue like demo.



Bluetooth LE for iOS demo. LightBlue like demo.,布布扣,bubuko.com

Bluetooth LE for iOS demo. LightBlue like demo.

上一篇:ThinkAndroid框架 网络状态监听原理


下一篇:浅析iOS开发中的多线程技术:NSThread,NSOperation/NSOperationQueue&GCD