JSP是Java Server Page的缩写,在传统的HTML页面中加入JSP标签和java的程序片段就构成了JSP。JSP中脚本元素包括3类:声明语句、脚本段和JSP表达式,在JSP页面中需要通过特殊的约定来表示这些元素,在客户端这些元素是不可见的,它们都是由服务器来执行。
声明语句
声明语句在JSP页面中定义方法和变量,其声明格式如下:
<%! 声明变量或方法 %>
Eg1:<%! int count=100; %>
Eg2:<%! String getName() { return name;} %>
在页面中通过声明元素的方法和变量,在整个页面内部都有效,它们是JSP页面被转换为类文件后的方法和属性,并且它们会被多个线程(即多个用户)共享。也就是说,其中的任何一个线程对生命的变量或方法进行修改都会改变它们原来的状态。它们的生命周期从创建开始,到服务器关闭后结束。
注:
- 声明必须是完整的声明语句,遵照Java语言的语法。
- 使用声明语句的变量为全局变量,也就是说,当有多个用户在执行此JSP页面时,将共享该变量。
- 在“<%”与“!”之间不要有空格。声明的语法与在Java语言中声明变量和方法是一样的。
- 声明只在当前JSP页面中有效。
- 声明不会在当前的输入流中产生任何输出。
Eg3:
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//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>
<%!
int number =0;//声明计数变量number
void add(){//该方法用来实现计数功能
number++;
}
%>
<%
this.add();//该脚本程序调用定义的计数方法
%>
本网页的访问次数是:<%=number %>次。
</body>
</html>
或者这样写:
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//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>
<%!
int number =0;//声明计数变量number
%>
本网页的访问次数是:<%=++number %>次。
</body>
</html>
【结果】
刚执行时,页面显示是1次;刷新页面,次数逐渐增加;关闭Tomcat服务器重启启动执行,页面再次显示1次。(上面的代码还要注意一下前缀加和后缀加哦,前缀加是先返回再做加法;后缀加是先做加法再返回。所以第二个代码应该输出“++number”)
脚本段
脚本段就是JSP代码片段或脚本片段,嵌在“<%%>”标记中。在脚本段可以定义变量、调用方法和进行各种表达式运算,每行语句后面加入分号(因为在<%%>里面嵌入的Java代码和我们一般的Java代码没有什么区别,这和表达式是不同的)。使用JSP脚本元素可以将Java代码嵌入到JSP页面里,这些Java代码将出现在由当前JSP页面生成的Servlet中,使JSP将静态内容与动态内容分离出来。这种Java代码在Web服务器响应请求时会运行。在脚本段周围可以是原始的HTML或XML语句,在这些地方,代码段可以创建条件执行代码,或调用另一段代码。
脚本段使用格式如下:
<% Java代码 %>
Eg4:<%intcount=100;%>
<%%>是脚本段,它是在请求处理期间要执行的java代码段。脚本段可以产生输出,并把输出发送到客户端,也可以是一些流程控制语句。在脚本段中可以声明本地变量,在后面的脚本段中一样可以使用该变量。
Eg5:
<%@ page language="java" contentType="text/html;charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//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>
<%!
//int number =0;//声明计数变量number
%>
<%
//this.add();//该脚本程序调用定义的计数方法
int number =0;//声明计数变量number
%>
本网页的访问次数是:<%=++number %>次。
</body>
</html>
【结果】
每次访问都是1次,刷新网页没变化;关闭Tomcat服务器再重启仍然没变化。
<!% %>与<% %>的比较
二者的差异在于作用域和生存期:
①jsp声明中创建的名字有类范围的作用域和生存期
②jsp脚本中创建的名字有局限于方法的作用域和生存期。
二者的作用域就像是java中在类中定义一个属性A和在类的方法中定义一个属性B,类中不能引用属性B,但是在方法中可以引用属性A。
二者的生存期:
①jsp声明,例如:<%!int count=100;%><%=count++%>。 脚本中的变量生存期存在于第一个用户延续到第二个用户。。。。,如果第一个用户第一次访问时100,第二个用户访问就101,第三个用户访问时102,以此类推。。。如果服务器停止而重新启动后,则count值就返回到100。
②jsp脚本,例如:<%int count=100;%><%=count++%>。 脚本中的变量生存期存在于每个用户的访问期间,所以每次用户访问都是100。
无论声明和脚本放置的位置不同,jsp容器都是首先进行初始化声明,再执行脚本的。
【总结】
①不能在脚本中定义方法,但可以在jsp声明中定义自己的方法,因为脚本程序是局限于jspService方法中的,如果在jspservice方法中再次定义方法是不允许的。
②不能在jsp声明中使用out等隐藏对象,因为out等隐藏对象,是作用域jspservice方法中定义的。
③脚本中定义变量,不能在jsp声明中引用此变量。
④如果变量定义在方法中,则不能在方法之前使用此变量。
⑤脚本的本质就是将代码插入到Servlet的service()方法中。声明的本质其实就是将声明的变量加入到Servlet类(在任何方法之外),方法就成了Servlet()的方法。
【后台原理】
利用<%!%>声明的变量,在JSP容器转换JSP页面为Servlet类时,将作该类的实例变量或者类变量(声明时使用了static关键字),在多用户并发访问时,将导致线程安全的问题,除非你确认是单用户访问或者变量是只读的。(这里不讨论线程安全的问题)
而 <%%>,在JSP容器转换JSP页面为Servlet类时,页面中的代码会按照代码段中出现的次序,依次被转换为_jspService()方法中的代码,在脚本段生命的变量,将作为_jspService()方法中的本地变量,因此脚本段中的变量是线程安全的
表达式
JSP表达式用来把Java数据向页面直接输出信息,其使用格式如下:
<%=Java变量或返回值的方法名称%>
Eg6:<%=newjava.util.Date()%> //通过JSP表达式实现Date类对象,并输出当前的系统时间
Eg7:<%=a+b%> //输出a+b的值
Eg8:<%=user.getName()%> //输出getName()这个方法的返回值
表达式的本质:在将JSP页面转换成Servlet后,使用out.print()将表达式的值输出。这样如果user.getName()的返回值是"liky", 那么实际上在servlet中就将转换成out.print("liky");
注意:因此这里要注意以下两点:
①如果表达式是调用一个方法,那么这个方法必须要有返回值,而不应是void。例如:void getName(),这样的方法是不能被调用的。
②在方法的后面不能有分号。例如<%=getName();%>这是不允许的。
<%= %> 和 <% %>的比较
- <%= %>中的内容会被直接打印出来,且不允许多行和分号。而<% %>中间可以写java代码段,与java语法相同。
- <%= %> 会被解析成out.print();而<% %>中间的内容会直接解析成对应的代码段。
Eg9:
对应的java文件代码如下图所示:
上图中并没有看到关于i的声明,i在声明标签中会被声明成一个全局变量,如下图所示:
而且在servlet在服务器中是单实例,实例被创建要等到服务停掉才会销毁,而每次请求会执行其中的_jspService函数,这就意味如果用声明脚本声明了一个变量,那么在所有的服务请求中都会是同一个变量。
部分参考于:
http://www.2cto.com/kf/201607/524648.html
http://blog.youkuaiyun.com/zzh19911025/article/details/45949797
http://blog.youkuaiyun.com/yinyuan1987/article/details/3099924