SP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。JSP实际上就是Servlet。 jsp=html+java
jsp包含3个指令,6个动作,9个内置对象。
html:静态内容
servlet:服务器端的小应用程序。适合编写java逻辑代码,如果编写网页内容--苦逼。
jsp:适合编写输出动态内容,但不适合编写java逻辑。
所以开发中常使用servlet做为控制器,重点是编写java逻辑;jsp作为代码显示模板,重点是显示数据。
浏览器在访问服务器的某个应用下的jsp文件时,服务器会把这个jsp文件翻译为java文件然后编译成class文件(字节码文件),服务器底层执行字节码文件。生成的java文件和class文件存在于tomcat目录下的work/Catalina...下的项目目录中。生成时间是浏览器访问服务器的时候。
生成的java文件继承了org.apache.jasper.runtime.HttpJspBase类。而这个HttpJspBase类继承了HttpServlet类。所以我们可以说jsp就是Servlet。
服务器怎么处理jsp文件中的标签? 服务器才不会去解读html标签!他会将标签通过out.write()方法通过http协议写给客户端。如下图所示:
服务器怎么处理java代码? 直接执行,将执行结果通过out.write()方法写给客户端。
jsp建议少些java代码,纯业务逻辑写在jsp中会造成服务器做不必要的操作,我们可以在jsp中写入普通java代码,我们把业务逻辑一般写在Servlet中。例如:我们写一个Login小项目,需要与用户交互的表单页面我们用jsp写,业务逻辑如判断用户合法性我们用Servlet写。
有的时候我们的jsp中可以不含有任何的java代码,这样的文件是可以被html替代的。但是jsp的好处是,我们需要回显消息的时候,就需要在页面上接收回显消息,因为jsp可以写java代码的原因,就不再使用html了。
小脚本的格式:
<%
//脚本内容java代码
%>
表达式格式:
<%=表达式 %>
通过对编译后的java文件分析发现,表达式脚本的底层就是<% 定义变量的语句; out.write(变量) %>
比如下面两个代码块的输出是相同的:
<% int i=10;
out.print(i);
%>
<%=i%>
等于说表达式中的值在底层就是传入print()的参数中,所以定义表达式的时候结尾是不加分号的。
声明格式:
<%! %> 表示定义全局变量和静态代码块,也可以声明方法。
成员变量我们直接在<% %>中定义即可。
<%! %>是我们用来声明全局变量、创建静态代码块、声明方法的地方。
<% %>相当于是一个方法,所以不能在这里声明方法,在这里定义的变量也是局部变量。
<%=10%>相当于是out.print(10);的作用,将表达式10发送给客户端。
jsp文件中包含html的结构,当然可写html注释:。html注释可以在客户端源码中看到,是不安全的;并且是服务器write过来的,耗流量。
jsp注释:<%-- --%> 。jsp注释不能在客户端看到,是安全的。不发送给客户端,是不耗流量的。
JSP指令(directive)是为JSP引擎设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
JSP2.0规范中共同定义了三个指令:page指令、include指令、taglib指令
jsp指令基本语法格式:<%@ 指令 属性名="值" %> 如果一个指令中有多个属性,那么多个指令可以写在一个指令中,也可以写在多个指令中。例如:
例如: <%@ page contentType="text/html;charset=gb2312"%> <%@ page import="java.util.Date"%> 也可以写作: <%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%> |
jsp2.0中规定中定义page指令的完整语法(下面给出的都是默认值):
<%@ page [ language="java" ] 目前只支持java语言 [ extends="package.class" ] 因为是单继承,所以我们最好不要写这个指令,除非自己写的比HttpJspBase等类好! [ import="{package.class | package.*}, ..." ] 用来导包,多包用逗号隔开 [ session=“true | false” ]//true创建session对象 [ buffer="none | 8kb | sizekb" ] [ autoFlush="true | false" ] 是否开启自动刷新功能 [ isThreadSafe=“true | false” ] false才继承SingleThreadModel接口,线程安全问题将变量写成局部变量即可。上面方法过时了。 [ info="text" ] [ errorPage="relative_url" ] 如果网页出现500错误,跳转到指定url [ isErrorPage="true | false" ] 如果是true则导入execption包,我们可以使用exception对象操作错误信息 [ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] 告诉浏览器解码方式 contentType包含在pageEncoding中,由后者可以不写前者。 [ pageEncoding="characterSet | ISO-8859-1" ] 告诉服务器转译java文件的编码方式 [ isELIgnored="true | false" ] 是否支持EL表达式 %> |
这些我们开发的时候大多只保留pageEncoding,其他取默认就行了。导包的话也是自动的。 |
包含,有静态包含和动态包含两种。
静态包含是把其他资源包含当当前页面中,在编译(转译)之前就包含了,所以只生成了一个java文件。例如: <%@ include file="/5.jsp" %>
转译结果
bbbb...来自5.jsp文件
就生成一个java文件一个class文件,java文件中有两套html标签。
动态包含,例如:
区别:编译时间不同。
开发原则:能用动不用静。
用来导标签库。
作用:在JSP页面中导入JSTL标签库。替换jsp中的java代码片段。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> |
jsp动作的作用是:使用标签的形式来替代一段java代码,好处是可以让前端开发人员读懂,书写简答不带java思想。
|
<% Student stu = new Student(); %> |
|
<% request.getRequestDispatcher("/7.jsp").forward(request, response); %> |
指在JSP的<%=%> 和<% %>中可以直接使用的对象
对象名 |
类型 |
说明 |
request |
javax.servlet.http.HttpServletRequest |
|
response |
javax.servlet.http.HttpServletResponse |
|
session |
javax.servlet.http.HttpSession |
由session="true"开关 |
application |
javax.servlet.ServletContext |
|
exception |
java.lang.Throwable |
由isErrorPage="false"开关 |
page |
java.lang.Object当前对象this |
当前servlet实例 |
config |
javax.servlet.ServletConfig |
|
out |
javax.servlet.jsp.JspWriter |
字符输出流,相当于 printWriter对象 |
pageContext |
javax.servlet.jsp.PageContext |
通过这个对象可以得到其他8个对象 |
标红的是域对象,pageContext只在当前页面有效,所以开发时很少用。
pageContext本身也是一个域对象,他可以操作其他三个域对象,但是作用域只在当前页面有效。有三个主要方法:
void setAttribute(String name,Object o); |
设置属性名,值 |
Object getAttribute(String name); |
通过属性名获取属性值 |
void removeAttribute(String name); |
通过属性名删除属性 |
这些方法在其他页面都不好使用,pageContext提供了操作其他域对象的方法:
void setAttribute(String name,Object o,int Scope); |
Object getAttribute(String name,int Scope); |
void removeAttribute(String name,int Scope); |
scope的值在pageContext中给出了四个字段,对应四种操作方式(见名知意好吧):
PageContext.PAGE_SCOPE PageContext.REQUEST_SCOPE PageContext.SESSION_SCOPE PageContext.APPLICATION_SCOPE |
由Servlet&Http的学习中可知,request需要请求转发建立关系。
pageContext还提供了一个自动查找,找到就取值的方法:
findAttribute(String name); |
这个方法会通过名字自上而下的查找传值页面的各值setAttribute的值,匹配为null继续找下一条,直到匹配到了就得到它的值并停止查找。
PageContext : pageConext 存放的数据在当前页面有效。开发时使用较少。
ServletRequest: request 存放的数据在一次请求(转发)内有效。使用非常多。
HttpSession: session 存放的数据在一次会话中有效。使用的比较多。如:存放用户的登录信息,购物车功能。
ServletContext: application 存放的数据在整个应用范围内都有效。因为范围太大,应尽量少用。
全称是expression language 表达式语言,可以简化jsp中的java语言。不是一种开发语言,是jsp中获取数据的一种规范。EL表达式的容错性好,出现语法错误时只会空输出,不会导致500错误。
基本表达式是:${ } 底层是java代码 pageContext.findAttribute(String name) 。
比如我们需要找User类中的name属性,有两种办法:
${u.name }
${u['name']} == ${u["name"]}
[ ]的作用条件要大于“.”的,不过“.”在大多数情况下都适用。点运算符相当于是用了get方法,点后面跟的是属性名。
empty 用来判断是否为null,空字符串和空的集合都会返回null ,则表达式返回true 。
三元运算符 和java中类似,如果条件为ture执行冒号前的内容,如果条件为false则执行冒号后面的内容。
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
<%
String str1 = null;
request.setAttribute("str1", str1);
String str2 = "";
request.setAttribute("str2",str2);
String str3 = "abc";
request.setAttribute("str3", str3);
List list1 = new ArrayList();
request.setAttribute("list1", list1);
List list2 = new ArrayList();
list2.add("asdf");
request.setAttribute("list2", list2);
int sex = 0;
request.setAttribute("s", sex);
%>
${ empty str1 } ---- true
${ empty str2 } ---- true
${ empty str3 } ---- false
${ empty list1 } ---- true
${ empty list2 } ---- false
${ empty list2 ? "你还没有买商品":"你卖的商品如下" }
男
女
EL隐式对象引用名称 |
类型 |
JSP内置对象名称 |
说明 |
pageContext |
javax.servlet.jsp.PageContext |
pageContext |
一样的 |
pageScope |
java.util.Map |
没有对应的 |
pageContext范围中存放的数据,页面范围 |
requestScope |
java.util.Map |
没有对应的 |
请求范围数据 |
sessionScope |
java.util.Map |
没有对应的 |
会话范围数据 |
applicationScope |
java.util.Map |
没有对应的 |
应用范围数据 |
param |
java.util.Map |
没有对应的 |
一个请求参数 |
paramValues |
java.util.Map |
没有对应的 |
重名请求参数 |
header |
java.util.Map |
没有对应的 |
一个请求消息头 |
headerValues |
java.util.Map |
没有对应的 |
重名请求消息头 |
initParam |
java.util.Map |
没有对应的 |
web.xml中全局参数 |
cookie |
java.util.Map |
没有对应的 |
key:cookie对象的name值 |
前面已经说了,${ }的底层是pageContent.getAttribute(String name) ,那么我们现在希望使用EL表达式获取参数parameter,该怎么搞呢?
————我们使用隐式对象param获取表单中的
比如说我们需要获取userName 这个参数,那么写法为: ${param.userName } 这样的写法相当于request.getParameter(String name)。
paramValues隐式对象获取的是值对象数组,我们可以加入角标获取想要的位置元素
header可以取到消息头,比如我们要获得浏览器信息: ${header["User-agent"]}
cookie 获取cookieid的示例: ${cookie.JSESSIONID.value}
可以实现jsp页面中的逻辑处理功能。
在JSP页面添加taglib指令
使用JSTL标签
核心标签库:
> 通用标签: set、 out、 remove
> 条件标签:if choose
> 迭带标签:foreach
普通循环
迭带器
for(类型 变量名:数组或集合)
c:forEach中的varStatus属性。
指向一个字符串,该字符串引用一个对象。 map.put("vs",一个对象);
这个对象记录着当前遍历的元素的一些信息:
getIndex():返回索引。从0开始
getCount():返回计数。从1开始
isLast():是否是最后一个元素
isFirst():是否是第一个元素