JSP页面基本结构:
组成元素
普通的HTML标记符
JSP标记(指令标记 动作标记)
变量和方法的声明
java程序片
java表达式
 
常用的HTML语句
<HTML>      </HTML>   表示html文件的开始和结束
<BODY>      </BODY>   表示文件的主体部分,该标记可以有BGCOLOR属性设置背景颜色。
<Hn>        </Hn>     表示标题
<P>                   表示分段
<BR>        </BR>     表示换行
<FONT>      </FONT>   表示设置字体,该标记可以有SIZE和COLOR属性
<A href=“连接的地址”> 连接提示信息     </A>
我们先举个例子
example2_1.jsp

<%@ page contentType="text/html;charset=GB2312" %>  <!-- jsp指令标记 -->
<%@ page import="java.util.Date"  %>                <!-- jsp指令标记 -->
<%!   Date date;                                   // 数据声明
      int start,end,sum;
      public int continueSum(int start,int end)    // 方法声明
      {  for(int i=start;i<=end;i++)
            sum=sum+i;
         return sum;
      }
  %>
<HTML><BODY bgcolor=cyan>                         <!—html标记 -->
<FONT size=4><P>程序片创建Date对象:
   <% date=new Date();                            //java程序片
      out.println("<BR>"+date);
      start=1;
      end=100;
      sum=continueSum(start,end);
   %>
<BR>从
   <%= start %>                                   <!-- Java表达式 -->
   至
   <%= end %>
   的连续和是
   <%= sum %>
</FONT></BODY></HTML>

 
程序的运行结果是:
 

 
这里我们可以看到,第3行和第13行,是一对标记符号<%! 和 %>,在这对标记符号中间存放 了java程序,但是我们同样发现, 13行和18行,还有一对标记符号<% 和 %> 中间同样有java程序,他们的区别是什么呢?
回想一下java中的静态(static)变量和成员变量的区别,一个类的所有对象访问的都是同一个静态变量,即其中一个变量对静态变量的改变,都会导致所有对象访问该静态变量值的变化;但是成员变量则不一样,当其中一个对象对其成员变量进行改变时,其他对象访问该成员变量的值不发生变化。简单来说,所有对象共同访问一个静态变量,但是他们各自拥有自己的成员变量。
这个就类似于静态变量和实例变量的区别,<%! 和 %> 这一对中声明的类似于static变量,访问这个JSP页面的所有用户都访问的同一个变量或方法,而<% 和 %> 就像普通的变量,每一个用户,Tomcat都会为其分配一个全新的线程和执行这部分代码。我们把在<%! 和 %>中定义的变量称为成员变量,把在<% 和 %>中的java代码成为java程序片,声明的变量称为局部变量。
 

 
 
为了更好的说明这部分,我们继续刷新这个页面,或者再开启一页,我们会发现,数字会一直增大。

sum变量在<%! 和 %> 中定义导致的程序bug


 
这就说明所有用户共享的是一个sum变量,第一个用户计算之后sum变成5050并返回,第二个用户在5050的基础上继续计算,即变成10100,如果sum是<% 和 %> 中定义的,则不会出现这种问题。
 
example2_2.jsp就是对<%!  和 %> 和<% 和 %> 的应用。
example2_2.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY BGCOLOR=cyan><FONT size=3>
  <%! int i=0;
  %>
  <% i++;
  %>
<P>您是第
   <%= i %>
  个访问本站的客户。
</BODY></HTML>

 
程序的运行结果:

 
但是这个方法会产生一个潜在的风险,就是当两个或者多个用户同时访问这个网页,多个线程同时对成员变量进行访问或者更改,往往会发生意料之外的事情,比如多个用户同时访问例2_2中的 i,那么多个用户将收到同样的 i,怎么防止这个问题的发生呢?我们使用同步代码块(synchronized)来解决这个问题,同步代码块,顾名思义,这个代码块是同步的,也就是这部分代码具有原子性(不可再分),当一个线程在同步代码块中,其他线程不允许进入同步代码块,只有当前线程离开,其他线程才可以进入。
synchronized关键字可以在方法前进行声明(如例example2_4),也可以直接使用{}来进行声明。

synchronized{
    count++;
}

 
 
example2_4.jsp

<%@ page contentType="text/html;Charset=GB2312" %>
<HTML><BODY>
    <%! int count=0;                //被客户共享的count
        synchronized void setCount()  //synchronized修饰的方法
        {   count++;
        }
    %>
    <%  setCount();
         out.println("您是第"+count+"个访问本站的客户");
    %>
</BODY></HTML>

 
程序的运行结果:
 

这个方法就是线程安全的,即在多线程的情况下,运行这个程序不会因为多线程产生一些未知bug。
 

Java表达式:

 
example2_6.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY  bgcolor=cyan><FONT size=3>
<%  double a=12.89;
    int x=12,y=10;
%>
计算表达式a+x*y-100/x+x%5的值:
  <%= a+x*y-100/x+x%5 %>
<BR>计算表达式x>y&&a>0的值:
  <%=x>y&&a>0%>
<BR>计算表达式sin(x)+cos(y):
  <%=Math.sin(x)+Math.cos(y)%>
<BR> 求8的平方根:
  <%=Math.sqrt(8)%>
</FONT></BODY></HTML>

 
我们发现,JSP代码中我们使用<%= 和 %> 中插入表达式(<%= 是一个完整的符号,他们中间不可以有空格)
 
我们看这个栗子的结果并思考,就可以理解<%= 和 %>  的用途了。
 

 

JSP中的注释:

html注释 <!- -注释内容- -> 发送到客户端,由游览器执行。
jsp注释 <%- -注释内容- -%> 引擎忽略,不发送到客户端。
(两个“-”中间没有空格,但是不加空格在这里会自动解析成一个杠,实际上是像下面代码中一样,没有空格)
 
example2_7.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY>
  <!-- 以下字体的颜色为蓝色 -->
  <FONT size=3 color=blue>抽取字符串"C:\myfile\jspfile\example.jsp"中的"example.jsp"
</FONT>
   <%-- 下面是成员变量的声明 --%>
  <%!  String s="C:\\myfile\\jspfile\\example.jsp";
  %>
  <%-- 下面是Java程序片 --%>
  <%  int index=s.lastIndexOf("\\");
      String str=s.substring(index+1);
  %>
  <BR><%-- 下面是Java表达式 --%>
  <%= str %>
</BODY></HTML>

 
我们看代码中,有两种注释,分别是橙色的HTML注释部分和红色部分的JSP注释。

在运行时,JSP引擎在处理JSP页面时,会忽略JSP注释,但是会保留HTML注释,一并发送到客户端,由客户端浏览器来解析。
为了验证这种说法,我们来访问这个页面并查看页面源码。
 

 
我们可以发现,代码中的java代码已经被执行,并只发送结果“example.jsp”到客户端,JSP注释部分也不像客户端发送,只发送了HTML注释部分。
 

JSP指令标记:

page指令标记:

page指令用来定义整个JSP页面的一些属性和这些属性的值,属性值用单引号或双引号括起来。可以用一个page指令指定多个属性的值,例如:

<%@ page 属性1 = "属性1的值"  属性2 = "属性2的值" ·····%>

或者

<%@ page 属性1 = "属性1的值"%>
<%@ page 属性2 = "属性2的值"%>
···
···
···

page指令的作用对整个JSP页面有效,与其书写的位置无关。习惯上把page指令写在JSP页面的最前面。
page指令标记可以指定如下属性值:
contentType、import、language、session、buffer、auotFlush、isThreadSafe。
1.contentType 属性
contentType属性值确定JSP页面响应的MIME类型和JSP页面字符的编码。

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

这里MIME类型是text/html,JSP页面字符编码是GB2312。
MIME的作用是告诉用户浏览器以什么形式来解析服务器发过来的信息,编码则指定信息的编码方式。
这里比如我们将example2_7.jsp的contentType属性的MIME值改成application/msword,我们再次访问这个页面。

浏览器以word形式解析,我们打开之后发现依然是网页显示的那些东西,只不过是以word形式解析。
page属性还有:text/html, text/plain, image/gif, image/x-xbitmap, image/jpeg, application/msword 等。
2.language 属性
该属性定义JSP页面使用的语言,该属性值目前只能取java。
3.import 属性
该属性的作用是为JSP页面因为Java运行环境提供包中的类;可以为该属性制定多个值,该属性的值可以使某包中的所有类或者一个具体的类。有两种声明方式。

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

或者

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

 
4.session 属性
该属性用于设置是否需要使用内置的session对象。默认是true。
5.buffer 属性
该属性用来指定out设置的缓冲区的大小或者不使用缓冲区。例如

<%@ page buffer = "24KB" %>

buffer的默认值是8KB,还可以设置为“none”,即不设置缓冲区。
6.autoFlush 属性
该属性指定out缓冲区被填满时,是否自动刷新,默认值true。
当autoFlush为flase时,当缓冲区被填满,会产生内存溢出。
当buffer设置为“none”时,不允许设置autoFlush为flase。
7.isThreadSafe 属性
该属性用来设置JSP页面是否可以多线程访问,默认值为true。
当isThreadSafe为true时,允许多个用户同时访问该页面,当isThreadSafe为flase时,同一时刻只允许一个用户访问JSP页面,其他用户必须排队等待。
8.info 属性
该属性的属性值是一个字符串,其目的是为了JSP页面准备一个常用但可能要经常修改的字符串。例如,

<%@ page info = "we are students" %>

可以在JSP页面中使用方法:
getServletInfo();
来获取info属性的属性值。
example2_9.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%@ page info="清华大学" %>
<%  String s=getServletInfo();
%>
<head>  <%= s %></head>
<HTML><BODY  bgcolor=white><FONT Size=4>
<BR><%=s %>出版社是中国著名出版社
<BR><%=s %>是全国著名的高等学府
</BODY><HTML>

 
运行之后是这样的

我们看到info属性后面是“清华大学”,我们使用String s=getServletInfo();就可以获取到Info属性里面的字符串,这个方法一般用来准备一个常用但可能要经常修改的字符串。
 

include指令标记

如果需要在JSP页面内某处整体嵌入一个文件,就可以考虑使用include指令标记,其语法格式如下:

<%@ include file="文件的URL"%>

 
它的作用就是在该指令出现的地方,静态的插入一个文件,被插入的文件必须是可以访问或者可以使用的,并且文件插入后不会导致JSP语法错误(比如新插入的文件的contentType属性为application/msword,而原页面的属性为text/html,这样就会产生两个contentType属性,导致语法错误。)有点类似于方法的调用,该标记目的是提高代码的复用性,比如多个页面都需要同一个功能,那么在多个页面中只要include功能文件即可。比如下面这个栗子。
假如我们需要一个网站导航,点击可以跳转到相应的页面,导航部分代码如下:
在根目录下新建文件夹myfile,并新建ok.jsp。
ok.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<center>
<A href = "example2_10_a.jsp">北京大学</A>
<A href = "example2_10_b.jsp">清华大学</A>
<p>

实际上,这个文件可以是任何可以访问的类型,只要是jsp语法即可,ok.txt 甚至ok.xml都行。
<A href = “example2_10_b.jsp”>清华大学</A> 这句话我们之前也提过,是专门用来跳转的语句(<A href=“连接的地址”> 连接提示信息 </A>)
 
我们再写include这个页面的jsp页面。
example2_10_a.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%@ include file="myfile/ok.jsp" %>
<HTMLl><BODY bgcolor=white>
<P>我是北京大学的jsp页面
</BODY></HTML>

 
example2_10_b.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%@ include file="myfile/ok.jsp" %>
<HTML><BODY bgcolor=yellow>
<P>我是清华大学的jsp页面
</BODY></HTML>

 
现在我们访问这两个页面任意一个。

我们发现上面有两个链接“北京大学”,和“清华大学”,和我们在后面加的文字“实际上这里可以直接打上你需要的文字”,我们点击清华大学,跳转到如下页面,我们发现导航栏依然在。
 

 
这种插入方式成为静态插入,即JSP引擎在编译原页面时,会将两个页面组合成一个新页面最终转移成字节码文件。也就是实际上example2_10_a.jsp这个页面的字节码文件已经包括了导航部分,JSP引擎在编译example2_10_a.jsp页面时,就将ok.jsp与example2_10_a.jsp合二为一并保存。
 

JSP动作标记

include、param动作标记
他们的语法格式是:

<jsp:include page="文件的URL">
     <jsp:param name="名字" value="指定给param的值"/>
     ···
     ···
   </jsp:include>

 
该标记可以将param中的值传递到include动作要加载的文件中去,被加载的JSP页面可以使用内置方法request获取param的值。

example2_11.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY  bgcolor=white >
<% double a=3,b=4,c=5;
%>
<BR>加载triangle.jsp计算三边为<%=a%>,<%=b%>,<%=c%>的三角形面积:
   <jsp:include page="myfile/triangle.jsp">
     <jsp:param name="sideA" value="<%=a%>"/>
     <jsp:param name="sideB" value="<%=b%>"/>
     <jsp:param name="sideC" value="<%=c%>"/>
   </jsp:include>
</BODY></HTML>

 
我们在根目录下的myfile中新建triangle.jsp
triangle.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%! public String getArea(double a,double b,double c)
     { if(a+b>c&&a+c>b&&c+b>a)
        {   double p=(a+b+c)/2.0;
            double area=Math.sqrt(p*(p-a)*(p-b)*(p-c)) ;
            return ""+area;
        }
      else
        {  return(""+a+","+b+","+c+"不能构成一个三角形,无法计算面积");
        }
    }
 %>
 <%   String sideA=request.getParameter("sideA");
       String sideB=request.getParameter("sideB");
       String sideC=request.getParameter("sideC");
       double a=Double.parseDouble(sideA);
       double b=Double.parseDouble(sideB);
       double c=Double.parseDouble(sideC);
 %>
 <Font color=blue size=4>
 <P>我是被加载的文件,负责计算三角形的面积<BR>
    给我传递的三边是:<%=sideA%>,<%=sideB%>,<%=sideC%>
 <BR>三角形的面积:<%= getArea(a,b,c)%>
 </Font>

 
我们访问example2_11.jsp页面,发现已经显示了跳转页面中的结果。

triangle打错了,懒的去重新截图上传了emmm


 
动作标记是动态的,不是在编译过程中加入的,而是在执行过程中,由引擎根据文件格式的不同(如果是文本文件直接发送到客户端,如果是JSP文件则本地执行发送结果),动态的执行。
所以这里的triangle.jsp文件就必须是.jsp文件,如果是其他格式的文件,会直接发送到客户端而不执行(浏览器显示代码),上个栗子中ok.jsp之所以可以是很多格式是因为静态插入时,JSP引擎在编译时将ok.jsp合并入了那两个页面变成一个页面了。
 

静态插入和动态插入的区别:

尽管他们的作用都是处理所需要的文件,但是处理方式和处理时间是不同的。include指令标记(静态)是在编译阶段就处理所需要的文件,被处理的文件在逻辑和语法上依赖于当前的JSP文件,其优点是页面的执行速度快。include动作标记(动态)是在JSP页面运行时再处理文件,被处理的文件在逻辑和语法上独立于当前的JSP页面,其优点是可以使用param子标记更灵活地处理所需要的文件,缺点是执行速度慢一些。
 

forward 动作标记

语法格式:

<jsp:forward page:"要转向的页面"/>
或者
<jsp:forward page:"要转向的页面">
    <jsp:param name="名字" value="值">
    ···
    ···
</jsp:forward>

 
当没有param子标记时必须使用第一种格式。
该指令的作用是:从该指令处停止当前页面的执行,而转向执行page属性指定的JSP页面。
 
example2_12.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY>
<%  double i=Math.random();
    if(i>0.5)
    {
%>  <jsp:forward page="/myfile/frontSide.jsp" >
          <jsp:param name="number" value="<%= i %>" />
     </jsp:forward>
<%  }
   else
    {
 %>  <jsp:forward page="/myfile/reverseSide.jsp" >
          <jsp:param name="number" value="<%= i %>" />
      </jsp:forward>
 <% }
 %>
</BODY></HTML>

 
在myfile中新建
frontSide.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white><Font size=3>
 <% String s=request.getParameter("number");
    out.println("<BR>传递过来的值是"+s);
 %>
 <BR>这是另一个页面
</FONT></BODY></HTML>

 
receiveSide.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white><Font size=3>
 <% String s=request.getParameter("number");
    out.println("传递过来的值是"+s);
 %>
 <BR>这是一个页面
</FONT></BODY></HTML>

 
我们访问127.0.0.1:8080/example2_12.jsp

 
或者
 

 
需要注意的是,当前页面使用forward动作标记转向后,尽管用户看到了转向后的页面的效果,但是浏览器的地址栏依然是转向前的JSP页面,因此,如果刷新当前页面,会回到转向前的页面。
 

useBean 动作标记

见JSP与javaBean。
 

课后题:

1.”<%!”和”%>”之间声明的变量与.”<%”和”%>”之间声明的变量有何不同?
·   <%! %>之间声明的变量和方法在整个jsp页面内都有效,也就是说可以理解为<%! %>之间声明的是全局的变量和方法,方法可以被公有使用,变量则可以被所有方法调用改变。当有运行多个线程时,任何一个线程对jsp页面成员变量操作的结果,都会影响其他线程。
在<% %>之间声明的变量则为“局部变量”,当运行多个线程时,不同线程中的java程序片的局部变量互不干扰,也就是说一个用户改变java程序片中的局部变量的值不会影响下一个用户java程序片中的局部变量。
2.如果有两个用户访问一个JSP页面,该页面中的java程序片将被执行几次?
·    两次。(java程序片特指<% %>中的java语句)
3.是否允许JSP页面同时含有如下两条page指令:<%@ page contentType=”text/html;charset=gb2312″ %>、<%@ page contentType=”application/msword” %>
·    不允许。
4.是否允许JSP页面同时含有如下两条page指令:<%@ page import=”java.util.*” %>、<%@ page import=”java.sql.*” %>
·    允许。
5.假设有两个用户访问下列JSP页面hello.jsp,请问第一个访问和第二个访问hello.jsp页面的用户看到的页面的效果有何不同?
hello.jsp

<%@ page contentType="text/html;charset=gb2312" %>
<%@ page isThreadSafe="flase" %>
<HTML><BODY>
    <%! int sum = 1;
        void add(int m){
            sum = sum+m;
        }
%>
<%      int n = 100;
        add(n);
%>
<%=sum%>
</BODY></HTML>

·    第一个用户看到的是101,第二个用户看到的是201。
6.请编写一个简单的JSP页面,显示英文字母表。

<%@ page contentType="text/html;charset=gb2312" %>
<%
  char letter = 'a';
  for(int i=0;i<26;i++){
    out.println((char)(letter+i));
  }
  %>
  <BR>
<%
  letter = (char)(letter-32);
  for(int i=0;i<26;i++){
    out.println((char)(letter+i));
  }
%>

 
7.请简单叙述include指令标记和include动作标记的不同。
·    include指令标记是在编译阶段就处理所需要的文件,被处理的文件在逻辑和语法上依赖于当前的JSP文件,其优点是页面的执行速度快。include动作标记是在JSP页面运行时再处理文件,被处理的文件在逻辑和语法上独立于当前的JSP页面,其优点是可以使用param子标记更灵活地处理所需要的文件,缺点是执行速度慢一些。
8.编写三个JSP页面:main.jsp、circle.jsp和ladder.jsp,将三个JSP页面保存在Web服务器目录中。main使用include动作标记加载circle和ladder页面。circle页面可以计算并显示圆的面积,ladder页面可以计算并显示梯形的面积。当circle和ladder被加载时获取main页面include动作标记的param子标记提供的圆的半径以及提醒的上底、下底和高的值。
main.jsp

<%@ page contentType="text/html;charset=gb2312" %>
<%
  int r = 3;
  int upper = 1,lower = 2,high = 1;
%>
<jsp:include page="/myfile/circle.jsp">
  <jsp:param name="r" value="<%=r%>"/>
</jsp:include>
<jsp:include page="myfile/ladder.jsp">
  <jsp:param name="upper" value="<%= upper%>"/>
  <jsp:param name="lower" value="<%= lower%>"/>
  <jsp:param name="high" value="<%= high%>"/>
</jsp:include>

 
circle.jsp

<%@ page contentType="text/html;charset=gb2312" %>
<%!
  public double compute(int r){
    return r*r*3.14159265;
  }
%>
<%
  String r = request.getParameter("r");
  int a = Integer.parseInt(r);
  double area = compute(a);
%>
<frot color=blue size=2>
<br>
圆的面积是<%=area%>

 
ladder.jsp

<%@ page contentType="text/html;charset=gb2312" %>
<%!
  double compute(int upper,int lower,int high){
    return (upper+lower)*high/2;
  }
%>
<%
  String upper = request.getParameter("upper");
  String lower = request.getParameter("lower");
  String high = request.getParameter("high");
  double area = compute(Integer.parseInt(upper),Integer.parseInt(lower),Integer.parseInt(high));
%>
<frot color=blue size=2>
<br>
梯形的面积是<%=area%>

 

 

分类: JSP

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注