揣测:当客户端访问 JSP 文件时,Tomcat 对 JSP 文件进行分析,按一定规则,将其转化成对应的 java 文件及 class 文件。
JSP 文件修改后,只有客户端第一次访问的时候才会被转化,且后续只要不修改就不会转化。
一、嵌入方式
1、
<%
int i;
javacode();
%>
- 此法相当于将代码嵌入到 service 方法中
在没有语法提示的环境下,一定要注意后面的 分号 ,转化成 java 代码的时候后面没分号肯定会出错的。
2、声明语句
<%! int var2=9; %>
- 此法声明的变量,在生成 java 代码的时候,生成为类的成员变量,在 servlet 中,类只生成一个实例,所以多个页面访问此变量都是同一个变量。
public final class _3_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
int var2=9;
}
3、输出语句
<%= i%>
- 此法相当于在 service 方法中生成
out.print(i);
因此, 中间的内容必须可以转化成 String 类型
注意这里不能加 分号 ' ; ' 会转化成out.print(i;);
4、注释
<%--
int i;
--%>
<%
//int i;
%>
<%
/*
int i;
*/
%>
- 以上三种方法生成 java 文件中的注释,因而不会显示到客户端的HTML页面中
二、编译指令 Directive
<%@Directive 属性="属性值" %>
1、page :指明页面的一些配置
- import
- 是否自动 SESSION
- 此页面是否是 errorPage
- 页面出错返回其他的页面
- 属性不只这些
<%@page import="bean.*"|
session="true"|
isErrorPage="false"|
errorPage="errorPageUrl/xx.jsp"
%>
2、include : 将其他 jsp 或 HTML 包含进来(编译期)
<%@ include file="fileUrl/xx.jsp"%>
相当于把其他文件中的内容原封不动的在这个位置导入进来,编译是和本文件一起编译的
三、jsp:
1、jsp:include : 将其他 jsp 或 HTML 包含进来(运行时)
<jsp:include page="4.jsp" flush="true">
<jsp:param name="paramName" value="valueName"></jsp:param>
</jsp:include>
- 运行时将请求的页面结果包含进来,可以向页面传参
相当于在运行到这里时访问"4.jsp?paramName=valueName"
然后将得到的结果插到这个位置
2、jsp:forward
<jsp:forward page="4.jsp" flush="true">
<jsp:param name="paramName" value="valueName"></jsp:param>
</jsp:forward>
- 比如在 3.jsp 中写这样的代码,相当于服务器去访问 4.jsp ,然后将访问 4.jsp 的结果返回给客户端,而且 3.jsp 和 4.jsp 是同一个 request (通过 3.jsp 传递的参数也可以被 4.jsp 使用),观察实际成的java代码
// 对应代码
if (true) {
_jspx_page_context.forward("4.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("paramName", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("valueName", request.getCharacterEncoding()));
return;
}
// _jspx_page_context 来源
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8888, true);
_jspx_page_context = pageContext;
与重定向区别
response.sendRedirect("4.jsp");
- 这段代码是告诉客户端,“你别找我了,你自己去找 4.jsp 吧”,然后客户端会自己重新发起个对 4.jsp 的请求,request 不相同
3、jsp:useBean
声明
<jsp:useBean id="beanName" class="bean.BeanClass" scope="page|request|session|application" type="typeName"/>
其逻辑如下
- 通过 useBean 可以获得一个类的实例
scope 指定了此类存在的范围,首先以 id 为标志,通过范围指定的对应的 getAttribute 方法,看看是否有一个已经存在的实例 ,如 session.getAttribute("beanName") - 如果没有找到就
new
一个,并用存储在 scope 对应范围中
typeName beanName=new bean.BeanClass();
session.setAttribulte("beanName",beanName);
对于:
<jsp:useBean id="beanName" class="bean.BeanClass" scope="page|request|session|application" type="typeName"/>
id : 变量名
class : new 的 class 类型,因为这个生成 java 代码的时候,调用的是 无参的构造方法,new bean.BeanClass(),
所以,写 BeanClass 的时候一定要写好 无参构造方法
type : 声明的变量类型
<jsp:useBean id="daJinMao" class="bean.Dog" scope="page|request|session|application" type="Animal"/>
Animal daJinMao=new Dog();
实际对应生生成的 Java 代码如下
bean.CounterBean beans = null;
beans = (bean.CounterBean) _jspx_page_context.getAttribute("beans", javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (beans == null){
beans = new bean.CounterBean();
_jspx_page_context.setAttribute("beans", beans, javax.servlet.jsp.PageContext.PAGE_SCOPE);
}
set
<jsp:setProperty name="beans" property="count" value="23" />
- 调用 实例的成员变量对应的 set 方法,为成员变量赋值,相当于
beans.setCount(23);
实际生成的 java 代码
org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("beans"), "count", "23", null, null, false);
如果 beans.setCount(int count) 的话,是怎么确定要把 String 转成 int 的???
猜测内部是 beans.setCount(Integer.parseInt("23"))
get
<jsp:getProperty name="beans" property="count"/>
- 调用 实例的成员变量对应的 get 方法,获取成员变量的值,相当于
out.write(beans.getCount());
实际生成的 java 代码
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((bean.CounterBean)_jspx_page_context.findAttribute("beans")).getCount())));
关于 set 和 get
可以看到,对于 beans 的成员变量 count ,获取值实际调用的是 getCount() ,(赋予值猜测调用的应该也是 setCount())
所以 BeanCount 类一定要有 count 对应符合格式的 set、get 方法
网上见到的一种写法
<jsp:useBean id="beans" class="bean.CounterBean" >
<jsp:setProperty name="beans" property="count" value="23" />
<jsp:getProperty name="beans" property="count"/>
</jsp:useBean>
试验实际生成 java 代码如下
bean.CounterBean beans = null;
beans = (bean.CounterBean) _jspx_page_context.getAttribute("beans", javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (beans == null){
beans = new bean.CounterBean();
_jspx_page_context.setAttribute("beans", beans, javax.servlet.jsp.PageContext.PAGE_SCOPE);
out.write("\r\n");
out.write(" ");
org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("beans"), "count", "23", null, null, false);
out.write("\r\n");
out.write(" ");
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((bean.CounterBean)_jspx_page_context.findAttribute("beans")).getCount())));
out.write("\r\n");
out.write(" ");
}
可以看到如果 beans 不为空的话, set 、get 将得不到执行
4、jsp:setProperty 关联客户端请求参数
- 将客户端请求中,参数名为 count 的值,赋给 beans.count ,
bean.setCount(请求中 参数名也为 count 的值)
<jsp:setProperty name="beans" property="count" />
- 将客户端请求中,参数名 为 num 的值,赋给 beans.count
<jsp:setProperty name="beans" property="count" param="num" />
- 将客户端的请求参数的名字与 beans 成员变量名字相匹配,将值一一赋给 beans 的成员变量
注意:请求参数的名字不能出错,实际测试写错了并不会弹出 error 页面
<jsp:setProperty name="beans" property="*" />
网友评论