JSP/Servlet程序设计(入门书籍)

Web开发技术

1. 静态开发技术:

(1)HTML

     HTML是网站开发最基本的语言,是WEB的核心。所有后续的WEB开发技术都以HTML为基础。

(2)CSS

     CSS(Cascading Style Sheet)级联样式表。

(3)JavaScript

     JavaScript是一种基于对象和事件驱动的脚本语言。JavaScript程序可以直接嵌入HTML页面,作为一种客户端程序,允许用户与其进行交互。

2. 动态网页技术:

主要有ASP、ASP.NET、PHP和JSP等。都是将相应的程序代码嵌入到HTML文档中,用以实现客户机与服务器之间的交互。

(1) ASP(Active Server Page)

是一套微软公司开发的运行于服务器端的脚本平台,ASP内含于IIS(Internet Information Server)。

优点: ASP所使用的脚本语言VBScript直接来源于Visual Basic,简单易学。ASP提供的ADO组件可轻松存取数据库。

缺点: 运行速度慢。平台适应性差。

(2) PHP(Personal Home Pages)

是Rasmus Lerdorf 于1994年提出来的,经过不断的修改完善,现在已成为一种重要的网络程序设计语言。

优点: 开放源代码;多平台支持。

缺点: PHP的主要不足体现在对各种数据库没有统一的接口标准,它对于每一种数据库几乎都采用不同的接口标准。没有大公司的支持,其推广受到一定限制。由于PHP的每一种扩充模块并不是完全由PHP本身来完成,需要许多外部的应用程序库,因此,运行环境安装相对复杂,学习起来相对于ASP难度也要大一些。

(3) JSP(Java Server Pages)

SUN公司倡导,多家公司参与建立的一种动态网页技术。

优点: 平台适应性广,几乎所有平台都支持JSP。编译后运行,运行效率高。统一的数据库接口标准JDBC。

缺点: 开发运行环境相对于ASP来讲,要复杂一些。相对于ASP的VBScript脚本语言来讲,Java语言学习起来要困难一些。

JSP概述

JSP概述

WEB开发技术

静态开发技术: 1. HTML: HTML是网站开发最基本的语言,是WEB的核心。所有后续的WEB开发技术都以HTML为基础。 2. CSS, Cascading Style Sheet(级联样式表) 3. JavaScript: JavaScript是一种基于对象和事件驱动的脚本语言。JavaScript程序可以直接嵌入HTML页面,作为一种客户端程序,允许用户与其进行交互。

<%@ page [ language="java" ]
[ contentType="mimeType;charset=CHARSET" ]
[ import="{package.class|pageage.*},…" ]
[ extends="package.class" ]
[ session="true|false" ]
[ buffer="none|8kb|size kb ]
[ autoFlush="true|false" ]
[ isThreadSafe="true|false" ]
[ info="text" ]
[ errorPage="relativeURL" ]
[ isErrorPage="true|false" ]
[ isELIgnored="true|false" ]
[ pageEncoding="CHARSET" ]
%>



JavaScript是什么?

基本概念

JavaScript是一种基于对象(Object)事件驱动(Event Driven)的脚本语言。

JavaScript可以分为三部分:核心客户端服务器端

JavaScript的用途:

  • 可以完成一些本来需要服务器端完成的编程任务

  • 作为JavaScript的一种替代,易学易用

  • 检测按钮、菜单等表单元素的事件,完成与用户之间的交互,容易对用户交互进行编程

  • 通过DOM(文档对象模型)可以访问并修改某个XHTML文档中的任何元素的CSS属性和内容

  • JavaScript脚本大部分是事件驱动的,可以响应用户对文档的操作

<html>
<head>
<script type="text/javascript">
function sum(){
    var s1 = document.f1.s1.value;
    var s2 = document.f1.s2.value;
    var s3 = Number(s1)+Number(s2);
    document.f1.s3.value=s3;
}
</script>
</head>
<body>
<form name="f1">
<input type="text" name="s1">+
<input type="text" name="s2">=
<input type="text" name="s3">
<input type="button" value="计算结果" οnclick="sum()">
</form>
</body>
</html>        




基本语法

如何使用JavaScript

方法1: 在<script>标签中嵌入JS脚本:

<script type="text/javascript"></script>

方法2: 在XHTML文档中嵌入JS文件中的脚本:

<script type="text/javascript" src="test.js"> </script>

JavaScript的注释

JavaScript中的注释分为单行多行注释,在程序的解释和运行中是被忽略的。

  • 单行注释:使用//符号对单行信息进行注释

  • 多行注释:使用/…../对多行信息进行注释

标识符的命名

必须以字母、下划线或$开头,接下来的字符可以是字母、下划线、$或数字。标识符没有长度限制。标识符不可以使用已定义好的保留字。

声明(创建) JavaScript 变量

在 JavaScript 中使用 var 关键词来声明变量:

var carname;
carname="Volvo";

或者在声明变量时对其赋值:

var carname="Volvo";

可以在一条语句中声明很多变量。该语句以 var 开头,并使用逗号分隔变量即可:

var name="Gates", age=56, job="CEO";

原始数据类型

  • 数值:包括整数数字和浮点型数字

  • 字符串:"abc" 'hello' "你好"

  • 布尔值:true 和 false

  • 空值:null

  • 未定义值:undefined

表达式和运算符

  • 算术运算符

    运算符 描述 例子 结果
    + x=y+2 x=7
    - x=y-2 x=3
    * x=y*2 x=10
    / x=y/2 x=2.5
    % 求余数 (保留整数) x=y%2 x=1
    ++ 累加 x=++y x=6
    -- 递减 x=--y x=4
  • 比较运算符

    运算符 描述 例子
    == 等于 x==8 为 false
    === 全等(值和类型) x===5 为 true;x==="5" 为 false
    != 不等于 x!=8 为 true
    > 大于 x>8 为 false
    < 小于 x<8 为 true
    >= 大于或等于 x>=8 为 false
    <= 小于或等于 x<=8 为 true
  • 逻辑运算符: && || !


    运算符 描述 例子(给定x=6,y=3)
    && and (x < 10 && y > 1) 为 true
    || or (x==5 || y==5) 为 false
    ! not !(x==y) 为 true
  • 赋值运算符: = += -= *= /= %=

  • 条件选择符: 条件表达式?A:B



JSP页面结构

JSP页面结构

JSP页面 = 静态页面元素(HTML+CSS+JavaScript)+ 指令标识 + 脚本 + 表达式 + 动作标识

<!-- JSP中的指令标识 -->
<%@ page language="java" contentType="text/html; charset=gb2312" %>
<%@ page import="java.util.Date" %>
<!-- HTML标记语言 -->
<html>
  <head><title>JSP页面的基本构成</title></head>
  <body>
   <center>
<!-- 嵌入的Java代码 -->
<% String today=new Date().toLocaleString(); %>
<!-- JSP表达式 -->
今天是:<%=today%>
<!-- HTML标记语言 -->
   </center>
  </body>
</html>



JSP指令


JSP指令可以使服务器按照指令的设置来执行动作和设置在整个JSP页面范围内有效的属性。指令通常以“<%@”标记开始,以“%>”标记结束,可设置多个属性,指令的一般格式为:

<%@ 指令名称 属性1="属性值" 属性2="属性值" …%>

在JSP中主要包含3种指令,分别是page指令(页面指令)、include指令taglib指令

page指令

page指令定义了整个JSP页面范围内有效的属性,可以放在JSP页面中的任意行,习惯上放在文件的开始部分。除import属性外,其他属性只能在指令中出现一次。

<%@ page
  [ language="java" ]
  [ contentType="mimeType;charset=CHARSET" ]
  [ import="{package.class|pageage.*},…" ]
  [ extends="package.class" ]
  [ session="true|false" ]
  [ buffer="none|8kb|size kb ]
  [ autoFlush="true|false" ]
  [ isThreadSafe="true|false" ]
  [ info="text" ]
  [ errorPage="relativeURL" ]
  [ isErrorPage="true|false" ]
  [ isELIgnored="true|false" ]
  [ pageEncoding="CHARSET" ]
%>

language属性:设置当前页面中编写JSP脚本使用的语言,默认值为java,例如:

<%@ page language="java" %>

contentType属性:设置页面响应的MIME类型,通常被设置为text/html,例如:

<%@ page contentType="text/html" %>

在该属性中还可以设置页面采用的字符编码类型,默认的编码为ISO-8859-1,如果需要显示中文,字符集可以使用UTF-8,例如:

<%@ page contentType="text/html;charset=UTF-8" %>

import 属性:import属性类似于Java中的import语句,用来向JSP文件中导入需要用到的包。在Page指令中可多次使用该属性来导入多个包。例如:

<%@ page import="java.util.*" %>
<%@ page import="java.text.*" %>

或者通过逗号间隔,来导入多个包。

<%@ page import="java.util.*,java.text.*" %>

JSP中已经默认导入了以下包:

java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*

extends属性: 用于指定将一个JSP页面转换为Servlet后继承的类。通常不会设置该属性,JSP容器会提供继承的父类。如果设置了该属性,一些改动会影响JSP的编译能力。

session属性:该属性默认值为true,表示当前页面支持session,设为false表示不支持session。

buffer属性: 该属性用来设置out对象(JspWriter类对象)使用的缓冲区的大小。若设置为none,表示不使用缓存,而直接通过PrintWriter对象进行输出;如果将该属性指定为数值,则输出缓冲区的大小不应小于该值,默认值为8KB(因不同的服务器而不同,但大多数情况下都为8KB)。

autoFlush属性: 该属性默认值为true,表示当缓冲区已满时,自动将其中的内容输出到客户端。如果设为false,则当缓冲区中的内容超出其设置的大小时,会产生“JSP Buffer overflow”溢出异常。

注意:若buffer属性设为none,则autoFlush不能设为false。

isThreadSafe属性:该属性默认值为true,表示当前JSP页面被转换为Servlet后,会以多线程的方式来处理来自多个用户的请求;如果设为false,则转换后的Servlet会实现SigleThreadModel接口,该Servlet将以单线程的方式来处理用户请求,即其他请求必须等待直到前一个请求处理结束。

info属性:该属性可设置为任意字符串,如当前页面的作者或其他有关的页面信息。可通过Servlet.getServletInfo()方法来获取设置的字符串。例如:

<%@ page info="This is index.jsp!" %>
<%=this.getServletInfo()%>

errorPage属性:该属性用来指定一个当前页面出现异常时所要调用的页面。如果属性值是以“/”开头的路径,则将在当前应用程序的根目录下查找文件;否则,将在当前页面的目录下查找文件。

isErrorPage属性:将该属性值设为true,此时在当前页面中可以使用exception异常对象。若在其他页面中通过errorPage属性指定了该页面,则当前者出现异常时,会跳转到该页面,并可在该页面中通过exception对象输出错误信息。相反,如果将该属性设置为false,则在当前页面中不能使用exception对象。该属性默认值为false

isELIgnored属性:通过该属性的设置,可以使JSP容器忽略表达式语言“${}”。其值只能为true或false。设为true,则忽略表达式语言。

pageEncoding 属性:该属性用来设置JSP页面字符的编码。默认值为ISO-8859-1

include指令

该指令用于在当前的JSP页面中,在当前使用该指令的位置嵌入其他的文件,如果被包含的文件中有可执行的代码,则显示代码执行后的结果。该指令的使用格式如下:

<%@ include file="文件的绝对路径或相对路径" %>

file属性:该属性指定被包含的文件,该属性不支持任何表达式,也不允许通过如下的方式来传递参数。

<%@ include file="welcome.jsp?name=yxq" %>

如果该属性值以“/”开头,那么指定的是一个绝对路径,将在当前应用的根目录下查找文件;如果是以文件名称或文件夹名开头,那么指定的是一个相对路径,将在当前页面的目录下查找文件。

可以将复杂页面分成若干个独立的部分,将相同的部分在单独的JSP文件中进行编写,使用include指令引用这些文件,以减少代码的冗余。例如,有两个JSP页面都需要应用下图所示的网页模板进行布局。

<%@ page contentType="text/html;charset=gb2312" %>
<table>
    <tr><td colspan="2"> <%@ include file="top.jsp"%> </td></tr>
    <tr>
        <td><%@ include file="side.jsp"%></td>
        <td>在这里对内容显示区进行编码</td>
    </tr>
    <tr><td colspan="2"><%@ include file="end.jsp"%></td></tr>
</table>

taglib指令

声明用户使用自定义的标签,将标签库描述符文件导入到jsp页面。指令的语法格式如下:

<%@ taglib uri="tagURI" prefix="tagPrefix" %>

uri属性:定位标签库描述符的位置。唯一标识和前缀相关的标签库描述符,可以使用绝对或相对URL。

tagDir属性:指示前缀将被用于标识在WEV-INF/tags目录下的标签文件。

prefix属性:标签的前缀,区分多个自定义标签。不可以使用保留前缀和空前缀,遵循XML命名空间的命名约定。前缀不能命名为jsp、jspx、java、javax、sun、servlet和sunw。

开发者可通过前缀来引用标签库中的标签。以下为一个简单的使用JSTL的代码,该段代码通过<c:set>标签将字符串hello赋值给了变量name:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="name" value="hello"/>




JSP脚本

JSP表达式

语法:<%=变量/有返回值的方法调用/Java表达式 %>

作用:向页面输出信息

(1)向页面输出内容

<% String name="www.qq.com"; %>

用户名:<%=name%>

(2)生成动态的链接地址

<% String path="welcome.jsp"; %>

<a href="<%=path%>">链接到welcom.jsp</a>

(3)动态指定Form表单处理页面

 <% String name="logon.jsp"; %>

 <form action="<%=name%>"></form>

该段代码将生成如下HTML代码:

<form action="logon.jsp"></form>

(4)为通过循环语句生成的元素命名

<% for(int i=1;i<3;i++){ %> 

    file<%=i%>:<input type="text" name="<%="file"+i%>"><br>

<% } %>

代码运行将生成下面的HTML代码:

file1:<input type="text" name="file1"><br>

file2:<input type="text" name="file2"><br>




声明(Declaration)

作用:声明变量和方法

语法:<%! 声明变量或方法的代码 %>

注意事项:

· 

在“<%”与“!”之间不要有空格

· 

· 

声明的语法与在Java语言中声明变量和方法时是一样的。

· 

· 

在页面中通过声明标识声明的变量和方法,在整个页面内都有效,它们将成为JSP页面被转换为Java类后类中的属性和方法。并且它们会被多个线程即多个用户共享。

· 

【程序】一个简单的网站计数器

<%@ page contentType="text/html;charset=UTF-8" %>

 

<%!

  int num=0;    //声明一个计数变量

  synchronized void add(){  //该方法实现访问次数的累加操作

  num++;

}

%>

<% add(); %>   <%-- 该脚本程序调用实现访问次数累加的方法 --%>

<html>

<body><center>您是第<%=num%>位访问该页的游客!</center></body>

</html>

脚本程序

语法规则:<% Java程序片段 %>

作用:在脚本程序中可以定义变量、调用方法和进行各种表达式运算,且每行语句后面要加入分号。

在脚本程序中定义的变量:

· 

在当前的整个页面内都有效

· 

· 

但不会被其他的线程共享

· 

· 

当前用户对该变量的操作不会影响到其他的用户

· 

· 

当变量所在的页面关闭后就会被销毁。

· 

【示例程序】脚本的使用

<%@ page contentType="text/html;charset=gb2312"%>

<% int able=1; %>

<html>

<body>

<table>

<% if(able==1){%>

<tr><td>欢迎登录!您的身份为“普通管理员”。</td></tr>

<% }

   else if(able==2){

    %>

   <tr><td>欢迎登录!您的身份为“系统管理员”。</td></tr>

   <% } %>

 </table>

</body>

</html>

JSP的注释

(1)HTML注释:

语法:<!-- 注释内容 -->

HTML注释中可以嵌入表达式:

(2)隐藏注释

语法:<%-- 注释内容 --%>

该注释在客户端浏览时看不到,而且即使是通过在客户端查看HTML源代码,也不会看到

(3)脚本程序中的注释

单行注释://注释内容放在这里

多行注释:

/* 注释1

   注释2

   注释...

*/

 

 

 

JSP动作

JSP中的动作标识可用来实现一些特殊功能,例如请求的转发、在页面中包含其他文件、在页面中创建一个JavaBean实例等。动作标识是在请求处理阶段按页面中的出现顺序执行。

动作标识的基本语法形式:

<动作名称 属性1="值1" 属性2="值2"…/>

<动作名称 属性1="值1" 属性2="值2" …>

    <子动作 属性1="值1" 属性2="值2" …/>

</动作名称>

JSP动作标识主要有:

· 

<jsp:include>

· 

· 

<jsp:forward>

· 

· 

<jsp:useBean>

· 

· 

<jsp:setProperty>

· 

· 

<jsp:getProperty>

· 

· 

<jsp:fallback>

· 

· 

<jsp:plugin>

· 

<jsp:include>

作用:用于向当前的页面中包含其他动态或静态文件。

语法格式:

<jsp:include page="被包含文件的路径" flush="true|false"/>

也可以向被包含的动态页面中传递参数:

<jsp:include page="被包含文件的路径" flush="true|false">

    <jsp:param name="参数名称" valude="参数值"/>

</jsp:include>

page属性:该属性指定了被包含文件的路径,其值可以是一个代表了相对路径的表达式。当路径是以“/”开头时,则按照当前应用的路径查找这个文件;如果路径是以文件名或目录名称开头,那么将按照当前的路径来查找被包含的文件。

flush属性:表示当输出缓冲区满时,是否清空缓冲区。该属性值为boolean型,默认值为false,通常情况下设为true。

<jsp:param>子标识:可以向被包含的动态页面中传递参数。

<jsp:include>标识对包含的动态文件和静态文件的处理方式是不同的。如果被包含的是静态文件,则页面执行后,在使用了该标识的位置处将会输出这个文件的内容。如果<jsp:include>标识包含的是一个动态文件,那么JSP编译器将编译并执行这个文件。不能通过文件的名称来判断该文件是静态的还是动态的,<jsp:include>标识会识别出文件的类型。

<jsp:include>动作标识与include指令都可用来包含文件,它们的区别主要有:

(1)属性不同

include指令通过file属性来指定被包含的页面,include指令将file属性值看作一个实际存在的文件的路径,所以该属性不支持任何表达式。若在file属性值中应用JSP表达式,则会抛出异常,如下面的代码:

<%  String path="logon.jsp";  %>

<%@ include file="<%=path%>" %>

这段代码将抛出下面的异常:

File "/<%=path%>" not found

<jsp:include>动作标识通过page属性来指定被包含的页面,该属性支持JSP表达式。

(2)处理方式不同

使用include指令被包含的文件,它的内容会原封不动地插入到包含页中使用该指令的位置,然后JSP编译器再对这个合成的文件进行翻译。所以在一个JSP页面中使用include指令来包含另外一个JSP页面,最终编译后的文件只有一个。

使用<jsp:include>动作标识包含文件时,当该标识被执行时,程序会将请求转发到(注意是转发,而不是请求重定向)被包含的页面,并将执行结果输出到浏览器中,然后返回包含页继续执行后面的代码。因为服务器执行的是两个文件,所以JSP编译器会分别对这两个文件进行编译。

(3)包含方式不同

使用include指令包含文件,最终服务器执行的是将两个文件合成后由JSP编译器编译成的一个Class文件,所以被包含文件的内容应是固定不变的,若改变了被包含的文件,则主文件的代码就发生了改变,因此服务器会重新编译主文件。include指令的这种包含过程称为静态包含。

使用<jsp:include>动作标识通常是来包含那些经常需要改动的文件。此时服务器执行的是两个文件,被包含文件的改动不会影响到主文件,因此服务器不会对主文件重新编译,而只需重新编译被包含的文件即可。而对被包含文件的编译是在执行时才进行的,也就是说,只有当<jsp:include>动作标识被执行时,使用该识包含的目标文件才会被编译,否则被包含的文件不会被编译,所以这种包含过程称为动态包含。

(4)对被包含文件的约定不同

使用include指令包含文件时,对被包含文件有约定。

【示例程序】 通过include指令包含文件

top.jsp文件:

<%@ page contentType="text/html;charset=gbk" %>

这是top.jsp页面中的内容!

index.jsp文件:

<%@ page contentType="text/html;charset=gb2312" %>

<%@ include file="top.jsp" %>

<br>这是index.jsp页面中的内容!

【示例程序】 通过include动作标识包含文件

<%@ page contentType="text/html;charset=gb2312" %> <jsp:include page="top.jsp"/> 
这是index.jsp页面中的内容!

<jsp:forward>

用来将请求转发到另外一个JSP、HTML或相关的资源文件中。当该标识被执行后,当前的页面将不再被执行,而是去执行该标识指定的目标页面。

语法形式:

<jsp:forward page="文件路径 | 表示路径的表达式"/>

如果转发的目标是一个动态文件,可以向该文件中传递参数,格式如下:

<jsp:include page="被包含文件的路径" flush="true|false">

    <jsp:param name="参数名称" value="参数值"/>

</jsp:include>

page属性:该属性指定了目标文件的路径。如果该值是以“/”开头,表示在当前应用的根目录下查找文件,否则就在当前路径下查找目标文件。请求被转向到的目标文件必须是内部的资源,即当前应用中的资源。

如果想通过forward动作转发到应用外部的文件中,例如,当前应用为A,在根目录下的index.jsp页面中存在下面的代码用来将请求转发到应用B中的logon.jsp页面。

<jsp:forward page="http://localhost:8080/B/logon.jsp"/>

将出现下面的错误提示:The requested resource (/http://localhost:8080/B/logon.jsp) is not available

<jsp:param>子标识:用来向动态的目标文件中传递参数。

<jsp:forward>标识实现的是请求的转发操作,而不是请求重定向。它们之间的一个区别就是:进行请求转发时,存储在request对象中的信息会被保留并被带到目标页面中;而请求重定向是重新生成一个request请求,然后将该请求重定向到指定的URL,所以事先存储在request对象中的信息都不存在了。

<jsp:useBean>

<jsp:useBean>动作标识可以在JSP页面中创建一个Bean实例,并且通过属性的设置可以将该实例存储到JSP中的指定作用域。如果在指定的作用域内已经存在了指定的Bean实例,那么将使用这个实例,而不会重新创建。通过<jsp:useBean>标识创建的Bean实例可以在Scriptlet中应用。

基本语法格式如下:

<jsp:useBean 

    id="变量名" 

 scope="page|request|session|application"

 {

    class="package.className"|

  type="数据类型"|

  class="package.className" type="数据类型"|

  beanName="package.className" type="数据类型"

 }

/>

<jsp:setProperty name="变量名" property="*"/>

也可以在标识体内嵌入子标识或其他内容:

<jsp:useBean id="变量名" scope="page|request|session|application" …>

    <jsp:setProperty name="变量名" property="*"/>

</jsp:useBean>

这两种使用方法是有区别的。在页面中应用<jsp:useBean>标识创建一个Bean时,如果该Bean是第一次被实例化,那么对于<jsp:useBean>标识的第二种使用格式,标识体内的内容会被执行,若已经存在了指定的Bean实例,则标识体内的内容就不再被执行了。而对于第一种使用格式,无论在指定的范围内是否已经存在一个指定的Bean实例,<jsp:useBean>标识后面的内容都会被执行。

<jsp:useBean>标识中各属性:

id属性:该属性指定一个变量,在所定义的范围内或脚本中将使用该变量来对所创建的Bean实例进行引用。该变量必须符合Java中变量的命名规则。

type属性:用于设置由id属性指定的变量的类型。type属性可以指定要创建实例的类的本身、类的父类或者是一个接口。

使用type属性来设置变量类型的使用格式如下:

<jsp:useBean id="us" type="com.Bean.UserInfo" scope="session"/>

如果在session范围内,已经存在了名为“us”的实例,则将该实例转换为type属性指定的UserInfo类型(必须是合法的类型转换)并赋值给id属性指定的变量;若指定的实例不存在将抛出“bean us not found within scope”异常。 scope属性:该属性指定了所创建Bean实例的存取范围,省略该属性时的值为page。<jsp:useBean>标识被执行时,首先会在scope属性指定的范围来查找指定的Bean实例,如果该实例已经存在,则引用这个Bean,否则重新创建,并将其存储在 scope属性指定的范围内。scope属性具有的可选值如下。

· 

page:指定了所创建的Bean实例只能够在当前的JSP文件中使用,包括在通过include指令静态包含的页面中有效。

· 

· 

request:指定了所创建的Bean实例可以在请求范围内进行存取。在请求被转发至的目标页面中可通过request对象的getAttribute("id属性值")方法获取创建的Bean实例。一个请求的生命周期是从客户端向服务器发出一个请求到服务器响应这个请求给用户后结束,所以请求结束后,存储在其中的Bean的实例也就失效了。

· 

· 

session:指定了所创建的Bean实例的有效范围为session。session是当用户访问Web应用时,服务器为用户创建的一个对象,服务器通过session的ID值来区分其他的用户。针对某一个用户而言,在该范围中的对象可被多个页面共享。

· 

· 

application:该值指定了所创建的Bean实例的有效范围从服务器启动开始到服务器关闭结束。application对象是在服务器启动时创建的,它被多个用户共享。所以访问该application对象的所有用户共享存储于该对象中的Bean实例。可以使用application对象的getAttribute("id属性值")方法获取存在于application中的Bean实例。

· 

class属性:指定了一个完整的类名,其中package表示类包的名字,className表示类的Class文件名称。通过class属性指定的类不能是抽象的,它必须具有公共的、没有参数的构造方法。在没有设置type属性时,必须设置class属性。格式如下:

<jsp:useBean id="us" class="com.Bean.UserInfo" scope="session"/>

在<jsp:useBean>标识中class属性与type属性一起使用时格式如下:

<jsp:useBean id="us" class="com.Bean.UserInfo" type="com.Bean.UserBase" scope="session"/>

这里假设UserBase类为UserInfo类的父类。该标识被执行时,程序首先创建了一个以type属性的值为类型,以id属性值为名称的变量us,并赋值为null;然后在session范围内来查找这个名为“us”的Bean实例,如果存在,则将其转换为type属性指定的UserBase类型(类型转换必须是合法的)并赋值给变量us;如果实例不存在,那么将通过new操作符来实例化一个UserInfo类的实例并赋值给变量us,最后将us变量储在session范围内。

beanName属性:与type属性可以指定同一个类,在<jsp:useBean>标识中beanName属性与type属性一起使用时的格式如下:

<jsp:useBean id="us" beanName="com.Bean.UserInfo" type="com.Bean.UserBase"/>

这里假设UserBase类为UserInfo类的父类。该标识被执行时,程序首先创建了一个以type属性的值为类型,以id属性值为名称的变量us,并赋值为null;然后在session范围内来查找这个名为“us”的Bean实例,如果存在,则将其转换为type属性指定的UserBase类型(类型转换必须是合法的)并赋值给变量us;如果实例不存在,那么将通过instantiate()方法从UserInfo类中实例化一个类并将其转换成UserBase类型后赋值给变量us,最后将变量us存储在session范围内。

通常情况下应用<jsp:useBean>标识的格式如下:

<jsp:useBean id="变量名" class="package.className"/>

如果想共享这个Bean实例,可根据需要设置scope属性。

<jsp:setProperty>

通常情况下与<jsp:useBean>标识一起使用,它将调用Bean中的setXxx()方法将请求中的参数赋值给由<jsp:useBean>标识创建的JavaBean中对应的简单属性或索引属性。该标识的语法格式如下:

<jsp:setProperty

    name="Bean实例名"

 {

  property="*" |

  property="propertyName" |

  property="propertyName" param="parameterName" |

  property="propertyName" value="值"

 }/>

name属性:用来指定一个存在JSP中某个范围中的Bean实例。<jsp:setProperty>标识将会按照page、request、session和application的顺序来查找这个Bean实例,直到第一个实例被找到。若任何范围内不存在这个Bean实例,则会抛出异常。

property="*":property属性取值为“*”时,则request请求中所有参数的值将被一一赋给Bean中与参数具有相同名字的属性。如果请求中存在值为空的参数,那么Bean中对应的属性将不会被赋值为Null;如果Bean中存在一个属性,但请求中没有与之对应的参数,那么该属性同样不会被赋值为Null。

该使用方法要求请求中参数的名称和类型必须与Bean中属性的名称和类型一致。但由于通过表单传递的参数都是String类型的,所以JSP会自动将这些参数转换为Bean中对应属性的类型。下表给出了JSP自动将String类型转换为其他类型时所调用的方法。

property="propertyName":property属性取值为Bean中的属性时,则只会将request请求中与该Bean属性同名的一个参数的值赋给这个Bean属性。更进一步讲,如果property属性指定的Bean属性为userName,那么指定Bean中必须存在setUserName()方法,否则会抛出类似于下面的异常:

Cannot find any information on property 'userName' in a bean of type 'com.Bean.UserInfo'

在此基础上,如果请求中没有与userName同名的参数,则该Bean属性会保留原来或默认的值,而不会被赋值为Null。当请求中参数的类型与Bean中属性类型不一致时,JSP会自动进行转换。

property="propertyName" param="parameterName"

param属性指定一个request请求中的参数,property属性指定Bean中的某个属性。该种使用方法允许将请求中的参数赋值给Bean中与该参数不同名的属性。如果param属性指定参数的值为空,那么由property属性指定的Bean属性会保留原来或默认的值而不会被赋为null。

property="propertyName" value="值"

value属性指定的值可以是一个字符串数值或表示一个具体值的JSP表达式或EL表达式。该值将被赋给property属性指定的Bean属性。

· 

当value属性指定的是一个字符串时,如果指定的Bean属性与其类型不一致时,则会根据表3-3中的方法将该字符串值自动转换成对应的类型。

· 

· 

当value属性指定的是一个表达式时,那么该表达式所表示的值的类型必须与property属性指定的Bean属性一致,否则会抛出“argument type mismatch”异常。

· 

· 

通常<jsp:setProperty>标识与<jsp:useBean>标识一起使用,但这并不是绝对的,应用如下的方法同样可以将请求中的参数值赋给JavaBean中的属性。

· 

<jsp:getProperty>

<jsp:getProperty>属性用来从指定的Bean中读取指定的属性值,并输出到页面中。该Bean必须具有getXxx()方法。<jsp:getProperty>的语法格式如下:

<jsp:getProperty name="Bean实例名" property="propertyName"/>

name属性:name属性用来指定一个存在某JSP范围中的Bean实例。<jsp:getProperty>标识将会按照page、request、session和application的顺序来查找这个Bean实例,直到第一个实例被找到。若任何范围内不存在这个Bean实例则会抛出“Attempted a bean operation on a null object”异常。

property属性:该属性指定了要获取Bean中哪个属性的值。若它指定的值为“userName”,那么Bean中必须存在getUserName()方法,否则会抛出下面的异常:

Cannot find any information on property 'userName' in a bean of type '此处为类名'

如果指定Bean中的属性是一个对象,那么该对象的toString()方法被调用,并输出执行结果。

 

 

JSP内置对象

概述

JSP页面中内置了一些默认的对象,这些对象不需要预先声明就可以在脚本代码和表达式中随意使用。

request、response和session是JSP内置对象中重要的3个对象,这3个对象体现了服务器端与客户端(即浏览器)进行交互通信的控制。

request对象

request对象是JSP中重要的对象,每个request对象封装着一次用户请求,并且所有的请求参数都被封装在request对象中,因此request对象是获取请求参数的重要途径。

除此之外,request可代表本次请求范围,所以还可用于操作request范围的属性。

本节主要介绍:

(1)访问请求参数

(2)在请求作用域中管理属性

(3)Cookie操作

(4)获取客户信息

(5)访问安全与国际化信息

 

访问请求参数

客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据,然后通过request对象的相关方法来获取这些数据。

访问请求参数

· 

获取单值参数

· 

客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据; 服务器端可使用request对象的getParameter()方法获取用户提交的单值参数数据。

String userName = request.getParameter("name");

login.jsp

<form id="form1" name="form1" method="post" action="login_deal.jsp">

    用户名:<input name="username" type="text" id="username" /><br/> <br/>

    密  码: <input name="pwd" type="password" id="pwd" /> <br/> <br/>

    <input type="submit" name="Submit" value="提交" />

    <input type="reset" name="Submit2" value="重置" />

</form>

login_deal.jsp

<body>

<%

    request.setCharacterEncoding("gb2312");

    String username=request.getParameter("username");

    String pwd=request.getParameter("pwd");

    out.println("用户名为:"+username);

    out.println("密码为:"+pwd);

%>

</body>

</html>

· 

中文乱码问题

· 

超链接中需要传递中文数据,需要使用java.net.URLEncoder先进行编码转换:

<%@ page import="java.net.URLEncoder" %>

 

<a href="processTest.jsp?username=<%=URLEncoder.encode("张三","UTF-8")%>&pwd=123456">click me!</a>

对于post类型的请求,需要在处理页面中获取数据之前使用下面的语句:

 request.setCharacterEncoding("UTF-8");

对于get类型的请求,可以在获取到参数数据后使用java.net.URLDecoder进行解码:

<%@ page import="java.net.URLDecoder" %>

 

String name=request.getParameter("username");

name=URLDecoder.decode(name,"UTF-8");

【示例程序】处理中文乱码问题

testform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<%@ page import="java.net.URLEncoder" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

    <head>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <title>Insert title here</title>

    </head>

    <body>

        <a href="processTest.jsp?username=<%=URLEncoder.encode("张三","UTF-8")%>&pwd=123456">click me!</a><br>

        <form method="get" action="processTest.jsp">

            姓名:<input type="text" name="username"><br>

            密码:<input type="password" name="pwd"><br>

            <input type="checkbox" name="hobby" value="睡觉">睡觉

            <input type="checkbox" name="hobby" value="打游戏">打游戏

            <input type="checkbox" name="hobby" value="吃饭">吃饭<br>

 

            <input type="submit" value="保存">

        </form>

    </body>

</html>

processTest.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<%@ page import="java.net.URLDecoder" %>

<%

    String name=null;

    String hobby=null;

    if(request.getMethod().equalsIgnoreCase("get")){

        name=request.getParameter("username");

        //name=new String(name.getBytes("ISO-8859-1"),"UTF-8");

        name=URLDecoder.decode(name,"UTF-8");

        System.out.println("get method...");

    }else{

        request.setCharacterEncoding("UTF-8");

        name=request.getParameter("username");

        System.out.println("post method...");

 

        String[] hobbies=request.getParameterValues("hobby");

        StringBuffer sb=new StringBuffer("");

        if(hobbies!=null){

            for(String h:hobbies){

                sb.append(h+" ");

            }

            hobby=sb.toString();

        }

    }

    System.out.println(name);

    out.println(name);

    out.println("<br>"+hobby);

 

%>

· 

获取多值参数的值

· 

可通过getParameterValues方法获取多值参数的值。

String values = request.getParameterValues("name");

for(String value : values){

    System.out.println(value);

}

request.getParameterValues("name")方法将获取所有form表单中name属性为"name"的值,该方法返回一个数组,遍历数组就可得到value值。

· 

获取所有参数的名称

· 

request.getParameterNames()方法可以获取发送请求页面中form表单里所有具有name属性的表单对象(包括button),返回一个Enumeration类型的枚举对象。

Enumeration pNames=request.getParameterNames();

while(pNames.hasMoreElements()){

    String name=(String)pNames.nextElement();

    String value=request.getParameter(name);

    out.print(name + "=" + value);

}

上述代码通过EnumerationhasMoreElements()方法遍历,再由nextElement()方法获得枚举的值(即:form表单中控件的name属性的值)。最后通过request.getParameter()方法获取表单控件的value值。

 

在作用域中管理属性

在进行请求转发时,需要把一些数据带到转发后的页面进行处理。这时,就可以使用request对象的setAttribute()方法将数据以对象属性的方式保存在request对象中,可以在请求的作用域内可以存取。

保存属性:

request.setAttribute("key", Object);

参数key是键,为String类型。在转发后的页面取数据时,就通过这个键来获取数据。参数object是键值,为Object类型,它代表需要保存在request范围内的数据。

获取属性:

Object value=request.getAttribute(String name);

其中参数name表示键名,返回值为Object类型。

【示例程序】 request作用域内的属性读写

setAttribute.jsp

<%

  request.setAttribute("error","很抱歉!您输入的用户名或密码不正确!");

%>

<jsp:forward page="error.jsp" />

error.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>

 

<html xmlns="http://www.w3.org/1999/xhtml">

    <head>

        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

        <title>处理结果</title>

    </head>

 

<body>

<%

    out.println("错误提示信息为:"+ request.getAttribute("error"));

%>

</body>

</html>

 

 

Cookie操作

Cookie为Web应用程序保存用户相关信息提供了一种有用的方法。Cookie是一小段文本信息,伴随着用户请求和页面在Web服务器和浏览器之间传递。用户每次访问站点时,Web应用程序都可以读取Cookie包含的信息。

获取Cookie

JSP中,可以通过request对象中的getCookies()方法获取Cookie中的数据。

Cookie[] cookie = request.getCookies();

保存Cookie

Cookie cookie_response=new Cookie("AccessTime","");

cookie_response.setValue(new java.util.Date().toLocaleString());

response.addCookie(cookie_response);

【示例程序】 记录网页的上一次访问时间

getCookie.jsp

<%

Cookie[] cookies = request.getCookies();//从request中获得Cookies集

Cookie cookie_response = null; //初始化Cookie对象为空

 

if (cookies != null && cookies.length >= 2) {

for (Cookie c : cookies) {

if (c.getName().equals("AccessTime")) {

cookie_response = c;

break;

}

}

}

java.util.Date now = new java.util.Date();

out.println("本次访问时间:" + now.toLocaleString() + "<br>");

 

if (cookie_response != null) {

//输出上一次访问的时间,并设置cookie_response对象为最新时间

out.println("上一次访问时间:" + cookie_response.getValue());

cookie_response.setValue(now.toLocaleString());

}

//如果Cookies集为空,创建cookie,并加入到response中

if (cookies == null || cookies.length < 2) {

cookie_response = new Cookie("AccessTime", "");

cookie_response.setValue(now.toLocaleString());

 

}

response.addCookie(cookie_response);

%>

 

获取客户信息

 request对象提供一些用来获取客户信息的方法,如下表所示。

【示例程序】 获取客户基本信息

getInfo.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>

<html xmlns="http://www.w3.org/1999/xhtml">

    <head>

        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

        <title>获取客户信息</title>

    </head>

 

<body>

    客户提交信息的方式:<%=request.getMethod()%>

    <br>使用的协议:<%=request.getProtocol()%>

    <br>获取发出请求字符串的客户端地址:<%=request.getRequestURI()%>

    <br>获取提交数据的客户端IP地址:<%=request.getRemoteAddr()%>

    <br>获取服务器端口号:<%=request.getServerPort()%>

    <br>获取服务器的名称:<%=request.getServerName()%>

    <br>获取客户端的机器名称:<%=request.getRemoteHost()%>

    <br>获取客户端所请求的脚本文件的文件路径:<%=request.getServletPath()%>

    <br>获得Http协议定义的文件头信息Host的值:<%=request.getHeader("host")%>

    <br>获得Http协议定义的文件头信息User-Agent的值:<%=request.getHeader("user-agent")%>

</body>

</html>

 

访问安全与国际化信息

访问安全信息

request对象提供了对安全属性的访问,如下表所示。

用户安全信息:<%=request.isSecure()%>

上面的代码用来确定当前请求是否使用了安全协议。

访问国际化信息

浏览器可以通过accept-language的HTTP报头向Web服务器指明它所使用的本地语言。

request对象中的getLocale()getLocales()方法允许JSP开发人员获取这一信息,获取的信息属于java.util.Local类型。

java.util.Local类型的对象封装了一个国家和一种国家所使用的语言。使用这些信息,JSP开发者就可以使用语言所特有的信息作出响应。

<%

    java.util.Locale locale=request.getLocale();

    if(locale.equals(java.util.Locale.US)){

        out.print("Welcome to BeiJing");

    }

    if(locale.equals(java.util.Locale.CHINA)){

        out.print("北京欢迎您");

    }

%>

这段代码,如果所在区域为中国,将显示“北京欢迎您”,而所在区域为美国,则显示“Welcome to BeiJing”。

 

 

response对象

response对象和request对象相对应,用于响应客户请求,向客户端输出信息。response对象是javax.servlet.http.HttpServletResponse接口类的对象,它封装了JSP产生的响应,并发送到客户端以响应客户端的请求。

页面重定向

可以使用response对象中的sendRedirect()方法将客户请求重定向到另外一个页面。

response.sendRedirect("login_ok.jsp");

上述代码是将客户请求重定向到login_ok.jsp页面。

可以使用response对象中的sendError()方法指明一个错误状态。该方法接收一个错误以及一条可选的错误消息,该消息将在内容主体上返回给客户。

例如:

response.sendError(500,"请求页面存在错误");

会将客户请求重定向到一个在内容主体上包含了出错消息的出错页面。

response对象中用于重定向网页的方法如下表所示:

【示例程序】 页面的重定向

login_deal.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

    <title>处理结果</title>

</head>

 

<body>

<%

    request.setCharacterEncoding("gb2312");

    String username=request.getParameter("username");

    String pwd=request.getParameter("pwd");

    if(!username.equals("") && !pwd.equals("")){

        response.sendRedirect("login_ok.jsp");

    }else{

        response.sendError(500,"请输入登录验证信息");

    }

%>

</body>

</html>

设置HTTP响应报头

response对象提供了设置HTTP响应报头的方法:

<%response.setHeader("Cache-Control","no-store");

response.setDateHeader("Expires",0);%>

上述代码通过设置HTTP头可实现禁用缓存功能。需要注意的是,上面的代码必须在没有任何输出发送到客户端之前使用。

【示例程序】 将JSP页面保存为word文档

saveAsWord.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>

<%

if(request.getParameter("submit1")!=null){

    response.setContentType("application/msword;charset=gb2312");

}

%>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

<title></title>

</head>

 

<body>

平平淡淡才是真!

快快乐乐才是福!

<form action="" method="post" name="form1">

    <input name="submit1" type="submit" id="submit1" value="保存为word">

</form>

</body>

</html>

缓冲区配置

缓冲可以更加有效地在服务器与客户之间传输内容。HttpServletResponse对象为支持jspWriter对象而启用了缓冲区配置。response对象提供了配置缓冲区的方法,如下表所示。

【示例程序】 输出缓冲区的大小并测试强制将缓冲区的内容发送给客户。

buffer.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>

 

<html xmlns="http://www.w3.org/1999/xhtml">

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

    <title>处理结果</title>

    </head>

 <body>

<%

    out.print("缓冲区大小:"+response.getBufferSize()+"<br>");

    out.print("缓冲区内容强制提交前<br>");

    out.print("输出内容是否提交:"+response.isCommitted()+"<br>");

    response.flushBuffer();

    out.print("缓冲区内容强制提交后<br>");

    out.print("输出内容是否提交:"+response.isCommitted()+"<br>");

%>

 

</body>

</html>

 

 

session对象

HTTP协议是一种无状态协议。当一个客户向服务器发出请求,服务器接收请求,并返回响应后,该连接就被关闭了,此时服务器端不保留连接的有关信息。

JSP提供了session对象,这样服务器和客户端之间的连接就会一直保持下去,但是在一定时间内(系统默认在30min内),如果客户端不向服务器发出应答请求,session对象就会自动消失。不过在编写程序时,可以修改这个时间限定值,使session对象在特定时间内保存信息。保存的信息可以是与客户端有关的,也可以是一般信息,这可以根据需要设定相应的内容。

创建及获取客户的会话

内置对象session使用setAttribute()getAttribute()方法创建及获取客户的会话。

setAttribute()方法用于是设置指定名称的属性值,并将其存储在session对象中,其语法格式如下:

session.setAttribute(String name,Object value);

参数:name为属性名称,value为属性值。

getAttribute()方法用于是获取与指定属性名name相联系的属性值,返回值类型为Object,语法格式如下:

session.getAttribute(String name);

【示例程序】 session中属性的保存与获取

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%

  session.setAttribute("information","向session中保存数据");

  response.sendRedirect("forward.jsp");

%>

forward.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<% out.print(session.getAttribute("information"));%>

可以使用session对象的removeAttribute()方法将指定名称的对象移除,也就是说,从这个会话删除与指定名称绑定的对象。

session.removeAttribute (String name);

参数: name为session对象的属性名

【示例程序】 删除session对象中的属性

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%

    session.setAttribute("information","向session中保存数据");

    response.sendRedirect("forward.jsp");

%>

forward.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%

    session.removeAttribute("information");

    if (session.getAttribute("information") == null) {

        out.print("session对象information已经不存在了");

    }else{

        out.print(session.getAttribute("information"));

    }

%>

session内置对象使用invalidate()方法将会话中的全部内容删除,使会话失效。

session.invalidate();

获取session中的所有属性名称:

Enumeration<String> getAttributeNames()

获取session ID,session ID是唯一标识该会话的一个标识性字符串:

String getId()

会话超时的管理

session对象用于管理会话生命周期的方法主要有:

· 

返回客户端最后一次发送与这个会话相关联的请求时间

· 

long getLastAccessedTime()

· 

· 

设置最大不活动时间间隔

· 

void setMaxInactiveInterval(int interval)

· 

· 

以秒为单位返回一个会话内两个请求的最大时间间隔,Servlet容器在客户访问期间保存这个会话处于打开状态

· 

int getMaxInactiveInterval()

· 

· 

· 

 

· 

【示例程序】 简单的购物程序(session.rar(下载附件 1.51 KB))、稍微复杂的购物程序(session2.rar(下载附件 1.69 KB)

· 

 

application对象


application对象提供了对应用程序环境属性的访问。Tomcat使用了web.xml文件指定程序的初始化参数,它位于应用程序环境目录下的WEB-INF子目录中。

访问应用程序初始化参数的方法有:

· 

返回一个已命名的初始化参数的值

· 

String getInitParameter(String name)

· 

· 

返回所有已定义的应用程序初始化参数名称的枚举

· 

Enumeration<String> getInitParameterNames()

· 

【示例程序】 获取web.xml中的初始化参数

index.jsp

<%

    java.util.Enumeration enema=application.getInitParameterNames();

    while(enema.hasMoreElements()){

    String name=(String)enema.nextElement();

    String value=application.getInitParameter(name);

    out.println(name+",");

    out.println(value);

    out.print("<br>");

}

%>

可以在application对象中设置属性。在application对象中设置的属性在整个应用程序范围内是有效的,即使所有的用户都不发送请求,只要不关闭应用服务器,在其中设置的属性仍然是有效的。

application对象管理应用程序环境属性的方法如下表所示:

【示例程序】 通过application对象中的setAttribute()和getAttribute()方法实现网页计数器。

index.jsp

<% 

    int number=0;

    if(application.getAttribute("number")==null){

        number=1;

    }else{

        number=Integer.parseInt((String)application.getAttribute("number"));

        number=number+1;

    }

    out.print("您是第"+number+"位访问者!");

    application.setAttribute("number",String.valueOf(number));

%>

 

 

out对象

管理响应缓冲

在JSP页面中,可以通过out对象调用clear()方法清除缓冲区的内容。这类似于重置响应流,以便重新开始操作。如果响应已经提交,则会有产生IOException异常的副作用。

另一种方法clearBuffer()清除缓冲区的“当前”内容,而且即使内容已经提交给客户端,也能够访问该方法。

out对象用于管理响应缓冲区的方法如下:

向客户端输出数据

out对象的另外一个很重要的功能就是向客户写入内容。

<%=out.println("同一世界,同一梦想")%>

这句代码用于在页面中输出“同一世界,同一梦想”

 

 

pageContext对象


pageContext对象是一个比较特殊的对象。它相当于页面中所有其他对象功能的最大集成者,使用它可以访问到本页中所有其他对象。

pageContext对象被封装成javax.servlet.jsp.pageContext接口,主要用于管理对属于JSP中特殊可见部分中已经命名对象的访问,它的创建和初始化都是由容器来完成。

JSP页面里可以直接使用pageContext对象的句柄,pageContext对象的getXxx()setXxx()findXxx()方法可以用来根据不同的对象范围实现对这些对象的管理。

pageContext对象的常用方法如下:

pageContext对象在实际JSP开发过程中很少使用,因为requestresponse等对象可以直接调用方法进行使用,如果通过pageContext来调用其他对象有些麻烦。

 

 

config对象

config对象被封装成javax.servlet.ServletConfig接口,它表示Servlet的配置,当一个Servlet初始化时,容器把某些信息通过此对象传递给这个Servlet

开发者可以在web.xml文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。

config对象的常用方法如下表:

 

 

page对象


page对象是为了执行当前页面应答请求而设置的Servlet类的实体,即显示JSP页面自身,只有在JSP页面内才是合法的。page隐含对象本质上包含当前Servlet接口引用的变量,可以看作是this变量的别名,因此该对象对于开发JSP比较有用。

page对象比较常用的方法见下表:

 

 

exception对象


exception内置对象用来处理JSP文件执行时发生的所有错误和异常。

如果在JSP页面中出现没有捕捉异常,就会生成exception对象,并把这个exception对象传送到在page指令中设定的错误页面中,然后在错误提示页面中处理相应的exception对象。

exception对象只有在错误页面(在页面指令里有isErrorPage=true的页面)才可以使用。

exception对象比较常用的方法如下表所示:

【示例程序】 通过exception异常对象将系统出现的异常转向到其他页面

index.jsp

<%@ page contentType="text/html; charset=gb2312" errorPage="error.jsp" %>

<%

    int a=100;

    int b=0;

    out.println("结果="+(a/b));

%>

error.jsp

<%@ page contentType="text/html; charset=gb2312"  isErrorPage="true" %>

错误提示为:<%=exception.getMessage()%>

 

 

JavaBean

JavaBean是利用Java语言编写的组件,每个JavaBean都实现了一个特定的功能。它好比一个封装好的容器,使用者不知其内部是如何实现 通过合理地组织不同功能的JavaBean,可以快速生成一个全新的应用程序。

使用JavaBean的最大优点是提高代码的重用性,宗旨是“一次性编写,任何地方执行,任何地方重用”,通过使用JavaBean可以将复杂需求分解成简单功能模块,模块相对独立,可以继承、重用。

JavaBean按功能可分为可视化JavaBean和不可视化JavaBean。

(1)可视化JavaBean

可视化JavaBean具有GUI图形用户界面;

不可视JavaBean就是没有GUI图形用户界面,最终对用户是不可见的,更多应用于JSP中。

(2)不可视JavaBean

不可视JavaBean又分为值JavaBean和工具JavaBean。

· 

值JavaBean

· 

值JavaBean严格遵循了JavaBean的命名规范,通常用来封装表单数据,作为信息的容器。

【示例程序】 值JavaBean

package myweb;

 

public class UserInfo {

    private String name;

    private String password;

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getPassword() {

        return password;

    }

    public void setPassword(String password) {

        this.password = password;

    }   

}

· 

工具JavaBean

· 

工具JavaBean则可以不遵循JavaBean规范,通常用于封装业务逻辑,数据操作等,例如连接数据库,对数据库进行增、删、改、查和解决中文乱码等操作。

工具JavaBean可以实现业务逻辑与页面显示的分离,提高了代码的可读性与易维护性。

【示例程序】

public class MyTools {

    public String change(String source){

        source=source.replace("<", "<");

        source=source.replace(">", ">");

        return source;      

    }

}

 

JavaBean规范

通常一个标准的JavaBean需遵循以下规范:

(1)实现java.io.Serializable接口;

(2)是一个公共类;

(3)类中必须存在一个无参数的构造函数;

(4)提供对应的setXxx()和getXxx()方法来存取类中的属性,方法中的“Xxx”为属性名称,属性的第一个字母应大写。若属性为布尔类型,则可使用isXxx()方法代替getXxx()方法。

实现java.io.Serializable接口的类实例化的对象被JVM(Java虚拟机)转化为一个字节序列,并且能够将这个字节序列完全恢复为原来的对象,序列化机制可以弥补网络传输中不同操作系统的差异问题。

【示例程序】

package myweb;

import java.io.Serializable;

public class SimpleJavaBean implements Serializable {

    public SimpleJavaBean(){}

    private String name;

    private String password;

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getPassword() {

        return password;

    }

    public void setPassword(String password) {

        this.password = password;

    }

}

 

 

JavaBean中的属性

通常JavaBean中的属性分为以下4种:

(1)简单属性(Simple)

(2)索引属性(Indexed)

(3)绑定属性(Bound)

(4)约束属性(Constrained)

简单属性(Simple)

简单属性就是在JavaBean中对应了简单的setXxx()getXxx()方法的变量;若属性为布尔类型,则可使用isXXX()方法代替getXxx()方法。

public class Person{

    private String name;

    private boolean married;

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public boolean isMarried() {

        return married;

    }

    public void setMarried(boolean married) {

        this.married = married;

    }

}

索引属性(Indexed)

需要通过索引访问的属性通常称为索引属性。索引属性的getXxx()setXxx()方法如下:

public void setXxx(type[] value);

public type[] getXxx();

public void setXxx(int index, type value);

public type getXxx(int index);

【示例程序】

public class Demo{    

    private String[] select;

 

    public String[] getSelect() {

        return select;

    }

    public String getSelect(int index){

        return select[index];

    }

    public void setSelect(String[] select) {

        this.select = select;

    }

    public void setSelect(int index, String s){

        select[index] = s;

    }    

}

绑定属性(Bound)

也称为束缚属性(Bound),当该类型属性的值发生变化时,要通知其它对象。每次属性值改变时,该属性就会触发一个PropertyChange事件。事件中封装了属性名、属性的原值、属性变化后的新值,这种事件被传递到其它的Bean对象,接收事件的Bean对象应做什么动作由其自己定义。

Bean类需要提供addPropertyChangeListener()removePropertyChangeListener()方法来管理bean类的监听器。 当绑定属性发生改变是,bean对象将向已注册的监听器发送PropertyChangeEvent事件。

PropertyChangeEventPropertyChangeListenerjava.beans包中定义。 java.beans包中还定义了一个类PropertyChangeSupport,可完成绑定属性的大多数功能。该类可以保持对属性监听器进行跟踪并提供了方便使用的方法,这些方法触发属性改变事件并发送给所有已注册的监听器。

【示例程序】使用PropertyChangeSupport定义bound属性

package myjavaprj;

 

import java.beans.PropertyChangeEvent;

import java.beans.PropertyChangeListener;

import java.beans.PropertyChangeSupport;

 

public class FaceBean {

    private int mouthWidth = 90;

    private PropertyChangeSupport mPcs = new PropertyChangeSupport(this);

 

    public int getMouthWidth() {

        return mouthWidth;

    }

    public void setMouthWidth(int mw) {

        int oldMouthWidth = mouthWidth;

        mouthWidth = mw;

        mPcs.firePropertyChange("mouthWidth", oldMouthWidth, mw);

    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {

        mPcs.addPropertyChangeListener(listener);

    }

    public void removePropertyChangeListener(PropertyChangeListener listener){

        mPcs.removePropertyChangeListener(listener);

    }

    

    public static void main(String[] args){

     FaceBean fb=new FaceBean();

     fb.addPropertyChangeListener(new MyListener());

     fb.setMouthWidth(90);

     fb.setMouthWidth(60);

    }

}

 

class MyListener implements PropertyChangeListener {  

 

        @Override  

        public void propertyChange(PropertyChangeEvent evt) {  

            System.out.println(evt.getOldValue() + "->" + evt.getNewValue());  

        }  

  

}

约束属性(Constrained)

JavaBean的constrained属性是一种特殊的绑定属性。对于约束,bean对象将一直跟踪一组否决监听器(veto listeners)。当约束属性要发生变化时,将咨询veto监听器。任何一个否决监听器都可以否决这一变化,使属性值保持不变。constrained属性的监听者通过抛出PropertyVetoException来阻止该属性值的改变。

java.beans中定义的VetoableChangeSupport类大大简化了约束属性的使用。

【示例程序】

package javabean;

import java.beans.PropertyChangeEvent;

import java.beans.PropertyChangeListener;

import java.beans.PropertyChangeSupport;

import java.beans.PropertyVetoException;

import java.beans.VetoableChangeListener;

import java.beans.VetoableChangeSupport;

 

public class FaceBean {

    private int mouthWidth = 90;

    private PropertyChangeSupport mPcs = new PropertyChangeSupport(this);

    private VetoableChangeSupport mVcs = new VetoableChangeSupport(this);

 

    public int getMouthWidth() {

        return mouthWidth;

    }

 

    public void setMouthWidth(int mw) throws PropertyVetoException {

        int oldMouthWidth = mouthWidth;

        if(mw>100||mw<10){

         mVcs.fireVetoableChange("mouthWidth", oldMouthWidth, mw);

        }

         mouthWidth = mw;

            mPcs.firePropertyChange("mouthWidth", oldMouthWidth, mw);

    }

 

    public void addPropertyChangeListener(PropertyChangeListener listener) {

        mPcs.addPropertyChangeListener(listener);

    }

 

    public void removePropertyChangeListener(PropertyChangeListener listener) {

        mPcs.removePropertyChangeListener(listener);

    }

 

    public void addVetoableChangeListener(VetoableChangeListener listener) {

        mVcs.addVetoableChangeListener(listener);

    }

 

    public void removeVetoableChangeListener(VetoableChangeListener listener) {

        mVcs.removeVetoableChangeListener(listener);

    }

    

    public static void main(String[] args){

     FaceBean fb=new FaceBean();

     fb.addPropertyChangeListener(new MyListener());

     fb.addVetoableChangeListener(new MyVetoListener());

     try {

fb.setMouthWidth(90);

     fb.setMouthWidth(60);

     fb.setMouthWidth(120);

} catch (PropertyVetoException e) {

//e.printStackTrace();

}

    

     System.out.println(fb.getMouthWidth());

 

    }

}

 

class MyListener implements PropertyChangeListener {  

 

    @Override  

    public void propertyChange(PropertyChangeEvent evt) {  

        System.out.println("In propertyChange(): "+ evt.getOldValue() + "->" + evt.getNewValue());  

    }  

 

 

class MyVetoListener implements VetoableChangeListener{

 

@Override

public void vetoableChange(PropertyChangeEvent pce)

throws PropertyVetoException {

System.out.println("In vetoableChange(): "+pce.getPropertyName()+" old:"

+pce.getOldValue()+"->new:"+pce.getNewValue());

throw new PropertyVetoException("Value cannot be changed.",pce);

}

}

 

 

JavaBean的使用


<jsp:useBean>

<jsp:useBean>动作标识可以在JSP页面中创建一个Bean实例,并且通过属性的设置可以将该实例存储到JSP中的指定作用域。如果在指定的作用域内已经存在了指定的Bean实例,那么将使用这个实例,而不会重新创建。通过<jsp:useBean>标识创建的Bean实例可以在Scriptlet中应用。

基本语法格式如下:

<jsp:useBean 

    id="变量名" 

 scope="page|request|session|application"

 {

    class="package.className"|

  type="数据类型"|

  class="package.className" type="数据类型"|

  beanName="package.className" type="数据类型"

 }

/>

<jsp:setProperty name="变量名" property="*"/>

也可以在标识体内嵌入子标识或其他内容:

<jsp:useBean id="变量名" scope="page|request|session|application" …>

    <jsp:setProperty name="变量名" property="*"/>

</jsp:useBean>

这两种使用方法是有区别的。在页面中应用<jsp:useBean>标识创建一个Bean时,如果该Bean是第一次被实例化,那么对于<jsp:useBean>标识的第二种使用格式,标识体内的内容会被执行,若已经存在了指定的Bean实例,则标识体内的内容就不再被执行了。而对于第一种使用格式,无论在指定的范围内是否已经存在一个指定的Bean实例,<jsp:useBean>标识后面的内容都会被执行。

<jsp:useBean>标识中各属性:

id属性:该属性指定一个变量,在所定义的范围内或脚本中将使用该变量来对所创建的Bean实例进行引用。该变量必须符合Java中变量的命名规则。

type属性:用于设置由id属性指定的变量的类型。type属性可以指定要创建实例的类的本身、类的父类或者是一个接口。

使用type属性来设置变量类型的使用格式如下:

<jsp:useBean id="us" type="com.Bean.UserInfo" scope="session"/>

如果在session范围内,已经存在了名为“us”的实例,则将该实例转换为type属性指定的UserInfo类型(必须是合法的类型转换)并赋值给id属性指定的变量;若指定的实例不存在将抛出“bean us not found within scope”异常。 scope属性:该属性指定了所创建Bean实例的存取范围,省略该属性时的值为page。<jsp:useBean>标识被执行时,首先会在scope属性指定的范围来查找指定的Bean实例,如果该实例已经存在,则引用这个Bean,否则重新创建,并将其存储在 scope属性指定的范围内。scope属性具有的可选值如下。

· 

page:指定了所创建的Bean实例只能够在当前的JSP文件中使用,包括在通过include指令静态包含的页面中有效。

· 

· 

request:指定了所创建的Bean实例可以在请求范围内进行存取。在请求被转发至的目标页面中可通过request对象的getAttribute("id属性值")方法获取创建的Bean实例。一个请求的生命周期是从客户端向服务器发出一个请求到服务器响应这个请求给用户后结束,所以请求结束后,存储在其中的Bean的实例也就失效了。

· 

· 

session:指定了所创建的Bean实例的有效范围为session。session是当用户访问Web应用时,服务器为用户创建的一个对象,服务器通过session的ID值来区分其他的用户。针对某一个用户而言,在该范围中的对象可被多个页面共享。

· 

· 

application:该值指定了所创建的Bean实例的有效范围从服务器启动开始到服务器关闭结束。application对象是在服务器启动时创建的,它被多个用户共享。所以访问该application对象的所有用户共享存储于该对象中的Bean实例。可以使用application对象的getAttribute("id属性值")方法获取存在于application中的Bean实例。

· 

class属性:指定了一个完整的类名,其中package表示类包的名字,className表示类的Class文件名称。通过class属性指定的类不能是抽象的,它必须具有公共的、没有参数的构造方法。在没有设置type属性时,必须设置class属性。格式如下:

<jsp:useBean id="us" class="com.Bean.UserInfo" scope="session"/>

在<jsp:useBean>标识中class属性与type属性一起使用时格式如下:

<jsp:useBean id="us" class="com.Bean.UserInfo" type="com.Bean.UserBase" scope="session"/>

这里假设UserBase类为UserInfo类的父类。该标识被执行时,程序首先创建了一个以type属性的值为类型,以id属性值为名称的变量us,并赋值为null;然后在session范围内来查找这个名为“us”的Bean实例,如果存在,则将其转换为type属性指定的UserBase类型(类型转换必须是合法的)并赋值给变量us;如果实例不存在,那么将通过new操作符来实例化一个UserInfo类的实例并赋值给变量us,最后将us变量储在session范围内。

beanName属性:与type属性可以指定同一个类,在<jsp:useBean>标识中beanName属性与type属性一起使用时的格式如下:

<jsp:useBean id="us" beanName="com.Bean.UserInfo" type="com.Bean.UserBase"/>

这里假设UserBase类为UserInfo类的父类。该标识被执行时,程序首先创建了一个以type属性的值为类型,以id属性值为名称的变量us,并赋值为null;然后在session范围内来查找这个名为“us”的Bean实例,如果存在,则将其转换为type属性指定的UserBase类型(类型转换必须是合法的)并赋值给变量us;如果实例不存在,那么将通过instantiate()方法从UserInfo类中实例化一个类并将其转换成UserBase类型后赋值给变量us,最后将变量us存储在session范围内。

通常情况下应用<jsp:useBean>标识的格式如下:

<jsp:useBean id="变量名" class="package.className"/>

如果想共享这个Bean实例,可根据需要设置scope属性。

<jsp:setProperty>

通常情况下与<jsp:useBean>标识一起使用,它将调用Bean中的setXxx()方法将请求中的参数赋值给由<jsp:useBean>标识创建的JavaBean中对应的简单属性或索引属性。该标识的语法格式如下:

<jsp:setProperty

    name="Bean实例名"

 {

  property="*" |

  property="propertyName" |

  property="propertyName" param="parameterName" |

  property="propertyName" value="值"

 }/>

name属性:用来指定一个存在JSP中某个范围中的Bean实例。<jsp:setProperty>标识将会按照page、request、session和application的顺序来查找这个Bean实例,直到第一个实例被找到。若任何范围内不存在这个Bean实例,则会抛出异常。

property="*":property属性取值为“*”时,则request请求中所有参数的值将被一一赋给Bean中与参数具有相同名字的属性。如果请求中存在值为空的参数,那么Bean中对应的属性将不会被赋值为Null;如果Bean中存在一个属性,但请求中没有与之对应的参数,那么该属性同样不会被赋值为Null。

该使用方法要求请求中参数的名称和类型必须与Bean中属性的名称和类型一致。但由于通过表单传递的参数都是String类型的,所以JSP会自动将这些参数转换为Bean中对应属性的类型。下表给出了JSP自动将String类型转换为其他类型时所调用的方法。

property="propertyName":property属性取值为Bean中的属性时,则只会将request请求中与该Bean属性同名的一个参数的值赋给这个Bean属性。更进一步讲,如果property属性指定的Bean属性为userName,那么指定Bean中必须存在setUserName()方法,否则会抛出类似于下面的异常:

Cannot find any information on property 'userName' in a bean of type 'com.Bean.UserInfo'

在此基础上,如果请求中没有与userName同名的参数,则该Bean属性会保留原来或默认的值,而不会被赋值为Null。当请求中参数的类型与Bean中属性类型不一致时,JSP会自动进行转换。

property="propertyName" param="parameterName"

param属性指定一个request请求中的参数,property属性指定Bean中的某个属性。该种使用方法允许将请求中的参数赋值给Bean中与该参数不同名的属性。如果param属性指定参数的值为空,那么由property属性指定的Bean属性会保留原来或默认的值而不会被赋为null。

property="propertyName" value="值"

value属性指定的值可以是一个字符串数值或表示一个具体值的JSP表达式或EL表达式。该值将被赋给property属性指定的Bean属性。

· 

当value属性指定的是一个字符串时,如果指定的Bean属性与其类型不一致时,则会根据表3-3中的方法将该字符串值自动转换成对应的类型。

· 

· 

当value属性指定的是一个表达式时,那么该表达式所表示的值的类型必须与property属性指定的Bean属性一致,否则会抛出“argument type mismatch”异常。

· 

· 

通常<jsp:setProperty>标识与<jsp:useBean>标识一起使用,但这并不是绝对的,应用如下的方法同样可以将请求中的参数值赋给JavaBean中的属性。

· 

<jsp:getProperty>

<jsp:getProperty>属性用来从指定的Bean中读取指定的属性值,并输出到页面中。该Bean必须具有getXxx()方法。<jsp:getProperty>的语法格式如下:

<jsp:getProperty name="Bean实例名" property="propertyName"/>

name属性:name属性用来指定一个存在某JSP范围中的Bean实例。<jsp:getProperty>标识将会按照page、request、session和application的顺序来查找这个Bean实例,直到第一个实例被找到。若任何范围内不存在这个Bean实例则会抛出“Attempted a bean operation on a null object”异常。

property属性:该属性指定了要获取Bean中哪个属性的值。若它指定的值为“userName”,那么Bean中必须存在getUserName()方法,否则会抛出下面的异常:

Cannot find any information on property 'userName' in a bean of type '此处为类名'

如果指定Bean中的属性是一个对象,那么该对象的toString()方法被调用,并输出执行结果。

【示例程序】利用JavaBean获取表单中的数据javabean.rar(下载附件 1.86 KB)

form.jsp: 表单页面

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@ page import="java.net.URLEncoder"%>

<html>

<head>

<title>Insert title here</title>

</head>

<body>

    <form method="post" action="deal.jsp">

        姓名:<input type="text" name="username"><br> 密码:<input

            type="password" name="pwd"><br> 年龄:<input type="text"

            name="age"><br> 爱好:<input type="checkbox" name="hobby"

            value="睡觉">睡觉 <input type="checkbox" name="hobby" value="打游戏">打游戏

        <input type="checkbox" name="hobby" value="玩手机">玩手机 <input

            type="checkbox" name="hobby" value="跳楼">跳楼 <input

            type="submit" value="保存">

    </form>

</body>

</html>

UserBean.java:Bean类

package myweb.bean;

 

import java.io.Serializable;

 

public class UserBean implements Serializable {

    private String username;

    private String pwd;

    private int age;

    private String[] hobby;

    public String getUsername() {

        return username;

    }

    public void setUsername(String username) {

        this.username = username;

    }

    public String getPwd() {

        return pwd;

    }

    public void setPwd(String pwd) {

        this.pwd = pwd;

    }

    public String[] getHobby() {

        return hobby;

    }

    public void setHobby(String[] hobby) {

        this.hobby = hobby;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

 

}

deal.jsp:获取表单数据

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="myweb.bean.UserBean"%>

<%

    request.setCharacterEncoding("UTF-8");

%>

<jsp:useBean id="user" class="myweb.bean.UserBean" scope="session">

    <jsp:setProperty name="user" property="*"></jsp:setProperty>

</jsp:useBean>        

UserName: <jsp:getProperty name="user" property="username" /><br>

Password: <jsp:getProperty name="user" property="pwd" /><br>

Age: <jsp:getProperty name="user" property="age" /><br>

 

<%

    String[] hobby=user.getHobby();

    for(String s:hobby){

        out.println(s+" ");

    }

%>

<a href="another.jsp?username=lisi&password=88888">Another.jsp</a><br>

<a href="another.jsp">Another.jsp</a>

another.jsp: 参数传递

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="myweb.bean.UserBean"%>

 

<jsp:useBean id="user" class="myweb.bean.UserBean" scope="session">

</jsp:useBean>

<jsp:setProperty name="user" property="*"></jsp:setProperty>

 

<jsp:setProperty name="user" property="pwd" param="password"></jsp:setProperty>

 

<jsp:getProperty name="user" property="username" />

<%

 

   out.println(user.getUsername());

%>

 

<jsp:getProperty name="user" property="pwd" />

 

<%

    String[] hobby=user.getHobby();

    for(String s:hobby){

        out.println(s+" ");

    }

%>

 

 

简介

Servlet是一种独立于平台和协议的服务器端的Java技术,主要用于处理客户端传来的Http请求,并返回一个响应,生成动态的Web页面。

开发Servlet时,可直接继承javax.servlet.http.HttpServlet,并需要在web.xml中(或使用注解)进行描述。

Servlet的功能涉及范围很广,主要功能如下:

(1)创建并返回包含客户请求的动态内容的完整HTML页面;

(2)创建可嵌入到现有HTML页面中的HTML片段;

(3)与其他服务器资源进行通信;

(4)接收多个客户机的输入,并将结果传递到多个客户机上;

Servlet技术具有以下特点:高效、方便、跨平台、功能强大、灵活且可扩展、共享数据、安全

Servlet的生命周期

 

图1  Servlet的生命周期

Servlet部署在容器里,其生命周期由容器管理。Servlet的生命周期概括为以下几个阶段:

(1)容器加载Servlet类。

当第一次有Web客户请求Servlet服务或当Web服务启动时。

(2)创建Servlet对象实例。

容器环境根据客户请求,创建一个或多个Servlet对象实例,并把这些实例加入到Servlet实例池中。

(3)Servlet初始化。

容器环境调用Servlet的初始化方法init()进行初始化,并传入一个包含初始化参数和容器环境信息的ServletConfig对象,向Servlet传递数据,若传递失败,则产生ServletException异常,Servlet将不能正常工作。

(4)容器生成请求和响应对象。

容器利用HttpServletRequestHttpServletResponse对象,封装从Web客户接收到的HTTP请求和由Servlet生成的响应。

(5)调用service方法提供服务。

容器调用HttpServlet.service()方法提供服务,并将请求和响应对象传递给该方法。service()方法可被多次调用,各调用过程运行在不同的线程中,互不干扰。 从请求对象读取HTTP请求数据,通过session对象访问状态信息,并用HttpServletResponse对象生成HTTP响应数据。

(6)注销Servlet。

当Web服务器和容器关闭时,会自动调用HttpServlet.destroy()方法关闭所有打开的资源,并进行一些关闭前的处理。

 

 

Servlet API-常用接口与类

Servlet接口

javax.servlet.Servlet是所有Java Servlet的基础接口,是封装了建立接收请求和产生响应功能的组件(即Servlet)。

HttpServlet类

HttpServlet类定义在javax.servlet.http包内,是针对使用HTTP协议的Web服务器的Servlet类。

ServletConfig接口

ServletConfig接口存放在javax.servlet包内,它是一个由Servlet容器使用的Servlet配置对象,用于在Servlet初始化时向它传递信息。

HttpServletRequest接口

HttpServletRequest接口定义在javax.servlet.http包内,代表客户端请求。

HttpServletResponse接口

定义在javax.servlet.http包内,代表对客户端的HTTP响应。

 

 

IDE中创建和配置Servlet

Servlet的创建、配置与使用

Eclipse中创建Servlet

第1步:设置类名和包名

第2步:设置描述符名称及URL映射

第3步:设置需要实现的方法

第4步:在构建路径中添加servlet-api.jar

MyEclipse中创建Servlet

第1步:设置类名、包名和要实现的方法

第2步:设置部署描述符中的URL等属性

 

 

Servlet的编写、部署

创建Servlet类:

package com.myservlet;

 

import java.io.IOException;

import java.io.PrintWriter;

 

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

@WebServlet(description = "infoProcess", urlPatterns = { "/info" })    

public class ProcessServlet extends HttpServlet {   

    protected void doPost(HttpServletRequest request, HttpServletResponse response) 

    throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");

        response.setContentType("text/html;charset=UTF-8");

        String name=request.getParameter("name");

        String age=request.getParameter("age");

    }

}

这里采用注解的方式配置Servlet:@WebServlet(description = "infoProcess", urlPatterns = { "/info" })

目录结构:

使用部署描述文件(DD)在web.xml中配置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>InfoServlet</servlet-name>

    <servlet-class>firstPrj.InfoServlet</servlet-class>

  </servlet>

 

  <servlet-mapping>

    <servlet-name>InfoServlet</servlet-name>

    <url-pattern>/servlet/info</url-pattern>

  </servlet-mapping>

如果要对一个JSP页面文件进行配置,则可通过下面的代码进行指定:

<servlet>

    <description>Simple Servlet</description>

    <display-name>Servlet</display-name>

    <servlet-name>Login</servlet-name>

    <jsp-file>login.jsp</jsp-file>

</servlet>

配置Servlet初始化参数

 <servlet>

    <servlet-name>InfoServlet</servlet-name>

    <servlet-class>firstPrj.InfoServlet</servlet-class>

    <init-param>

        <param-name>number</param-name>

        <param-value>1000</param-value>

    </init-param>

 </servlet>

在Servlet中可以在init方法中通过getInitParameter()方法访问这些参数:

public void init() throws ServletException {

   String n=this.getInitParameter("number");

}

启动加载优先权

通过<load-on-startup>元素指定启动加载优先权。

<servlet>

    <servlet-name>ServletONE</servlet-name>

    <servlet-class>com.ServletONE</servlet-class>

    <load-on-startup>10</load-on-startup>

</servlet>

<servlet>

    <servlet-name>ServletTWO</servlet-name>

    <servlet-class>com.ServletTWO</servlet-class>

    <load-on-startup>20</load-on-startup>

</servlet>

<servlet>

    <servlet-name>ServletTHREE</servlet-name>

    <servlet-class>com.ServletTHREE</servlet-class>

    <load-on-startup>AnyTime</load-on-startup>

</servlet>

在这段代码中,ServletONE类先被载入,ServletTWO类则后被载入,而ServletTHREE类可在任何时间内被载入。

Servlet的映射

在web.xml配置文件中可以给一个Servlet做多个映射,因此,可以通过不同的方法访问这个Servlet:

<servlet-mapping>

    <servlet-name>OneServlet</servlet-name>

    <url-pattern>/One</url-pattern>

</servlet-mapping>

通过上述代码的配置,若请求的路径中包含“/One”,则会访问逻辑名为“OneServlet”的Servlet。

<servlet-mapping>

    <servlet-name>OneServlet</servlet-name>

    <url-pattern>/Two/*</url-pattern>

</servlet-mapping>

通过上述配置,若请求的路径中包含“/Two/a”或“/Two/b”等符合“/Two/*”的模式,则同样会访问逻辑名为“OneServlet”的Servlet。

采用注解配置Servlet

采用注解配置Servlet的基本语法如下。

import javax.servlet.annotation.WebServlet;

 

@WebServlet(urlPatterns = {"/映射地址"}, asyncSupported = true|false, 

loadOnStartup = -1, name = "Servlet名称", displayName = "显示名称", 

initParams = {@WebInitParam(name = "username", value = "值")} 

)

在上面的语法中,urlPatterns属性用于指定映射地址;asyncSupported属性用于指定是否支持异步操作模式;loadOnStartup属性用于指定Servlet的加载顺序;name属性用于指定 Servlet 的name属性;displayName属性用于指定该Servlet的显示名;initParams属性用于指定一组 Servlet 初始化参数。

 

 

MVC是指模型(Model)、视图(View)和控制(Controller),目的是实现Web系统的职能分工。Model层实现系统中的业务逻辑,通常可用JavaBean或EJB实现。View层用于与用户的交互,通常用JSP来实现。Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作,通常用Servlet来实现。

· 

 

· 

· 

图1 MVC设计模式示意图

· 

使用MVC的好处:

· 

各施其职,互不干涉

· 

在MVC模式中,三层各司其职,如果哪一层的需求发生了变化,就只需要更改相应层中的代码而不会影响到其它层。

· 

· 

有利于开发中的分工

· 

在MVC模式中,分层能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的JSP,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。

· 

· 

有利于组件的重用

· 

分层后更有利于组件的重用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。

· 

 

 

 过滤器是一个程序,它先于与之相关的servlet或JSP页面在服务器上运行。过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进入这些资源的请求信息。在这之后,过滤器可以作如下的选择:

· 

以常规的方式调用资源(即,调用servlet或JSP页面)。

· 

· 

利用修改过的请求信息调用资源。

· 

· 

调用资源,但在发送响应到客户机前对其进行修改

· 

· 

阻止该资源调用,代之以转到其他的资源,返回一个特定的状态代码或生成替换输出。

· 

它以一种模块化的或可重用的方式封装公共的行为。

你有30个不同的serlvet或JSP页面,需要压缩它们的内容以减少下载时间吗?

利用它能够将高级访问决策与表现代码相分离。

例如,希望阻塞来自某些站点的访问而不用修改各页面。

过滤器使你能够对许多不同的资源进行批量性的更改。

有许多现存资源,这些资源除了公司名要更改外其他的保持不变,能办到么?没问题:构造一个串替换过滤器。

Filter接口

一个过滤器就是一个Java类,它实现了javax.servlet.Filter接口。javax.servlet.Filter接口定义了三个方法:

创建过滤器

1. 

定义一个实现Filter接口的类。

2. 

这个类需要三个方法,分别是:doFilterinitdestroydoFilter方法包含主要的过滤代码,init方法建立设置操作,而destroy方法进行清除。 ``

3. 

4. 

doFilter方法中放入过滤行为。

5. 

doFilter方法的第一个参数为ServletRequest对象。此对象给过滤器提供了对进入的信息(包括 表单数据、cookie和HTTP请求头)的完全访问。第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。最后一个参数为 FilterChain,如下所述,此参数用来调用servlet或JSP页。

6. 

7. 

调用FilterChain对象的doFilter方法。

8. 

Filter接口的doFilter方法取一个FilterChain对象作为它的一个参数。在调用此对象的doFilter方法时,激活下一个相关的过滤器。如果没有另一个过滤器与servlet或JSP页面关联,则servlet或JSP页面被激活。

9. 

10. 

注册过滤器。

11. 

在部署描述符文件(web.xml)中使用<filter><filter-mapping>元素注册过滤器。

12. 

过滤器的配置

(1)web.xml文件中进行配置

【例1】

<filter>

    <filter-name>Set Character Encoding</filter-name>

    <filter-class>SetCharacterEncodingFilter</filter-class>

</filter>

<filter-mapping>

    <filter-name>Set Character Encoding</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

【例2】

<filter>

    <filter-name>LogFilter</filter-name>

    <filter-class>LogFilter</filter-class>

    <init-param>

    <param-name>test-param</param-name>

    <param-value>Initialization Paramter</param-value>

    </init-param>

</filter>

<filter-mapping>

   <filter-name>LogFilter</filter-name>

   <url-pattern>/*</url-pattern>

</filter-mapping>

【例3】

<filter>

   <filter-name>LogFilter</filter-name>

   <filter-class>LogFilter</filter-class>

   <init-param>

      <param-name>test-param</param-name>

      <param-value>Initialization Paramter</param-value>

   </init-param>

</filter>

 

<filter>

   <filter-name>AuthenFilter</filter-name>

   <filter-class>AuthenFilter</filter-class>

   <init-param>

      <param-name>test-param</param-name>

      <param-value>Initialization Paramter</param-value>

   </init-param>

</filter>

 

<filter-mapping>

   <filter-name>LogFilter</filter-name>

   <url-pattern>/*</url-pattern>

</filter-mapping>

 

<filter-mapping>

   <filter-name>AuthenFilter</filter-name>

   <url-pattern>/*</url-pattern>

</filter-mapping>

(2)使用注解进行配置

@WebFilter(urlPatterns={"/a.jsp","/b.jsp"},

initParams={@WebInitParam(name="default_market",  value="NASDAQ"),

@WebInitParam(name="coding",  value="UTF-8")})

 

public class Logging implements Filter {

    //…

【示例程序】 字符编码过滤器

package com.myweb.filter;

 

import java.io.IOException;

 

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.annotation.WebFilter;

import javax.servlet.annotation.WebInitParam;

 

/**

 * Servlet Filter implementation class EncodingFilter

 */

@WebFilter(urlPatterns = {"/*","/form/*","/abc/*"}, initParams = {

        @WebInitParam(name = "encode", value = "UTF-8"),

        @WebInitParam(name = "ignore", value = "false") })

public class EncodingFilter implements Filter {

 

    private String encode;

    private boolean ignore = false; // 过滤器开关

 

    /**

     * Default constructor.

     */

    public EncodingFilter() {

        // TODO Auto-generated constructor stub

    }

 

    /**

     * @see Filter#destroy()

     */

 

    public void destroy() {

        encode = null;

        ignore = false;

    }

 

    /**

     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)

     */

    public void doFilter(ServletRequest request, ServletResponse response,

            FilterChain chain) throws IOException, ServletException {

        // TODO Auto-generated method stub

        // place your code here

        if (!ignore) {

            if (null == request.getCharacterEncoding()) {

                request.setCharacterEncoding(encode);

                System.out.println("setting encode: "+encode);

            }

        }

        // pass the request along the filter chain

 

        chain.doFilter(request, response);

 

    }

 

    /**

     * @see Filter#init(FilterConfig)

     */

    public void init(FilterConfig fConfig) throws ServletException {

        // TODO Auto-generated method stub

        String encode = fConfig.getInitParameter("encode");

        String ignore = fConfig.getInitParameter("ignore");

        if (this.encode == null&&encode!=null){

            this.encode = encode;

        }else{

            this.encode="UTF-8";

        }

        if ("1".equals(ignore) || "yes".equals(ignore)) {

            this.ignore = true;

        }

 

    }

 

}

【示例程序】 登录过滤器

package com.myweb.filter;

 

import java.io.IOException;

 

import javax.servlet.DispatcherType;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.annotation.WebFilter;

import javax.servlet.annotation.WebInitParam;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

 

/**

 * Servlet Filter implementation class LoginFilter

 */

@WebFilter(

        urlPatterns = "/form/process.jsp", 

        initParams = { 

                @WebInitParam(name = "redirectURL", value = "/index.jsp"),

        })

public class LoginFilter implements Filter {

    String redirectURL;

 

/**

 * Default constructor. 

 */

public LoginFilter() {

// TODO Auto-generated constructor stub

}

 

    /**

     * @see Filter#destroy()

     */

    public void destroy() {

        // TODO Auto-generated method stub

    }

 

    /**

     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)

     */

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        // TODO Auto-generated method stub

        // place your code here

        System.out.println("登录过滤器");

        HttpServletRequest res=(HttpServletRequest) request;

        HttpServletResponse resp=(HttpServletResponse)response;

        HttpSession session=res.getSession();

        String url=res.getContextPath()+redirectURL;

        System.out.println("url:"+url);

        Object logined=session.getAttribute("isLogined");

        if(null==logined||!"yes".equals((String)logined)){

            resp.sendRedirect(url);

            return;

        }

 

 

        // pass the request along the filter chain

        chain.doFilter(request, response);

    }

 

    /**

     * @see Filter#init(FilterConfig)

     */

    public void init(FilterConfig fConfig) throws ServletException {

        // TODO Auto-generated method stub

        String url = fConfig.getInitParameter("redirectURL");

        if(null!=url&&!"".equals(url.trim())){

            redirectURL=url;

        }else{

            redirectURL="/index.jsp";

        }

    }

 

}

 

 

 

 

      Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。

可以监听客户端的请求、服务端的操作,监听许多信息的初始化,销毁,增加,修改,删除值等。通过监听器,可以自动激发一些操作,比如:监听在线用户数量,当增加一个HttpSession时,给在线人数加1。

监听器的类型

按监听的对象划分:servlet2.4规范定义的事件有三种:

1. 

用于监听应用程序环境对象(ServletContext)的事件监听器

2. 

3. 

用于监听用户会话对象(HttpSession)的事件监听器

4. 

5. 

用于监听请求消息对象(ServletRequest)的事件监听器

6. 

按监听的事件类型划分

1. 

用于监听域对象自身的创建和销毁的事件监听器

2. 

3. 

用于监听域对象中的属性的增加和删除的事件监听器

4. 

5. 

用于监听绑定到HttpSession域中的某个对象的状态的事件监听器

6. 

监听器接口

实现对应的接口就可以实现对应的监听处理:

1. ServletContextListener:用于监听WEB 应用启动和销毁的事件,监听器类需要实现javax.servlet.ServletContextListener 接口。

2. ServletContextAttributeListener:用于监听WEB应用属性改变的事件,包括:增加属性、删除属性、修改属性,监听器类需要实现javax.servlet.ServletContextAttributeListener接口。

3. HttpSessionListener:用于监听Session对象的创建和销毁,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。

4. HttpSessionActivationListener:用于监听Session对象的钝化/活化事件,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。

5. HttpSessionAttributeListener:用于监听Session对象属性的改变事件,监听器类需要实现javax.servlet.http.HttpSessionAttributeListener接口。

Eclipse创建监听器

【示例程序】filterProject.rar(下载附件 12.33 KB)

package com.myweb.listener;

 

import javax.servlet.ServletContextAttributeEvent;

import javax.servlet.ServletContextAttributeListener;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

import javax.servlet.annotation.WebListener;

import javax.servlet.http.HttpSessionAttributeListener;

import javax.servlet.http.HttpSessionBindingEvent;

import javax.servlet.http.HttpSessionEvent;

import javax.servlet.http.HttpSessionListener;

 

 

@WebListener

public class ContextListener implements ServletContextListener, ServletContextAttributeListener, HttpSessionListener, HttpSessionAttributeListener {

 

/**

 * Default constructor. 

 */

public ContextListener() {

// TODO Auto-generated constructor stub

}

 

public void sessionCreated(HttpSessionEvent arg0)  { 

    System.out.println("A new session has been created,ID = "+arg0.getSession().getId());

 

}

 

public void attributeAdded(ServletContextAttributeEvent arg0)  { 

    System.out.println("A new attribute is added to the ServletContext,name: "+arg0.getName()+" value: "+arg0.getValue());

}

 

 

public void attributeRemoved(ServletContextAttributeEvent arg0)  { 

    System.out.println("A new attribute was removed from the ServletContext,name: "+arg0.getName());

}

 

public void sessionDestroyed(HttpSessionEvent arg0)  { 

 

}

 

public void contextDestroyed(ServletContextEvent arg0)  { 

 // TODO Auto-generated method stub

}

 

public void attributeAdded(HttpSessionBindingEvent arg0)  { 

    System.out.println("A new attribute is added to the Session,name: "+arg0.getName());

}

 

 public void attributeRemoved(HttpSessionBindingEvent arg0)  { 

    System.out.println("A new attribute is removed from the Session,name: "+arg0.getName());

}

 

public void attributeReplaced(HttpSessionBindingEvent arg0)  { 

    System.out.println("An attribute is replaced in Session,name: "+arg0.getName());

}

 

public void attributeReplaced(ServletContextAttributeEvent arg0)  { 

    System.out.println("An attribute is replaced in ServletContext,name: "+arg0.getName());

 

}

 

public void contextInitialized(ServletContextEvent arg0)  { 

 // TODO Auto-generated method stub

}

 

}

 

 

 

 

基本概念

JDBC(Java Database Connectivity):Java数据库连接,是Java程序与数据库系统通信的标准API。

JDBC由一组用Java语言编写的类和接口组成,可以做三件事:

· 

与数据库建立连接

· 

· 

发送SQL语句

· 

· 

处理结果

· 

JDBC驱动程序

使用JDBC访问数据库,必须下载相应的JDBC驱动程序。JDBC驱动程序分为四种类型:

1. 

类型1驱动程序:JDBC-ODBC桥驱动,通过ODBC数据源进行与数据库的连接

2. 

3. 

类型2驱动程序:直接将应用程序与网络库连接的驱动程序

4. 

5. 

类型3驱动程序:通过中间件服务器与数据库建立连接的驱动程序

6. 

7. 

类型4驱动程序:直接与数据库相连的纯Java驱动程序

8. 

JDBC主要接口

· 

java.sql.DriverManager

· 

DriverManager类是Java.sql包中用于数据库驱动程序管理的类,作用于用户和驱动程序之间。

· 

· 

java.sql.Connection

· 

Connection是用来表示数据库连接的对象,对数据库的一切操作都是在这个连接的基础上进行的。

· 

· 

java.sql.Statement

· 

Statement用于在已经建立的连接的基础上向数据库发送SQL语句的对象。它只是一个接口的定义,其中包括了执行SQL语句和获取返回结果的方法。

· 

· 

java.sql.ResultSet

· 

结果集(ResultSet)用来暂时存放数据库查询操作获得的结果。

· 

 

 

 

相关软件包

JDBC API主要定义在java.sql和javax.sql两个包中。

在JSP中需要用page指令的import属性进行导入:

<%@page import="java.sql.*" %>

一般步骤

首先要获取相应数据库的JDBC驱动程序(MySQL JDBC驱动程序:mysql-connector-java-5.1.38-bin.jar(下载附件 960.85 KB))并进行配置,在web应用中,就是将其放置到工程目录中的/WEB-INF/lib目录中。

数据库访问程序的步骤:

1. 装载驱动程序

利用Class.forName()方法加载某一个数据库的驱动程序。

Class.forName(“JDBC驱动程序类”);

示例:

使用JDBC/ODBC桥驱动程序:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

使用mySQL的驱动程序:

Class.forName("com.mysql.jdbc.Driver");

使用SQLServer的驱动程序:

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

使用oracle的驱动程序:

Class.forName("oracle.jdbc.driver.OracleDriver");

使用DB2的驱动程序:

Class.forName("com.ibm.db2.jdbc.app.DB2Driver");

2. 建立与数据库的连接(URL、用户名、密码)

首先要定义连接数据库的URL,URL由3部分组成,各个部分用冒号间隔,格式如下:

jdbc:<子协议>:<子名称>

不同数据库连接的URL也不同,这点需要特别注意,常见的数据库连接的URL形式如下:

String ODBCURL= " jdbc:odbc:dbName";

String mysqlURL= "jdbc:mysql://host:port/dbName ";

String sqlserverURL= " jdbc:microsoft:sqlserver://host:1433;DatabaseName=dbName ";

String oracleURL= "jdbc:oracle:thin:@host:port:dbName ";

通过DriverManager调用getConnection方法建立连接,获取连接对象:

Connection con=DriverManager.getConnection(url, "用户名", "密码");

例:以连接mySQL数据库book为例,用户名为root,密码为123

String driverStr="com.mysql.jdbc.Driver";

String connStr="jdbc:mysql://localhost:3306/book";

Class.forName(driverStr);

Connection conn = DriverManager.getConnection(connStr, " root ", " 123 ");

3. 建立语句对象;

利用Connection接口的createStatement()方法创建语句对象。

Statement stmt=con.createStatement();

语句对象用于执行SQL语句。该对象负责将SQL语句传递给数据库管理系统执行。

4. 构建并执行SQL语句;

构建SQL语句:

String sql= " select * from  student";

将SQL语句通过Statement对象提交给服务器进行执行。

ResultSet resultSet=stmt.executeQuery(sql);

该语句将sql命令提交给数据库服务器进行执行,并将执行结果存储在ResultSet对象中进行执行。

Statement接口主要有如下三个方法:

public ResultSet  executeQuery(String sql) throws SQLException

作用:执行sql查询语句,返回一个ResultSet结果集(一个二维表)。

int  executeUpdate(String sql)

以sql语句为参数,执行sql更新语句及DDL语句,如添加、删除或修改操作,返回被受影响记录的条数。

boolean execute(String sql)

用于执行实现不知道类型的SQL语句,既可以执行查询语句,也可以执行更新语句。

当SQL语句的执行结果是一个ResultSet结果集时,本方法返回true;并可以通过Statement的getResultSet()方法得到返回的结果集;当SQL语句执行后没有返回的结果集时,该方法返回false

5. 处理返回结果;

若执行的是查询类的SQL语句,则会得到一个ResultSet对象,称为结果集,是符合条件的所有行的集合。可以通过(first(), last(), previous(), next(), absolute(int), …) 方法浏览可滚动结果集中的内容;

ResultSet中的方法:

boolean  next()

用于将 ResultSet定位到下一行。ResultSet最初是定位在第0行上的,此时应该先调用next()方法将其定位到第1行上,然后才可输出。当 ResultSet已经到了最后一行时,再调用next()方法,则返回 false。

XXX getXXX()

当 ResultSet已经定位在某一行上时,使用 getXxx ()方法得到这一行上单个字段的值。 针对不同的字段类型,调用不同的getXxx ()方法(getString(col), getDate(col), getInt(col),…)

例:

如果结果集中的第一个字段,字段名为“name”,是文本型的; 则可以使用getString(1)getString("name")来得到它的值。

如果结果集中的第三个字段,字段名为“score”,是数值型的; 则可以使用getFloat(3)getFloat("score")来得到它的值。

如果要显示结果集中所有记录的前两列:

while(rs.next()){

    name =rs.getString(1);

    phone =rs.getString(2);

    System.out.println(name+","+phone);

}

【示例程序】 读取数据库表中的所有图书信息

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="java.sql.*" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

 

<%

    Class.forName("com.mysql.jdbc.Driver");

    Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/bookdb","root","123456");

    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);

 

    String sql="select * from book";

 

    ResultSet rs=stmt.executeQuery(sql);

    if(rs!=null){

        while(rs.next()){

            int id=rs.getInt("book_id");

            String bookName=rs.getString("book_name");

            String author=rs.getString("author");

            float price=rs.getFloat("price");

            out.println(""+id+" :"+bookName+", "+author+", "+price+"<br>");

        }

    }

 

%>

 

</body>

</html>

6. 关闭相关对象

    rs.close();

    //关闭结果集

    stmt.close();

    //关闭语句对象

    con.close();

    //关闭连接

注意:资源关闭的顺序和打开的顺序恰恰相反。

 

 

语句对象有3种:

· 

Statement

· 

· 

PreparedStatement

· 

· 

CallableStatement。

· 

(1)Statement

通过Connection对象创建Statement语句对象的方法有:

Statement createStatement() throws SQLException

Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException

参数: resultSetType可以设置为如下常量: ResultSet.TYPE_FORWARD_ONLY,ResultSet.TYPE_SCROLL_INSENSITIVEResultSet.TYPE_SCROLL_SENSITIVE

resultSetConcurrency可以设置为:ResultSet.CONCUR_READ_ONLYResultSet.CONCUR_UPDATABLE

当resultSetType设置为:ResultSet.TYPE_FORWARD_ONLY(默认)时,游标是不能任意移动的,只能逐步向前,否则会报 SQLServerException。

Statement statement = con.createStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_XXX);

ResultSet rs = statement.executeQuery("select * from mytable");

rs.absolute(2);//这里会抛异常

System.out.println(rs.getString("virusid")+" "+rs.getString("featurecode")+" "+rs.getString("apppackage")+" "+rs.getInt("virustype")+" ");

当type设置为:ResultSet.TYPE_SCROLL_INSENSITIVE 或者ResultSet.TYPE_SCROLL_INSENSITIVE时,游标可以移动,但是移动的位置是[1,count],记住并不是从0开始,否则会报错。

游标移动的方法主要有:

rs = statement.executeQuery();  游标指向第一行前面的位置,这个位置是不能获取数据,否则报错:结果集没有当前行

rs.next();  // 游标下移一个位置,如果所在位置有结果集那么返回true,否则返回false

rs.previous(); // 游标上移一个位置,如果所在位置有结果集那么返回true,否则返回false

rs.first(); //  游标指向第一行的位置

rs.last(); //  游标指向最后一行的位置

rs.beforeFirst(); // 游标指向第一行前面的位置 , 这个位置不能获取数据

rs.afterLast(); //  游标指向最后一行后面的位置,这个位置不能获取数据

rs.absolute(index); // 游标移动至index位置,index是[1,count]的任意数字,但是不能超出,否则报错 

rs.relative(index); // 游标从当前位置算移动index个位置,也就是相对移动,index可以是负数,但是计算结果同样在[1,count]内

isAfterLast(); // 判断游标是否在最后一行之后。

isBeforeFirst();// 判断游标是否在第一行之前。

isFirst() ;  //判断游标是否指向结果集的第一行。

isLast(); // 判断游标是否指向结果集的最后一行。

getRow();// 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。

(2)PreparedStatement

PreparedStatement 对象中的 SQL 语句可具有一个或多个参数每个参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。

【示例代码1】

String sql = "select * from people p where p.id = ? and p.name = ?"; 

PreparedStatement ps = connection.prepareStatement(sql); 

ps.setint(1,id); 

ps.setstring(2,name); 

ResultSet rs = ps.executequery();

【示例代码2】

PreparedStatement pstmt = con.prepareStatement("UPDATE student SET stuname = ? WHERE stuid = ?");

pstmt.setString(1,"张三");

pstmt.setInt(2,1);

由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。

 

 

数据库连接池的工作原理

· 

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中

· 

· 

当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。

· 

· 

使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。

· 

· 

而连接的建立、断开都由连接池自身来管理。

· 

· 

可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数及每个连接的最大使用次数、最大空闲时间等等。

· 

· 

通过其自身的管理机制来监视数据库连接的数量、使用情况等。

· 

Tomcat中连接池的配置

1. 

将mysql的JDBC驱动jar包放进tomcat安装目录中的lib目录中

2. 

3. 

将以下内容保存为context.xml并放到web项目中的META-INF文件夹下:

4. 

<?xml version="1.0" encoding="UTF-8"?>  

<!DOCTYPE xml>  

<Context>  

    <Resource name="jdbc/book"   

    auth="Container"   

    type="javax.sql.DataSource"  

    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"   

    maxActive="100"   

    maxIdle="30"

    maxWait="1000"

    username="root"   

    password="123456"   

    driverClassName="com.mysql.jdbc.Driver"   

    url="jdbc:mysql://localhost:3306/bookdb?characterEncoding=UTF-8" />   

</Context>

5. 

连接池的使用

<%@ page import="java.sql.*,javax.sql.*,javax.naming.*" %>

<%

    Context cxt = new InitialContext();

    DataSource ds = 

        (DataSource)cxt.lookup("java:/comp/env/jdbc/book");

    Connection conn = ds.getConnection();

    //…

%>

 

 

Commons-FileUpload组件

Commons-FileUpload是Apache组织下jakarta-commons项目组下的一个小项目,该组件可以方便地将multipart/form-data类型请求中的各种表单域解析出来,并实现一个或多个文件的上传,同时也可以限制上传文件的大小等内容。

在使用Commons-FileUpload组件时,需要先下载该组件:http://commons.apache.org/fileupload/,需要同时下载commons-io组件。

也可以在这里下载:commons-fileupload-1.2.2.jar(下载附件 58.19 KB)  commons-io-2.4.jar(下载附件 180.8 KB)

并将其拷贝到应用的lib目录下:

文件上传的步骤

1. 添加表单及表单元素

    <form method="POST" enctype="multipart/form-data" action="a.jsp">

      File to upload: <input type="file" name="upfile"><br/>

      Notes about the file: <input type="text" name="note"><br/>

      <br/>

      <input type="submit" value="Press"> to upload the file!

    </form>

<form>元素中的method值要指定为post,enctype属性设置为"multipart/form-data"。

<input name="file" type="file" size="尺寸">

name属性:用于指定文件域的名称。

type属性:设置为file,表示文件域。

size属性:用于指定文件域中文本框的长度。

2. 创建上传对象

导入相应的类:

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

应用Commons-FileUpload组件实现文件上传时,需要创建一个工厂对象:

//基于磁盘文件项目创建一个工厂对象

DiskFileItemFactory factory = new DiskFileItemFactory();

//创建一个新的文件上传对象

ServletFileUpload upload = new ServletFileUpload(factory);

3. 解析上传请求

创建一个文件上传对象后,就可以通过这个对象调用parseRequest()方法获取全部的表单项:

public List parseRequest(HttpServletRequst request) throws FileUploadException

例如:

List items = upload.parseRequest(request); // 获取全部表单项

List集合中的表单项,不管是文件域还是普通表单域,都当成FileItem对象处理。 在进行文件上传时,可以通过FileItem对象的isFormField()方法判断表单项是文件域还是普通表单域。

可以通过FileItem类的getName()方法获取上传文件的文件名:

String fileName=item.getName();

获取上传文件大小:

long upFileSize=item.getSize();

获取上传文件的类型:

String type=item.getContentType();

【示例程序】 使用Commons-FileUpload组件实现文件上传(工程下载:upload.rar(下载附件 673.11 KB))

index.jsp:表单页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML>

<html>

<head>

<title>应用commons-fileUpload实现文件上传</title>

<style type="text/css">

ul{list-style: none;}

li{padding:5px;}

</style>

</head>

<body>

    <script type="text/javascript">

        function validate() {

            if (form1.file.value == "") {

                alert("请选择要上传的文件");

                return false;

            }

        }

    </script>

    <!-- 定义表单 -->

    <form action="UploadServlet" method="post"

        enctype="multipart/form-data" name="form1" id="form1"

        οnsubmit="return validate()">

        <ul>

            <li>请选择要上传的附件:</li>

            <li>上传文件: <input type="file" name="file" /> <!-- 文件上传组件 --></li>

            <li><input type="submit" name="Submit" value="上传" /> <input

                            type="reset" name="Submit2" value="重置" /></li>

        </ul>

    </form>

</body>

</html>

UploadServlet.java: 处理文件上传的Servlet类

package com.myupload.servlet;

 

import java.io.File;

import java.io.IOException;

import java.util.Iterator;

import java.util.List;

 

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileUploadException;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

 

@WebServlet("/UploadServlet")

public class UploadServlet extends HttpServlet {

    /**

     * 

     */

    private static final long serialVersionUID = 7042756416806244618L;

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doPost(request, response);

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        String adjunctname = null;

        String fileDir = getServletContext().getRealPath("/upload");

        System.out.println("fileDir: " + fileDir);

        // 指定上传文件的保存地址

        String message = "文件上传成功";

        String address = "";

        request.setCharacterEncoding("UTF-8");

        if (ServletFileUpload.isMultipartContent(request)) { // 判断是否是上传文件

            DiskFileItemFactory factory = new DiskFileItemFactory();

            factory.setSizeThreshold(20 * 1024); // 设置内存中允许存储的字节数

            //factory.setRepository(factory.getRepository()); // 设置存放临时文件的目录

            //factory.setRepository(new File("d:\\temp"));

            //System.out.println("path:"+factory.getRepository().getAbsolutePath());

            ServletFileUpload upload = new ServletFileUpload(factory); // 创建新的上传文件句柄

 

            int size = 5 * 1024 * 1024; // 指定上传文件的大小

            List formlists = null; // 创建保存上传文件的集合对象

            try {

                formlists = upload.parseRequest(request); // 获取上传文件集合

            } catch (FileUploadException e) {

                e.printStackTrace();

            }

            Iterator iter = formlists.iterator(); // 获取上传文件迭代器

            while (iter.hasNext()) {

                FileItem formitem = (FileItem) iter.next(); // 获取每个上传文件

                if (!formitem.isFormField()) { // 忽略不是上传文件的表单域

                    String name = formitem.getName(); // 获取上传文件的名称

                    if (formitem.getSize() > size) { // 如果上传文件大于规定的上传文件的大小

                        message = "您上传的文件太大,请选择不超过2M的文件";

 

                        break; // 退出程序

                    }

                    String adjunctsize = new Long(formitem.getSize())

                            .toString(); // 获取上传文件的大小

                    if ((name == null) || (name.equals(""))

                            && (adjunctsize.equals("0"))) // 如果上传文件为空

                        continue; // 退出程序

                    adjunctname = name.substring(name.lastIndexOf("\\") + 1,

                            name.length());

                    address = fileDir + "\\" + adjunctname; // 创建上传文件的保存地址

                    File saveFile = new File(address); // 根据文件保存地址,创建文件

                    try {

                        formitem.write(saveFile); // 向文件写数据

                        request.setAttribute("filepath", "upload/" + adjunctname);

 

                    } catch (Exception e) {

                        e.printStackTrace();

                    }

                }

            }

        }

        request.setAttribute("result", message); // 将提示信息保存在request对象中

 

        RequestDispatcher requestDispatcher = request

                .getRequestDispatcher("result.jsp"); // 设置相应返回地址

        requestDispatcher.forward(request, response);

    }

 

    public void init() throws ServletException {

        // Put your code here

    }

 

}

 

 

Java Mail开发环境

所需组件:

· 

Java Mail API  mail.jar(下载附件 348.16 KB)

· 

下载: http://www.oracle.com/technetwork/java/index-138643.html

· 

· 

JAF (JavaBeans Activation Framework) activation.jar(下载附件 54.62 KB)

· 

下载: http://java.sun.com/products/javabeans/jaf/downloads/index.html

· 

配置组件:

将两个组件的jar文件: mail.jar和activation.jar复制到工程的WEB-INF\lib目录中

Java Mail核心类

· 

Session(会话)类

· 

用于定义保存诸如SMTP主机和认证的信息的基本邮件会话。Session对象利用java.util.Properties对象获取诸如邮件服务器、用户名、密码等信息:

Properties props=new Properties();

props.put("mail.smtp.host",mailserver);

props.put("mail.smtp.auth","true");

创建Session对象:

(1)使用静态方法创建Session:

Session session = Session.getInstance(props, authenticator);

(2)创建默认的共享Session

Session defaultSession = Session.getDefaultInstance(props, authenticator);

创建一个不需要指定认证方式的Session对象:

Session mailSession=Session.getDefaultInstance(props,null);

· 

Message(消息)类

· 

核心类,用于存储实际发送的电子邮件信息。Message是抽象类,要使用其子类javax.mail.internet.MimeMessage

可以存储MIME类型和报头(在不同的RFC文档中均有定义)消息,并且将消息的报头限制成只能使用US-ASCII字符

实例化:

MimeMessage msg = new MimeMessage(mailSession);

MimeMessage类常用方法:

(1)setText()方法

setText()方法用于指定纯文本信息的邮件内容。语法格式为:

setText(String content)

(2)setContent()方法

用于设置电子邮件内容的基本机制,该方法包括两个参数,分别用于指定邮件内容和MIME类型。

setContent(Object content, String type)

(3)setSubject ()方法

用于设置邮件的主题。

setSubject(String subject)

(4)saveChanges()方法:保证报头域同会话内容保持一致。

(5)setFrom()方法:设置发件人地址。

msg.setFrom(new InternetAddress(from));

(6)setRecipients()方法:用于设置收件人地址。

setRecipients(RecipientType type, InternetAddress addres);

其中,type可以是:

· 

Message.RecipientType.TO//发送

· 

· 

Message.RecipientType.CC//抄送

· 

· 

Message.RecipientType.BCC//暗送

· 

addres:收件人地址,可以为InternetAddress类的一个对象或多个对象组成的数组。

(7)setSentDate()方法:用于设置发送邮件的时间。

setSentDate(Date date);

(8)getContent()方法:用于获取消息内容,该方法无参数。

(9)writeTo()方法:用于获取消息内容(包括报头信息),并将其内容写到一个输出流中。

writeTo(OutputStream os)

· 

Address(地址)类

· 

用于设置电子邮件的响应地址,Address是抽象类,使用其子类javax.mail.internetAuthenticator.InternetAddress 实例化该类的一个对象:

(1)创建只带有电子邮件地址的地址

InternetAddress address = new InternetAddress(“kkkk@sohu.com");

(2)创建带有电子邮件地址并显示其他标识信息的地址

InternetAddress address = new InternetAddress(“kkk@sohu.com",“kkkk");

· 

Authenticator(认证方式)类

· 

通过用户名和密码来访问受保护的资源。Authenticator是一个抽象类,首先要创建一个Authenticator的子类,并重载getPasswordAuthentication()方法:

class WghAuthenticator extends Authenticator {

    public PasswordAuthentication getPasswordAuthentication() {

        String username = “kkkk";   //邮箱登录账号

        String pwd = "111222";          //登录密码

        return new PasswordAuthentication(username, pwd);

    }

}

· 

Transport类

· 

用于使用指定的协议(通常是SMTP)发送电子邮件。Transport类提供了以下两种发送电子邮件的方法。

(1)只调用其静态方法send(),按照默认协议发送电子邮件:

Transport.send(message);

(2)首先从指定协议的会话中获取一个特定的实例,然后传递用户名和密码,再发送信息,最后关闭连接,代码如下:

Transport transport =sess.getTransport("smtp");

transport.connect(servername,from,password);

transport.sendMessage(message,message.getAllRecipients());

transport.close();

· 

Store类

· 

定义了用于保存文件夹间层级关系的数据库,以及包含在文件夹之中的信息。 在获取会话后,就可以使用用户名和密码或Authenticator类来连接Store类。与Transport类一样,首先要告诉Store类将使用什么协议:

(1)使用POP3协议连接Store

Store store = session.getStore("pop3");

store.connect(host, username, password);

(2)使用IMAP协议连接Store

Store store = session.getStore("imap");

store.connect(host, username, password);

说明:如果使用POP3协议,只可以使用INBOX文件夹,但是使用IMAP协议,则可以使用其他的文件夹。

· 

Folder类

· 

定义了获取(fetch)、备份(copy)、附加(append)及以删除(delete)信息等的方法。在连接Store类后,就可以打开并获取Folder类中的消息。

Folder folder = store.getFolder("INBOX");

folder.open(Folder.READ_ONLY);

Message message[] = folder.getMessages();

在使用Folder类读取完邮件信息后,需要及时关闭对文件夹存储的连接。

folder.close(Boolean boolean);

boolean:用于指定是否通过清除已删除的消息来更新文件夹。

【示例程序】 使用JavaMail发送邮件 mailPrj.rar(下载附件 424.25 KB)

sendmail.jsp: 发送邮件的表单页面

<%@ page contentType="text/html; charset=gb2312" language="java" %>

<html>

<head>

<title>发送普通文本格式的E-mail</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<link href="css/style.css" rel="stylesheet">

<script language="javascript">

function checkform(myform){

    for(i=0;i<myform.length;i++){

        if(myform.elements[i].value==""){

            alert(myform.elements[i].title+"不能为空!");

            myform.elements[i].focus();

            return false;

        }

    }

}

</script>

</head>

<body>

<form name="form1" method="post" action="mydeal.jsp" onSubmit="return checkform(form1)">

<table width="649" height="454"  border="0" align="center" cellpadding="0" cellspacing="0" background="images/bg.jpg">

  <tr>

<td width="67" height="109" background="Images/board_left.gif"> </td>

<td width="531" background="Images/board_left.gif"> </td>

<td width="51" background="Images/board_left.gif"> </td>

  </tr>

  <tr valign="top">

<td height="247"> </td>

<td valign="top"><table width="96%" border="0" align="center" cellpadding="0" cellspacing="0">

  <tr>

<td width="16%" height="27" align="center">收件人:</td>

<td width="84%" colspan="2" align="left"><input name="to" type="text" id="to" title="收件人" size="60"></td>

  </tr>

  <tr>

<td height="27" align="center">发件人:</td>

<td colspan="2" align="left"><input name="from" type="text" id="from" title="发件人" size="60"></td>

  </tr>

  <tr>

<td height="27" align="center">密  码:</td>

<td colspan="2" align="left"><input name="password" type="password" id="password" title="发件人信箱密码" size="60"></td>

  </tr>

  <tr>

<td height="27" align="center">主  题:</td>

<td colspan="2" align="left"><input name="subject" type="text" id="subject" title="邮件主题" size="60"></td>

  </tr>

  <tr>

<td height="93" align="center">内  容:</td>

<td colspan="2" align="left"><textarea name="content" cols="59" rows="7" class="wenbenkuang" id="content" title="邮件内容"></textarea></td>

  </tr>

  <tr>

<td height="30" align="center"> </td>

<td height="40" align="right"><input name="Submit" type="submit" class="btn_grey" value="发送">

   

  <input name="Submit2" type="reset" class="btn_grey" value="重置">

     </td>

<td align="left"> </td>

  </tr>

</table></td>

<td> </td>

  </tr>

  <tr valign="top">

<td height="48"> </td>

<td> </td>

<td> </td>

  </tr>

</table>

</form>

</body>

</html>

mydeal.jsp: 处理邮件发送

<%@ page contentType="text/html; charset=gb2312" language="java"  errorPage="" %>

<%@ page import="java.util.*" %>

<%@ page import ="javax.mail.*" %>

<%@ page import="javax.mail.internet.*" %>

<%@ page import="javax.activation.*" %>

<%

    try{

        request.setCharacterEncoding("gb2312");

        String from=request.getParameter("from");

        String to=request.getParameter("to");

        String subject=request.getParameter("subject");

        String messageText=request.getParameter("content");

        String password=request.getParameter("password");

        //生成SMTP的主机名称

        int n =from.indexOf('@');

        int m=from.length() ;

        String mailserver ="smtp."+from.substring(n+1,m);

        //String mailserver="wanggh";

        //建立邮件会话

            Properties pro=new Properties();

        pro.put("mail.smtp.host",mailserver);

        pro.put("mail.smtp.auth","true");

        Session sess=Session.getInstance(pro);

        sess.setDebug(true);

        //新建一个消息对象

        MimeMessage message=new MimeMessage(sess);

        //设置发件人

        InternetAddress from_mail=new InternetAddress(from);

        message.setFrom(from_mail);

           //设置收件人

        InternetAddress to_mail=new InternetAddress(to);

        message.setRecipient(Message.RecipientType.TO ,to_mail);

        //设置主题

        message.setSubject(subject);

       //设置内容

       message.setText(messageText);

       //设置发送时间

       message.setSentDate(new Date());

       //发送邮件

       message.saveChanges();  //保证报头域同会话内容保持一致

       Transport transport =sess.getTransport("smtp");

       transport.connect(mailserver,from,password);

       transport.sendMessage(message,message.getAllRecipients());

       transport.close();

       out.println("<script language='javascript'>alert('邮件已发送!');window.location.href='sendmail.jsp';</script>");

    }catch(Exception e){

        System.out.println("发送邮件产生的错误:"+e.getMessage());

        out.println("<script language='javascript'>alert('邮件发送失败!');window.location.href='sendmail.jsp';</script>");

    }

%>

 

 

 

 

动态图表


JFreeChart组件

Java开源项目,是一款优秀的Java图表生成插件,提供了在Java Application、Servlet和JSP下生成各种图片格式的图表,包括柱形图、饼形图、线图、区域图、时序图和多轴图等。

网址: http://www.jfree.org/jfreechart/index.html

将图中三个jar包拷贝到工程中的WEB-INF\lib目录下:

jfreechart-1.0.14.jar(下载附件 1.39 MB) 

jcommon-1.0.17.jar(下载附件 302.66 KB)

配置

在工程的web.xml文件中配置如下内容:

<servlet>

    <servlet-name>DisplayChart</servlet-name>

    <servlet-class>

        org.jfree.chart.servlet.DisplayChart

    </servlet-class>

</servlet>

 

<servlet-mapping>

    <servlet-name>DisplayChart</servlet-name>

    <url-pattern>/servlet/DisplayChart</url-pattern>

</servlet-mapping>

基本步骤

生成动态统计图表的基本步骤:

(1)创建绘图数据集合;

(2)创建JFreeChart实例;

(3)自定义图表绘制属性,该步可选;

(4)生成指定格式的图片,并返回图片名称;

(5)组织图片浏览路径;

(6)通过HTML中的标记显示图片。

JFreeChart的核心类

 

【示例程序】 绘制下图所示图表 chartPrj.rar(下载附件 1.59 MB)

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>

<%@ page import="org.jfree.chart.ChartFactory" %>

<%@ page import="org.jfree.chart.JFreeChart" %>

<%@ page import="org.jfree.data.category.DefaultCategoryDataset" %>

<%@ page import="org.jfree.chart.plot.PlotOrientation" %>

<%@ page import="org.jfree.chart.entity.StandardEntityCollection" %>

<%@ page import="org.jfree.chart.ChartRenderingInfo" %>

<%@ page import="org.jfree.chart.servlet.ServletUtilities" %>

<%@ page import="org.jfree.data.category.DefaultCategoryDataset"%>

<%@ page import="org.jfree.chart.StandardChartTheme"%>

<%@ page import="java.awt.Font"%>

 

<%

    StandardChartTheme standardChartTheme = new StandardChartTheme("CN");       //创建主题样式

    standardChartTheme.setExtraLargeFont(new Font("隶书", Font.BOLD, 20));        //设置标题字体

    standardChartTheme.setRegularFont(new Font("微软雅黑", Font.PLAIN, 15));        //设置图例的字体

    standardChartTheme.setLargeFont(new Font("微软雅黑", Font.PLAIN, 15));      //设置轴向的字体

    ChartFactory.setChartTheme(standardChartTheme);                         //设置主题样式

    DefaultCategoryDataset dataset1=new DefaultCategoryDataset();

    dataset1.addValue(200,"北京","苹果");

    dataset1.addValue(150,"北京","香蕉");

    dataset1.addValue(450,"北京","葡萄");

 

    dataset1.addValue(400,"吉林","苹果");

    dataset1.addValue(200,"吉林","香蕉");

    dataset1.addValue(150,"吉林","葡萄");

 

    dataset1.addValue(150,"深圳","苹果");

    dataset1.addValue(350,"深圳","香蕉");

    dataset1.addValue(200,"深圳","葡萄");

 

    //创建JFreeChart组件的图表对象

    JFreeChart chart=ChartFactory.createBarChart3D(

                                        "水果销量图",        //图表标题

                                        "水果",       //x轴的显示标题

                                        "销量",           //y轴的显示标题

                                        dataset1,   //数据集

                                        PlotOrientation.VERTICAL,//图表方向(垂直)

                                        true,       //是否包含图例

                                        false,      //是否包含提示

                                        false       //是否包含URL

                                        );

    //设置图表的文件名

    // 固定用法

    ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());

    String fileName=ServletUtilities.saveChartAsPNG(chart,400,270,info,session);

    String url=request.getContextPath()+"/servlet/DisplayChart?filename="+fileName;

%>

    <html>

 

      <head>

    <title>绘制柱形图</title>

      </head>

 

      <body topmargin="0">

    <table width="100%"  border="0" cellspacing="0" cellpadding="0">

      <tr>

    <td> <img src="<%=url %>"></td>

      </tr>

    </table>

      </body>

 

</html>

其它第三方图表组件

(1)HighCharts:http://www.hcharts.cn/

(2)echarts:http://echarts.baidu.com/

 

 

JSP报表

iText组件

能够快速产生PDF文件的Java类库,可以生成包含文本、表格、图形等内容的只读文档,而且可以将XML、HTML文件转化为PDF文件。

下载地址:http://itextpdf.com/ 

iText-2.0.7.jar(下载附件 1.15 MB)

jcommon-1.0.9.jar(下载附件 298.22 KB)

iTextAsian.jar(下载附件 322.01 KB)

配置:将itext-1.3.1.jar,iTextAsian.jar包放入项目目录下的WEB-INF/lib路径中

应用iText组件生成JSP报表

1. 建立com.lowagie.text.Document对象的实例

public Document();

public Document(Rectangle pageSize);  //定义页面的大小

public Document(Rectangle pageSize,int marginLeft,

int marginRight,int marginTop,int marginBottom);/*定义页面的大小,参数marginLeft、marginRight、marginTop、marginBottom分别为左、右、上、下的页边距*/

【示例代码】

Rectangle rectPageSize = new Rectangle(PageSize.A4); //定义A4页面大小

rectPageSize = rectPageSize.rotate(); //加上这句可以实现A4页面的横置

Document doc = new Document(rectPageSize,50,50,50,50);//其余4个参数设置了页面的4个边距

2.设定文档属性

public boolean addTitle(String title)

public boolean addSubject(String subject)

public boolean addKeywords(String keywords)

public boolean addAuthor(String author)

public boolean addCreator(String creator)

public boolean addProducer()

public boolean addCreationDate()

public boolean addHeader(String name, String content)

其中addHeader()对PDF文档无效,仅对HTML文档有效。

3.创建书写器(Writer)对象

文档(document)对象建立好之后,还需要建立一个或多个书写器与对象相关联,通过书写器可以将具体的文档存盘成需要的格式,例如:

com.lowagie.text.PDF.PDFWriter可以将文档存成PDF格式

com.lowagie.text.html.HTMLWriter可以将文档存成HTML格式。

4.进行中文处理

将iTextAsian.jar组件下载后放入项目目录下的WEB-INF/lib路径中。

5.创建表格

iText组件中创建表格的类包括com.lowagie.text.Tablecom.lowagie.text.PDF.PDFPTable两种。

比较简单的表格可以使用com.lowagie.text.Table类创建;创建复杂的表格,用到com.lowagie.text.PDF.PDFPTable

(1)com.lowagie.text.Table类

com.lowagie.text.Table类的构造函数有3个:

Table(int columns)

Table(int columns, int rows)

Table(Properties attributes)

参数columns,rows,attributes分别为表格的列数、行数、表格属性。创建表格时必须指定表格的列数,而对于行数可以不用指定。

创建表格之后,还可以设定表格的属性,如边框宽度、边框颜色、间距(padding space 即单元格之间的间距)大小等属性。

(2)com.lowagie.text.PdfPTable类

iText组件中一个文档(Document)中可以有很多个表格,一个表格可以有很多个单元格,一个单元格里面可以放很多个段落,一个段落里面可以放一些文字。但是,读者必须明确以下两点内容:

· 

在iText组件中没有行的概念,一个表格里面直接放单元格,如果一个5列的表格中放进10个单元格,那么就是两行的表格;

· 

· 

如果一个5列的表格放入4个最基本的没有任何跨列设置的单元格,那么这个表格根本添加不到文档中,而且不会有任何提示。

· 

6.图像处理

iText组件中处理图像的类为com.lowagie.text.Image,目前iText组件支持的图像格式有GIF,Jpeg,PNG,wmf等格式,对于不同的图像格式,iText组件用同样的构造函数自动识别图像格式,通过下面的代码可以分别获得gif,jpg,png图像的实例:

Image gif = Image.getInstance("face1.gif");

Image jpeg = Image.getInstance("bookCover.jpg");

Image png = Image.getInstance("ico01.png");

 

 


EL(Expression Language)是JSP2.0中引入的一种计算和输出Java对象的简单语言。

特点:

(1)在EL表达式中可以获得命名空间(PageContext对象,它是页面中最大范围的集成对象,通过它可以访问其他内置对象);

(2)表达式可以访问一般变量,还可以访问JavaBean类中的属性以及嵌套属性和集合对象;

(3)在EL表达式中可以执行关系、逻辑和算术等运算;

(4)扩展函数可以与Java类的静态方法进行映射;

(5)在表达式中可以访问JSP的作用域(request,session,application以及page)。

在EL表达式中允许程序员使用简单语法访问对象。例如,使用下面的代码访问系统作用域的值:

${name}

其中${name}为访问name变量的表达式,而通过表达式语言调用JavaBean中的属性值或方法的代码如下:

<jsp:useBean id="dao" scope="page" class="com.UserInfoDao"></jsp:useBean>

${dao.name} <!--调用UserInfoDao类中name属性-->

${dao.getName()}    <!--调用UserInfoDao类中getName()方法-->

 

 


基本语法

<%@ page isELIgnored="true|false" %>

语法格式:${expression}

如果在JSP网页中要显示“${”字符串,必须在前面加上“\”符号,即“\${”,或者写成“${'${'}”

如果想在JSP页面中输出EL表达式,可以使用“\”符号,即在“${}”之间加“\”,例如“\${5+3}”

运算符

(1)存取数据运算符

在EL表达式中可以使用运算符“[]”和“.”来取得对象的属性。例如,${user.name}或者${user[name]}都是表示取出对象user中的name属性值。

(2)算术运算符

算术运算符可以作用在整数和浮点数上。EL表达式的算术运算符包括加(+)、减(-)、乘(*)、除(/或div)、和求余(%或mod)等5个。

注意:可以采用${“a”}${“b”}形式进行字符串的连接

(3)关系运算符

EL表达式的关系运算符包括等于(==或eq)、不等于(!=或ne)、小于(<或lt)、大于(>或gt)、小于等于(<=或le)和大于等于(>=或ge)等6个。

注意:在使用EL表达式关系运算符时,不能够写成:

${param.password1} == ${param.password2}

或:

${${param.password1} ==  ${param.password2}}

而应写成:

${param.password1  ==  param.password2}

(4)逻辑运算符

逻辑运算符可以作用在布尔值(Boolean),EL表达式的逻辑运算符包括与(&&或and)、或(||或or)和非(!或not)等3个。

(5)empty运算符

empty运算符是一个前缀(prefix)运算符,即empty运算符位于操作数前方,被用来决定一个对象或变量是否为null或空。 ** (6)条件运算符**

EL表达式中可以利用条件运算符进行条件求值,其格式如下:

${条件表达式 ? 计算表达式1 : 计算表达式2}

运算符的优先级:

EL表达式中的保留字

为变量命名时,应该避免使用这些保留字。

 

 

隐含对象共有11个,分为以下3种:

(1)PageContext隐含对象

用于访问JSP内置对象,例如,request、response、out、session、config、servletContext等,如:

${PageContext.session}

(2)访问环境信息的隐含对象

EL表达式中定义的用于访问环境信息的隐含对象包括以下6个:

· 

cookie:用于把请求中的参数名和单个值进行映射;

· 

· 

initParam:把上下文的初始参数和单一的值进行映射;

· 

· 

header:把请求中的header名字和单值映射;

· 

· 

param:把请求中的参数名和单个值进行映射;

· 

· 

headerValues:把请求中的header名字和一个Arrar值进行映射;

· 

· 

paramValues:把请求中的参数名和一个Array值进行映射。

· 

(3)访问作用域范围的隐含对象

EL表达式中定义的用于访问环境信息的隐含对象包括以下4个:

· 

applicationScope:映射application范围内的属性值;

· 

· 

sessionScope:映射session范围内的属性值;

· 

· 

requestScope:映射request范围内的属性值;

· 

· 

pageScope:映射page范围内的属性值。

· 

 

JSTL:JavaServer Pages Standard Tag Library,是一个不断完善的开放源代码的JSP标准标签库 主要给Java Web开发人员提供一个标准的通用的标签库。

JSTL主要包括以下5种标签库:

(1)核心标签库:用于完成JSP页面的基本功能,包含JSTL的表达式标签、条件标签、循环标签和URL操作共4种标签。

(2)格式标签库:格式标签库提供了一个简单的标记集合国际化(I18N)标记,用于处理和解决国际化相关的问题,另外,格式标签库中还包含用于格式化数字和日期的显示格式的标签。

(3)SQL标签库:SQL标签封装了数据库访问的通用逻辑,使用SQL标签,可以简化对数据库的访问。如果结合核心标签库,可以方便地获取结果集、迭代输出结果集中的数据结果。

(4)XML标签库:XML标签库可以处理和生成XML的标记,使用这些标记可以很方便地开发基于XML的Web应用。

(5)函数标签库:函数标签库提供了一系列字符串操作函数,用于分解和连接字符串、返回子串、确定字符串是否包含特定的子串等。

标签库的使用

在使用这些标签之前必须在JSP页面的首行使用<%@ taglib%>指令定义标签库的位置和访问前缀。例如,使用核心标签库的taglib指令格式如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

使用格式标签库的taglib指令格式如下:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

使用SQL标签库的taglib指令格式如下:

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%>

使用XML标签库的taglib指令格式如下:

<%@ taglib prefix="xml" uri="http://java.sun.com/jsp/jstl/xml"%>

使用函数标签库的taglib指令格式如下:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

注意:如果出现错误提示:

Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"

解决方法为: 在WEB-INF/lib里加入 jstl.jar,standard.jar两个包

 

表达式标签包括<c:out>、<c:set>、<c:remove>、<c:catch>等4个标签,下面分别介绍它们的语法及应用。

(1)<c:out>标签

<c:out>标签用于将计算的结果输出到JSP页面中,该标签可以替代<%=%>。<c:out>标签的语法格式如下:

语法1:

<c:out value="value" [escapeXml="true|false"] [default="defaultValue"]/>

语法2:

<c:out value="value" [escapeXml="true|false"]>

    defalultValue

</c:out>

这两种语法格式的输出结果完全相同,它的属性说明如下表所示。

【示例程序】测试<c:out>标签的escapeXml属性及通过两种语法格式设置default属性时的显示结果。

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

 

<%

   String str1="hello <br> world!";

   request.setAttribute("str1",str1);

%>

<c:out value="${str1}"/><br>

<c:out value="${str1}" escapeXml="false"/><br>

<c:out value="${str2}" default="Nice to meet you!"/><br>

(2)<c:set>标签

用于定义和存储变量。

语法1:该语法格式在scope指定的范围内将变量值存储到变量中。

<c:set value="value" var="name" [scope="page|request|session|application"]/>

语法2:该语法格式在scope指定的范围内将标签主体存储到变量中。

<c:set var="name" [scope="page|request|session|application"]>

  标签主体

</c:set>

语法3:该语法格式将变量值存储在target属性指定的目标对象的propName属性中。

<c:set value="value" target="object" property="propName"/>

语法4:该语法格式将标签主体存储到target属性指定的目标对象的propName属性中。

<c:set target="object" property="propName">

  标签主体

</c:set>

【示例程序】

<%@ page language="java"  pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

    <title>测试<c:set>标签</title>

  </head>

  <body>

    <c:set var="name" value="张三" scope="page"/>

    <c:set var="password" value="123@$abc" scope=`"session"/>

    <c:out value="${name}"></c:out>

    <br>

    <c:out value="${hostpage}"></c:out>

  </body>

</html>

(3)<c:remove>标签

从指定的JSP范围中移除指定的变量,语法格式如下:

<c:remove var="name" [scope="page|request|session|application"]/>

var用于指定存储变量值的变量名称;scope用于指定变量存在于JSP的范围,可选值有pagerequestsessionapplication。默认值是page

【示例程序】 <c:remove>标签示例

<%@ page language="java"  pageEncoding="GBK"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

     <title>测试<c:remove>标签</title>

  </head>  

  <body>

    <c:set var="name" value="周峰" scope="page" />

    移除前输出的变量name为:

    <c:out value="${name}"></c:out>

    <c:remove var="name" />

    <br> 移除后输出的变量name为:

    <c:out value="${name}" default="变量name为空"></c:out>

</body>

</html>

(4)<c:catch>标签

<c:catch>标签是JSTL中处理程序异常的标签,它还能够将异常信息保存在变量中。<c:catch>标签的语法格式如下:

<c:catch [var="name"]>

……存在异常的代码

</c:catch>

 

 

(1)<c:if>标签

语法1:该语法格式会判断条件表达式,并将条件的判断结果保存在var属性指定的变量中,而这个变量存在于scope属性所指定范围中。

<c:if test="condition" var="name" 

   [scope=page|request|session|application]/>

语法2:该语法格式不但可以将test属性的判断结果保存在指定范围的变量中,还可以根据条件的判断结果去执行标签主体。标签主体可以是JSP页面能够使用的任何元素。

<c:if test="condition" var="name" [scope=page|request|session|application]>

    标签主体

</c:if>

以上语法格式所涉及的属性:

【示例程序】应用<c:if>标签判断用户名是否为空,如果为空则显示一个用于输入用户名的文本框及“提交”按钮。

<%@ page language="java"  pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

<title>测试<c:if>标签</title>

  </head>

 

  <body>

语法一:输出用户名是否为null<br>

    <c:if test="${param.user==null}" var="rtn" scope="page"/>

    <c:out value="${rtn}"/>

<br>语法二:如果用户名为空,则输出一个用于输入用户名的文本框及“提交”按钮<br>

        <c:if test="${param.user==null}">

            <form action="" method="post">

                请输入用户名:<input type="text" name="user">

                <input type="submit" value="提交">

            </form>

        </c:if>

  </body>

</html>

(2)<c:choose>标签

<c:choose>标签可以根据不同的条件去完成指定的业务逻辑,如果没有符合的条件会执行默认条件的业务逻辑。<c:choose>标签只能作为<c:when>和<c:otherwise>标签的父标签,可以在它之内嵌套这两个标签完成条件选择逻辑。<c:choose>标签的语法格式如下:

<c:choose>

    <c:when>

        业务逻辑

    </c:when>

    …   <!--多个<c:when>标签-->

    <c:otherwise>

        业务逻辑

    </c:otherwise>

</c:choose>

(3)<c:when>标签

<c:choose>标签中可以包含多个<c:when>标签来处理不同条件的业务逻辑,但是只能有一个<c:otherwise>标签来处理默认条件的业务逻辑。 <c:when>标签的语法格式如下:

<c:when test="condition">

    标签主体

</c:when>

(4)<c:otherwise>标签

包含在<c:choose>标签的子标签,用于定义<c:choose>标签中的默认条件处理逻辑,如果没有任何一个结果满足<c:when>标签指定的条件,将会执行这个标签主体中定义的逻辑代码。

在<c:choose>标签范围内只能存在一个该标签的定义。<c:otherwise>标签的语法格式如下:

<c:otherwise>

    标签主体

</c:otherwise>

注意:<c:otherwise>标签必须定义在所有<c:when>标签的后面,也就是说它是<c:choose>标签的最后一个子标签。

【示例程序】应用<c:choose>标签、<c:when>标签和<c:otherwise>标签根据当前时间显示不同的问候。

<%@ page language="java"  pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

    <title>测试<c:choose>标签</title>

  </head>

 

  <body>

<c:set var="hours">

    <%=new java.util.Date().getHours()%>

</c:set>

<c:choose>

    <c:when test="${hours>6 && hours<11}" >上午好!</c:when>

    <c:when test="${hours>11 && hours<17}">下午好!</c:when>

    <c:otherwise>晚上好!</c:otherwise>

</c:choose>

 现在时间是:${hours}点 

  </body>

</html>

 

 

(1)<c:forEach>标签

<c:forEach>标签可以枚举集合中的所有元素,也可以循环指定的次数,这可以根据相应的属性确定。 <c:forEach>标签的语法格式如下:

<c:forEach items="data" var="name" begin="start" end="finish" step="step" varStatus="statusName">

 标签主体

</c:forEach>

<c:forEach>标签中的属性都是可选项,可以根据需要使用相应的属性。其属性说明如下表所示。

【示例程序】 使用<c:forEach>标签输出List集合中的内容,并循环输出字符串“编程词典”6次。

<%@ page language="java" pageEncoding="UTF-8" import="java.util.*"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>

<head>

<title>测试<c:forEach>标签</title>

</head>

 

<body>

    <%

        List list = new ArrayList();

        list.add("Java程序设计");

        list.add("JSP程序设计");

        list.add("Android应用开发");

        request.setAttribute("list", list);

    %>

    利用<c:forEach>标签遍历List集合的结果如下:

    <br>

    <c:forEach items="${list}" var="tag" varStatus="id">

    ${id.count } ${tag }<br>

    </c:forEach>

    <c:forEach begin="1" end="6" step="1" var="str">

        <c:out value="${str}" />你好!

</c:forEach>

</body>

</html>

(2)<c:forTokens>标签

<c:forTokens>标签可以用指定的分隔符将一个字符串分割开,根据分割的数量确定循环的次数。<c:forTokens>标签的语法格式如下:

<c:forTokens items="String" delims="char" [var="name"] [begin="start"] [end="end"] [step="len"] [varStatus="statusName"]>

    标签主体

</c:forTokens>

【示例程序】应用<c:forTokens>标签分割字符串并显示。

<%@ page language="java" pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>

<head>

<title>测试<c:forTokens>标签</title>

</head>

 

<body>

    <c:set var="sourceStr" value="北京|上海|广州|南京|杭州|New York" />

    原字符串:

    <c:out value="${sourceStr}" />

    <br>

    <br>分割后的字符串:

    <c:forTokens var="str" items="${sourceStr}" delims="|"

        varStatus="status">

        <c:out value="${str}"></c:out> ☆ 

    <c:if test="${status.last}">

            <br>

            <br>总共输出<c:out value="${status.count}"></c:out>个元素。

    </c:if>

    </c:forTokens>

 

</body>

</html>

 

 

 


(1)<c:import>标签

导入站内或其他网站的静态和动态文件到JSP页面中。<c:import>标签的语法格式如下。

语法1:

<c:import url="url" [context="context"] [var="name"] [scope="page|request|session|application"][charEncoding="encoding"]

标签主体

</c:import>

语法2:

<c:import url="url" varReader="name" [context="context"] [charEncoding="encoding"]

(2)<c:redirect>标签

将客户端发出的request请求重定向到其他URL服务端,由其他程序处理客户的请求。该标签有两种语法格式:

语法1:该语法格式没有标签主体,并且不添加传递到目标路径的参数信息。

<c:redirect url="url" [context="/context"]/>

语法2:该语法格式将客户请求重定向到目标路径,并且在标签主体中使用<c:param>标签传递其他参数信息。

<c:redirect url="url" [context="/context"]>

    ……<c:param>

</c:redirect>

(3)<c:url>标签

用于生成一个URL路径的字符串。在使用该标签生成URL时还可以搭配<c:param>标签动态添加URL的参数信息。

<c:url>标签有两种语法格式:

语法1:

<c:url value="url" [var="name"] [scope="page|request|session|application"] [context="context"]/>

该语法将输出产生的URL字符串信息,如果指定了var和scope属性,相应的URL信息就不再输出,而是存储在变量中以备后用。

语法2:

<c:url value="url" [var="name"] [scope="page|request|session|application"] [context=

 "context"]>

    <c:param>

</c:url>

语法格式2不仅实现了语法格式1的功能,而且还可以搭配<c:param>标签完成带参数的复杂URL信息。

<c:url>标签的语法中所涉及的属性说明如下表所示。

(4)<c:param>标签

<c:param>标签只用于为其他标签提供参数信息,它与本节中的其他3个标签组合可以实现动态定制参数,从而使标签可以完成更复杂的程序应用。<c:param>标签的语法格式如下:

<c:param name="paramName" value="paramValue"/>

在上面的语法中,name属性用于指定参数名称,可以引用EL;value属性用于指定参数值。

 

 


自定义标签是程序员自己定义的JSP语言元素,使用自定义标签库有以下的好处:

· 

使用自定义标签可以加快Web应用开发的速度

· 

· 

提高代码重用性

· 

· 

使得JSP程序更加容易维护

· 

· 

引入自定义标签后的JSP程序更加清晰、简洁、便于管理维护以及日后的升级

· 

自定义标签的定义格式

自定义标签在页面中通过XML语法格式来调用的。它们由一个开始标签和一个结束标签组成

(1)无标签体的标签

无标签体的标签有两种格式,一种是没有任何属性的,另一种是带有属性的。例如下面的代码:

<wgh:displayDate/>  <!--无任何属性-->

<wgh:displayDate name="contact" type="com.UserInfo"/>  <!--带属性-->

上面的代码中,wgh为标签前缀,displayDate为标签名称,name和type是自定义标签使用的两个属性。

(2)带标签体的标签

自定义的标签中可包含标签体,例如下面的代码:

<wgh:iterate>Welcome to BeiJing</wgh:iterate>

自定义标签的构成

自定义标签由实现自定义标签的Java类文件和自定义标签的TLD文件构成。

(1)实现自定义标签的Java类文件

任何一个自定义标签都要有一个相应的标签处理程序,自定义标签的功能是由标签处理程序定义的。因此,自定义标签的开发主要就是标签处理程序的开发。

标签处理程序的开发有固定的规范,即开发时需要实现特定接口的Java类,开发标签的Java类时,必须实现Tag或者BodyTag接口类(它们存储在javax.servlet.jsp.tagext包下)。BodyTag接口是继承了Tag接口的子接口,如果创建的自定义标签不带标签体,则可以实现Tag接口,如果创建的自定义标签包含标签体,则需要实现BodyTag接口。

(2)自定义标签的TLD文件

自定义标签的TLD文件包含了自定义标签的描述信息,它把自定义标签与对应的处理程序关联起来。一个标签库对应一个标签库描述文件,一个标签库描述文件可以包含多个自定义标签声明。

自定义标签的TLD文件的扩展名必须是.tld。该文件存储在Web应用的WEB-INF目录下或者子目录下,并且一个标签库要对应一个标签库描述文件,而在一个描述文件中可以保存多个自定义标签的声明。 自定义标签的TLD文件的完整代码如下:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"

version="2.0">

<description>A tag library exercising SimpleTag handlers.</description>

<tlib-version>1.2</tlib-version>

    <jsp-version>1.2</jsp-version>

 <short-name>examples</short-name>

<tag>

    <description>描述性文字</description>

 <name>showDate</name>

    <tag-class>com.ShowDateTag</tag-class>

    <body-content>empty</body-content>   

    <attribute>

        <name>value</name>

        <required>true</required>   

    </attribute>

</tag>

</taglib>

说明:通过子标签和<tag-class>子标签可以建立自定义标签和映射类之间的对应关系。

在JSP文件中引用自定义标签

JSP文件中,可以通过下面的代码引用自定义标签:

<%@ taglib uri="tld uri"  prefix="taglib.prefix"%>

(1)uri属性

uri属性指定了tld文件在Web应用中的存放位置,此位置可以采用以下两种方式指定。

① 在uri属性中直接指明tld文件的所在目录和对应的文件名,例如下面的代码:

<%@ taglib uri="/WEB-INF/showDate.tld"  prefix="taglib.prefix"%>

② 通过在web.xml文件中定义一个关于tld文件的uri属性,让JSP页面通过该uri属性引用tld文件,这样可以向JSP页面隐藏tld文件的具体位置,有利于JSP文件的通用性。例如在Web.xml中进行以下配置:

<jsp-config>

    <taglib>

    <taglib-uri> showDateUri</taglib-uri>

    <taglib-location>/WEB-INF/showDate.tld</taglib-location>

    </taglib>

</jsp-config>

在JSP页面中就可应用以下代码引用自定义标签:

<%@ taglib uri="showDateUri "  prefix="taglib.prefix"%>

(2)prefix属性

prefix属性规定了如何在JSP页面中使用自定义标签,即使用什么样的前缀来代表标签,使用时标签名就是在tld文件中定义的段中的属性的取值,它要和前缀之间用冒号“:”隔开。

【示例程序】自定义标签示例:创建用于显示当前系统日期的自定义标签,并在JSP页面中调用该标签显示当前系统日期。(下载:tagPrj.rar(下载附件 384.24 KB)

ShowDate.java

package tagPrj;

 

import java.io.PrintStream;

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.PageContext;

import javax.servlet.jsp.tagext.TagSupport;

 

public class ShowDate extends TagSupport

{

  public int doStartTag()

throws JspException

  {

    JspWriter out = this.pageContext.getOut();

    try

    {

      java.util.Date dt = new java.util.Date();

      java.sql.Date date = new java.sql.Date(dt.getTime());

      out.print(date);

    } catch (Exception e) {

      System.out.println("显示系统日期时出现的异常:" + e.getMessage());

    }

        return 0;

  }

}

showDate.tld

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"

version="2.0">

 <description>A tag library exercising SimpleTag handlers.</description>

 <tlib-version>1.2</tlib-version>

     <jsp-version>1.2</jsp-version>

 <short-name>date</short-name>

    <tag>

    <description>显示当前日期</description>

 <name>showDate</name>

     <tag-class>tagPrj.ShowDate</tag-class>

     <body-content>empty</body-content>   

    </tag>

</taglib>

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>1111</display-name>

  <jsp-config>

  <taglib>

    <taglib-uri> showDateUri</taglib-uri>

    <taglib-location>/WEB-INF/showDate.tld</taglib-location>

  </taglib>

 

  </jsp-config>

 

  <welcome-file-list>

<welcome-file>userDefineTag.jsp</welcome-file>

  </welcome-file-list>

</web-app>

 

 

概述

Ajax: Asynchronous JavaScript and XML,异步JavaScript与XML。

Ajax是JavaScript、XML、CSS、DOM等多种已有技术的组合,可以实现客户端的异步请求操作,可以实现在不需要刷新整个页面的情况下与服务器进行通信,从而减少了用户的等待时间。

· 

传统的Web应用模式:

· 

页面中用户的每一次操作都将触发一次返回Web服务器的HTTP请求,服务器进行相应的处理(获得数据、运行与不同的系统会话)后,返回一个HTML页面给客户端。

· 

Ajax应用模式:

· 

页面中用户的操作将通过Ajax引擎与服务器端进行通信,然后将返回结果提交给客户端页面的Ajax引擎,再由Ajax引擎来决定将这些数据插入到页面的指定位置。

从上面两个图中可以看出,对于每个用户的行为,在传统的Web应用模式中,将生成一次HTTP请求,而在Ajax应用开发模式中,将变成对Ajax引擎的一次JavaScript调用。在Ajax应用开发模式中通过JavaScript实现在不刷新整个页面的情况下,对部分数据进行更新,从而降低了网络流量,给用户带来了更好的体验。

 

1.JavaScript脚本语言

JavaScript是一种具有丰富的面向对象特性的程序设计语言,利用它能执行许多复杂的任务。

2.XMLHttpRequest

Ajax技术之中最核心的技术是一个具有应用程序接口的JavaScript对象,能够使用超文本传输协议(HTTP)连接一个服务器。

Ajax可以只同服务器进行数据层面的交换,而不用每次都刷新页面,也不用每次都将数据处理的工作交给服务器来做,既减轻服务器负担,又加快了响应速度、缩短了用户等待的时间。

3.XML语言

Extensible Markup Language(可扩展的标记语言)提供了用于描述结构化数据的格式。

XMLHttpRequest对象与服务器交换的数据,通常采用XML格式,但也可以是基于文本的其他格式。

4.DOM

Document Object Model(文档对象模型)是表示文档(如HTML文档)和访问、操作构成文档的各种元素(如HTML标记和文本串)的应用程序接口(API)。

在Ajax应用中,通过JavaScript操作DOM,可以达到在不刷新页面的情况下实时修改用户界面的目的。

5.CSS

Cascading Style Sheet(层叠样式表)用于(增强)控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

在Ajax中,通常使用CSS进行页面布局,并通过改变文档对象的CSS属性控制页面的外观和行为。

 

 

使用XMLHttpRequest对象

发送请求和处理响应之前,首先需要初始化该对象,对于不同的浏览器,初始化的方法也是不同的:

//IE浏览器

var http_request = new ActiveXObject("Msxml2.XMLHTTP");

var http_request = new ActiveXObject("Microsoft.XMLHTTP");

 

//Mozilla、Safari等其他浏览器

var http_request = new XMLHttpRequest();

创建一个跨浏览器的XMLHttpRequest对象

if (window.XMLHttpRequest) { // Mozilla、Safari...

    http_request = new XMLHttpRequest();

} else if (window.ActiveXObject) { // IE浏览器

    try {

        http_request = new ActiveXObject("Msxml2.XMLHTTP");

    } catch (e) {

       try {

        http_request = new ActiveXObject("Microsoft.XMLHTTP");

       } catch (e) {}

    }

}

XMLHttpRequest对象的常用方法

(1)open()方法

open()方法用于设置进行异步请求目标的URL、请求方法以及其他参数信息:

open("method","URL"[,asyncFlag[,"userName"[, "password"]]]);

参数说明:

· 

method用于指定请求的类型,一般为get或post;

· 

· 

URL用于指定请求地址,可以使用绝对地址或者相对地址;

· 

· 

asyncFlag为可选参数,用于指定请求方式,同步请求为true,异步请求为false,默认情况下为true;

· 

(2)send()方法

send()方法用于向服务器发送请求。如果请求声明为异步,该方法将立即返回,否则将等到接收到响应为止。

 send(content);

参数说明:

content用于指定发送的数据,可以是DOM对象的实例、输入流或字符串。如果没有参数需要传递可以设置为null。

(3)setRequestHeader()方法

为请求的HTTP头设置值。

 setRequestHeader("label", "value");

参数说明:

· 

label用于指定HTTP头;value用于为指定的HTTP头设置值。

· 

· 

setRequestHeader()方法必须在调用open()方法之后才能调用。

· 

(4)abort()方法

用于停止当前异步请求。

(5)getAllResponseHeaders()方法

用于以字符串形式返回完整的HTTP头信息。

XMLHttpRequest对象的常用属性

 

 

 

1.浏览器兼容性问题

2.XMLHttpRequest对象封装

XMLHttpRequest对象实例在处理事件完成后就会被销毁,需要调用它时就得重新构建,因此需要进行封装。

现在很多开源Ajax框架都提供对XMLHttpRequest对象的封装。

3.性能问题

3种优化Ajax应用执行速度的方法:

(1)优化for循环;

(2)将DOM节点附加到文档上;

(3)尽量减少点“.”号操作符的使用。

4.中文编码问题 Ajax不支持多种字符集,默认字符集是UTF-8,所以在应用Ajax技术的程序中应及时进行编码转换,否则中文字符将变成乱码。

有以下两种情况可以产生中文乱码:

(1)发送路径的参数中包括中文,服务器端接收参数值时产生乱码。

Get方法:String name=request.getParameter("name");

out.println("姓名"+new String(name.getBytes("iso-8859-1"),"utf-8"));//解决中文乱码

Post方法:String name=request.getParameter("name");

out.println("姓名"+new String(name.getBytes("iso-8859-1"), "utf-8"));//解决中文乱码

(2)返回到responseText或responseXML的值中包含中文时产生乱码。

由于Ajax在接收responseText或responseXML的值时是按照UTF-8的编码格式进行解码的,所以如果服务器端传递的数据不是UTF-8格式,在接收responseText或responseXML的值时,就可能产生乱码。解决的办法是保证从服务器端传递的数据采用UTF-8的编码格式。

 

 


下载 jQuery: http://jquery.com/

共有两个版本的 jQuery 可供下载:一份是精简过的,另一份是未压缩的(供调试或阅读)。

向页面添加 jQuery 库:

<head>

<script type="text/javascript" src="jquery.js"></script>

</head>

jQuery语法

基础语法是:$(selector).action()

语法实例:

    $(this).hide()

 

隐藏当前的 HTML 元素。

 

    $("#test").hide()

 

隐藏 `id="test"` 的元素。

 

    $("p").hide()

 

隐藏所有 `<p>` 元素。

 

    $(".test").hide()

 

隐藏所有 class="test" 的元素。

jQuery 元素选择器

jQuery**使用CSS选择器**来选取HTML元素。

 

$("p") 选取 `<p>` 元素。

 

$("p.intro") 选取所有 class="intro" 的 `<p>` 元素。

 

$("p#demo") 选取所有 id="demo" 的 `<p>` 元素。

jQuery 属性选择器

jQuery 使用 XPath 表达式来选择带有给定属性的元素。

 

`$("[href]") `选取所有带有 href 属性的元素。

 

`$("[href='#']") `选取所有带有 href 值等于 "#" 的元素。

 

`$("[href!='#']")` 选取所有带有 href 值不等于 "#" 的元素。

 

`$("[href$='.jpg']")` 选取所有 href 值以 ".jpg" 结尾的元素。

jQuery CSS 选择器

jQuery CSS 选择器可用于改变 HTML 元素的 CSS 属性。

下面的例子把所有 p 元素的背景颜色更改为红色:

$("p").css("background-color","red");

jQuery事件函数

<html>

<head>

<script type="text/javascript" src="jquery.js"></script>

<script type="text/javascript">

$(document).ready(function(){

  $("button").click(function(){

$("p").hide();

  });

});

</script>

</head>

<body>

<h2>This is a heading</h2>

<p>This is a paragraph.</p>

<p>This is another paragraph.</p>

<button>Click me</button>

</body>

</html>

jQuery效果

隐藏和显示

$(selector).hide(speed,callback);

$(selector).show(speed,callback);

可选的 speed 参数规定隐藏/显示的速度,可以取以下值:"slow"、"fast" 或毫秒。

可选的 callback 参数是 toggle() 方法完成后所执行的函数名称。

淡入淡出

fadeIn()

fadeOut()

fadeToggle()

fadeTo()

元素上下滑动

slideDown()

slideUp()

slideToggle()

jQuery操作HTML元素

获得内容

text() - 设置或返回所选元素的文本内容

html() - 设置或返回所选元素的内容(包括 HTML 标记)

val() - 设置或返回表单字段的值

$("#btn1").click(function(){

  alert("Value: " + $("#test").val());

});

获取属性

attr() 方法用于获取属性值。

alert($("#w3s").attr("href"));

设置内容

$("#btn1").click(function(){

  $("#test1").text("Hello world!");

});

$("#btn2").click(function(){

  $("#test2").html("<b>Hello world!</b>");

});

$("#btn3").click(function(){

  $("#test3").val("Dolly Duck");

});

添加元素

append() - 在被选元素的结尾插入内容

prepend() - 在被选元素的开头插入内容

after() - 在被选元素之后插入内容

before() - 在被选元素之前插入内容

删除元素/内容

remove() - 删除被选元素(及其子元素)

empty() - 从被选元素中删除子元素

$("#div1").remove();

获取并设置 CSS 类

addClass() - 向被选元素添加一个或多个类

removeClass() - 从被选元素删除一个或多个类

toggleClass() - 对被选元素进行添加/删除类的切换操作

css() - 设置或返回样式属性

jQuery AJAX

load() 方法

可选的 callback 参数规定当 load() 方法完成后所要允许的回调函数。回调函数可以设置不同的参数:

· 

responseTxt 包含调用成功时的结果内容

· 

· 

statusTXT 包含调用的状态

· 

· 

xhr 包含 XMLHttpRequest 对象

· 

$("button").click(function(){

  $("#div1").load("demo_test.txt",function(responseTxt,statusTxt,xhr){

if(statusTxt=="success")

  alert("外部内容加载成功!");

if(statusTxt=="error")

  alert("Error: "+xhr.status+": "+xhr.statusText);

  });

});

· 

$.get()方法通过 HTTP GET 请求从服务器上请求数据。

$.post()方法通过 HTTP POST 请求从服务器上请求数据。

语法形式:

$.get(URL,callback);

$.post(URL,data,callback);

参数含义:

· 

必需的 URL 参数规定您希望请求的 URL。

· 

· 

可选的 data 参数规定连同请求发送的数据。

· 

· 

可选的 callback 参数是请求成功后所执行的函数名。

· 

 

 

1. Tomcat服务器的配置

(1)启动Eclipse for Java EE,在Window菜单中选择Preferences(首选项),如图1所示。

图1 选择首选项

(2) 在首选项窗口中(图2)选择Server->Runtime Enviroment,在窗口右侧点击Add按钮添加服务器配置。

图2 首选项窗口

(3)在弹出的New Server Runtime Environment(新建服务器运行环境)窗口中选择相应版本的Tomcat服务器,点击next按钮(图3)。

图3 新建服务器环境窗口

(4)在服务器配置窗口中点击“Browse按钮”设置tomcat的安装目录(图4)。配置完成后,点击Finish按钮结束服务器配置。

图4 Tomcat配置窗口

2. 创建Web应用

(1)在Eclipse中依次选择菜单File->New->Dynamic Web Project(图5)。

图5 创建Web工程

(2)在New Dynamic Web Project窗口中指定工程名称,选择目标服务器,点击Next按钮。

图6 新建动态web工程窗口

(3)设置缺省输出目录(图7)。

图7 设定缺省输出目录

(4)指定工程的Context root和content directory,可使用默认指定的值。并选择生成web.xml部署描述符(图8)。

图8 Web组件配置窗口

(5)可以在Project Explorer中看到已创建好的工程。

图9 工程浏览器

3. 在工程中新建JSP页面

在工程文件名或WebContent文件夹上点击鼠标右键,在右键菜单中选择New->JSP File(图10),打开新建JSP文件窗口,设置文件名保存即可。

图10 新建JSP文件

4. 运行Web页面

(1)在工程浏览器中用鼠标右键点击要运行的页面文件(图11),在右键菜单中依次选择Run As -> Run on Server。

图11 运行Web页面

(2)在Run on Server窗口中选择服务器,点击Next按钮(图12)。

图12 Run on Server配置窗口

(3)在该窗口中部署应用到服务器上,也可以从服务器上移除已部署的应用(图13),点击Finish按钮,Eclipse将自动打开内置浏览器运行相应的web应用。

图13 部署或移除应用

 

在Chrome中调试JS代码

(1)首先打开需要调试的页面,按F12快捷键打开调试工具:

在调试窗口中,所有的HTML元素都会呈现在调试窗口中:

(2)打开要调试的文件源代码并设置断点,设置方法左侧点击即可:

(3)刷新页面,当执行JS代码遇到断点时,程序暂停,可以在右侧查看对象及变量的状态和值。

在IE中调试JS代码

(1)首先打开IE浏览器,打开某个页面,按F12快捷键运行开发者工具:

(2) 选择“调试程序”,将打开程序源代码,可以设置断点,添加监视对象及变量。

(3)刷新执行页面,当执行到断点时,可以在右侧的监视区域查看已添加的监视对象,以及页面中的对象状态。

点击执行按钮可以继续执行。



  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用JSP/Servlet技术开发新闻发布系统具体步骤如下: 1. 数据库设计:首先,需要设计一个数据库用于存储新闻的相关信息,例如新闻标题、内容、发布时间等。可以使用MySQL、Oracle等关系型数据库进行设计。 2. 搭建开发环境:安装Java开发环境,并配置好相关的开发工具,例如Eclipse。 3. 创建项目:在Eclipse中创建一个基于Servlet的动态Web项目。 4. 设计前端页面:使用HTML、CSS、JavaScript等技术设计前端页面。可以设计一个新闻列表页面,用于展示已发布的新闻列表,还可以设计一个发布新闻的页面,用于输入新闻的标题和内容。 5. 实现后端逻辑:在Servlet中编写后端逻辑。可以创建一个Servlet用于处理新闻列表页面的请求,并从数据库中获取已发布的新闻列表进行展示。还可以创建一个Servlet用于处理发布新闻的请求,将新闻的标题和内容存入数据库中。 6. 配置相关路由:在web.xml文件中配置相关路由,使得前端页面的请求能够正确映射到对应的Servlet进行处理。 7. 调试和部署:对整个系统进行调试,确保功能的正常运行。之后将项目打包成war文件,部署到可以运行Java Web应用的服务器中,例如Tomcat。 8. 进一步优化:可以对系统进行进一步的优化,例如增加用户注册和登录功能,使得只有具备权限的用户才能够发布新闻。 使用JSP/Servlet技术可以实现一个简单的新闻发布系统,基本功能包括展示新闻列表和发布新闻。如果希望实现更复杂的功能,例如新闻分类、评论功能等,还需要进一步的开发和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值