JSP 文件可以只包含 HTML,也可以插入 JSP 代码,客户端发起请求后,HTML和插入的 JSP 脚本都会被翻译成 Servlet 程序,然后再编译并运行。

小脚本格式(scriptlet)

小脚本格式是指可以在 之间插入 JSP 代码:

// JSP Code

%>

JSP代码可以包含任意的Java语句、变量、方法或表达式,只要它们是有效的。

你也可以使用类似 XML 的格式插入:

// JSP Code

文本、HTML标签等都必须写在 JSP 的外边,例如:

演示页面

1+2+3+...+99+100 =

int result = 0;

for(int i=1; i<=100; i++){

result += i;

}

out.print(result);

%>

将上面的代码保存到 demo.jsp 并放到站点根目录,假设你为当前虚拟主机分配了 www.jspdemo 域名,访问 www.jspdemo:8080/demo.jsp,就可以看到输出内容。

图1  演示页面

打开 $CATALINA_HOME\\work\Catalina\www.jspdemo\_\org\apache\jsp 目录,你会看到由 JSP 翻译生成的 Servlet 程序 demo_jsp.java,部分代码如下所示:

package org.apache.jsp;

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

// demo.jsp 页面的内容被转换为 demo_jsp 类

public final class demo_jsp extends org.apache.jasper.runtime.HttpJspBase

implements org.apache.jasper.runtime.JspSourceDependent {

public void _jspInit() {

// 初始化

}

public void _jspDestroy() {

// 销毁

}

// 处理 http 请求,生成 html 代码

public void _jspService(final javax.servlet.http.HttpServletRequest request,

final javax.servlet.http.HttpServletResponse response)

throws java.io.IOException, javax.servlet.ServletException {

out.write("\r\n");

out.write("\r\n");

out.write("

\r\n");

out.write(" \r\n");

out.write("

演示页面\r\n");

out.write("\r\n");

out.write("

\r\n");

out.write("

\r\n");

out.write(" 1+2+3+...+99+100 = \r\n");

out.write(" ");

int result = 0;

for(int i=1; i<=100; i++){

result += i;

}

out.print(result);

out.write("\r\n");

out.write("

\r\n");

out.write("\r\n");

out.write("");

}

}

可以很清楚的看到 JSP 页面翻译生成的 Java 代码,在之间的代码都被放到了 _jspService() 方法内部,包括声明的变量,也是局部变量。

声明格式(declaration)

声明格式是指可以在 之间声明变量、方法和类。与小脚本格式不同的是:

声明的是局部变量,会被放到 _jspService() 方法内部。

不能声明方法,因为Java规定方法不能嵌套声明。

之间声明的是成员变量,由多线程共享。

注意: 只能用来声明变量、方法和类,不能包含表达式。

也可以使用类似 XML 的格式插入:

// JSP Code

示例代码:

演示页面

int click = 0;

%>

1+2+3+...+99+100 =

int result = 0;

for(int i=1; i<=100; i++){

result += i;

}

out.print(result);

click++;

%>

你是第位访客

生成的 demo_jsp.java 部分代码如下:

package org.apache.jsp;

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

public final class demo_jsp extends org.apache.jasper.runtime.HttpJspBase

implements org.apache.jasper.runtime.JspSourceDependent {

int click = 0;

public void _jspInit() {

// 初始化

}

public void _jspDestroy() {

// 销毁

}

public void _jspService(final javax.servlet.http.HttpServletRequest request,

final javax.servlet.http.HttpServletResponse response)

throws java.io.IOException, javax.servlet.ServletException {

out.write("\r\n");

out.write("\r\n");

out.write("

\r\n");

out.write(" \r\n");

out.write("

演示页面\r\n");

out.write("\r\n");

out.write("

\r\n");

out.write("\r\n");

out.write("

\r\n");

out.write(" 1+2+3+...+99+100 = \r\n");

out.write(" ");

int result = 0;

for(int i=1; i<=100; i++){

result += i;

}

out.print(result);

click++;

out.write("\r\n");

out.write("

\r\n");

out.write("

你是第");

out.print( click );

out.write("位访客

\r\n");

out.write("\r\n");

out.write("");

}

}

可以看到在 之间声明的 click 变量被翻译成了一个成员变量,与在 之间声明的变量作用域不同,访问权限也不同, 之间声明的变量在整个 JSP 页面内都有效。

重复访问该页面,会发现每次访客数量都会增加。

这是因为 Servlet 是单实例多线程的,成员变量在堆区分配内存,并一直存在,由多个线程共享,直到服务器关闭或JSP文件更新。而方法内的局部变量在栈区分配内存,线程结束后将被回收。

也就是说,当多个用户请求一个JSP 页面时,JSP 容器会为每个用户启动一个线程,这些线程由JSP容器来管理,这些线程共享 JSP 页面的成员变量,因此任何一个用户对 JSP 页面成员变量操作的结果,都会影响到其他用户。

demo_jsp 类只会在首次访问时被实例化,以后一直存在,新用户访问页面会启动一个线程,并使用该实例的数据,所以每次刷新页面 click 变量都会加1。

Servlet 单实例多线程的特性提高了程序的执行效率,启动一个线程的代价很小,在高并发量方面有很大的优势。但是它也有副作用,带来了线程安全问题,一个线程对数据的操作会影响到下一个线程。所以我建议,除非有必要,否则不要再 之间声明变量。

表达式格式(expression)

前面的JSP代码,输出IP地址时用到了 out.print() 语句:

其实还有一种简写,更加方便:

示例代码:

演示页面

你的IP地址是:

也可以使用类似 XML 的格式:

// JSP Code

可以认为是 out.print() 语句的简写,用来输出一个变量或表达式的值,注意结尾不能有分号(;)。

提示:

更多推荐

html添加java代码_在HTML中插入JSP代码