之前的servlet里面输出html代码显得十分的麻烦,jsp呢就可以实现在html里面写代码啦。
不过听说jsp已经过时了,我也就过了一遍,算是了解了解咋用的吧。
执行过程
1. 把 hello.jsp转译为hello_jsp.java
2. hello_jsp.java 位于
d:\tomcat\work\Catalina\localhost\_\org\apache\jsp
3. hello_jsp.java是一个servlet
4. 把hello_jsp.java 编译为hello_jsp.class
5. 执行hello_jsp,生成html
6. 通过http协议把html 响应返回给浏览器
页面元素
jsp由这些页面元素组成:
1. 静态内容
就是html,css,javascript等内容
2. 指令
以<%@开始 %> 结尾,比如<%@page import="java.util.*"%>
3. 表达式 <%=%>
用于输出一段html, 里面的内容不用分号结尾 相当于<%out.println("")%>
4. Scriptlet
在<%%> 之间,可以写任何java 代码,需要分号结尾
5. 声明
在<%!%> 之间可以声明字段或者方法。但是不建议这么做。
6. 动作
<jsp:include page="Filename" > 在jsp页面中包含另一个页面。
7. 注释 <%-- -- %>
不同于 html的注释 <!-- --> 通过jsp的注释,浏览器也看不到相应的代码,相当于在servlet中注释掉了
include
比如之前写前端的时候,把页面合并起来的时候很麻烦,如果用include就很方便了,比如页脚,就在每个网页的下面写上一句:
<%@include file="footer.jsp" %>
就可以啦。
上面这样写的叫指令include,特点是:footer.jsp的内容会被插入到 hello.jsp 转译 成的hello_jsp.java中,最后只会生成一个hello_jsp.java文件,相当于合并了,那么页面中的参数,footer里面也可以使用,不存在传参的问题。
对应的,还有一种叫动态include:
<jsp:include page="footer.jsp" />
动态include的特点是:
footer.jsp的内容不会被插入到 hello.jsp 转译 成的hello_jsp.java中,还会有一个footer_jsp.java独立存在。 hello_jsp.java 会在服务端访问footer_jsp.java,然后把返回的结果,嵌入到响应中。相当于对footer.jsp进行了一次独立的访问,那么就会有传参的问题啦。
<%@page contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
你好 JSP
<%=new Date().toLocaleString()%>
<jsp:include page="footer.jsp">
<jsp:param name="year" value="2017" />
</jsp:include>
服务端跳转和客户端跳转
和之前servlet的跳转一样,jsp的跳转也分为服务端跳转和客户端跳转,
客户端跳转,和servlet的一样:
response.sendRedirect("hello.jsp");
临时的跳过去了。
服务端跳转(路径不变):
request.getRequestDispatcher("hello.jsp").forward(request, response);
也可以简化的,还可以用上面的传参方式进行传参:
<jsp:forward page="hello.jsp"/>
Cookie
创建一个cookie,名字是"name" 值是"Gareen"
Cookie c = new Cookie("name", "Gareen");
表示这个cookie可以保留一天,如果是0,表示浏览器一关闭就销毁
c.setMaxAge(24 * 60 * 60);
Path表示访问服务器的所有应用都会提交这个cookie到服务端,如果其值是 /a, 那么就表示仅仅访问 /a 路径的时候才会提交 cookie
c.setPath("/");
通过response把这个cookie保存在浏览器端
response.addCookie(c);
Session会话
会话指的是从用户打开浏览器访问一个网站开始,无论在这个网站中访问了多少页面,点击了多少链接,都属于同一个会话。 直到该用户关闭浏览器为止,都属于同一个会话。
session对象保存数据的方式,有点像Map的键值对(key-value)
"name"是键,"teemo" 是值
<%
session.setAttribute("name", "teemo");
%>
辨认会话的方式是通过把jsesionid保存在cookie,如果客户端禁止了cookie,那么可以用response.encodeURL(),把url转换成jsesionid,以此辨认。
<%
session.setAttribute("name", "teemo");
%>
<a href="<%=response.encodeURL("getSession.jsp")%>">跳转到获取session的页面</a>
四种作用域
1、pageContext 当前页面作用域,设定的数据只能在当前页面使用,其他页面不行。
2、requestContext 表示一次请求作用域,随着本次请求的结束,作用域也结束啦。
要注意的是,如果发生服务端跳转,浏览器并没有产生新的请求,本次的请求作用域也就没有结束,这个操作可以用来实现页面间的数据传输,但是如果发生了客户端跳转,浏览器会产生新的请求,作用域就结束了。
3、sessionContext 会话作用域,一次会话内都可以数据交换。
4、applicationContext 全局作用域,所有用户使用同一个数据。
9个隐式对象
JSP的隐式对象指的是不需要显示定义,直接就可以使用的对象,比如request,response
JSP一共有9个隐式对象,分别是
request,response,out
pageContext, session,application
page,config,exception
前六个都熟悉了。
page: 表示当前对象,相当于java中的this
config:可以获取一些在web.xml中初始化的参数。 站长说不推荐用,不管了。
exception:用来抛出异常的。
可能出现异常的页面加上指令:errorPage="异常抛出页面.jsp"
只有准备好的异常抛出页面的<%@page 指令设置为isErrorPage="true"的时候才可以使用。
JSTL
JSTL JSP Standard Tag Library 标准标签库
可以像html标签那样,在jsp中使用java语言。
在页面中使用JSTL需要在jsp中 通过指令进行设置
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
prefix="c" 表示后续的标签使用都会以<c: 开头
<c:set var="name" value="${'gareen'}" scope="request" />
在作用域request中设置name,相当于
<%request.setAttribute("name","gareen")%>
<c:out value="${name}" />
相当于
<%=request.getAttribute("name")%>
<c:remove var="name" scope="request" />
在作用域request中删掉name,相当于
<%request.removeAttribute("name")%>
if判断,要注意的是没有else可以用,一般是在判断条件上取反:
配合if使用的还有通过empty进行为空判断
empty可以判断对象是否为null,字符串长度是否为0,集合长度是否为0
<c:if test="${hp<5}">
<p>这个英雄要挂了</p>
</c:if>
<c:if test="${!(hp<5)}">
<p>这个英雄觉得自己还可以再抢救抢救</p>
</c:if>
for循环:
<c:forEach items="${heros}" var="hero" varStatus="st" >
items="${heros}" 表示遍历的集合
var="hero" 表示把每一个集合中的元素放在hero上
varStatus="st" 表示遍历的状态,st.count就相当于计数器了。
还有字符串拆分forTokens, 格式化数据:formatNumber格式化数字,formatDate格式化日期,fn等标签,用到再查。
EL表达式
站长说el表达式超级好用
为了保证EL表达式能够正常使用,需要在<%@page 标签里加上isELIgnored="false"
输出: ${name}
EL表达式可以从pageContext,request,session,application四个作用域中取到值
EL会按照从高到低的优先级顺序获取
pageContext>request>session>application
EL可以很方便的访问JavaBean的属性
JavaBean的标准
1. 提供无参public的构造方法(默认提供)
2. 每个属性,都有public的getter和setter
3. 如果属性是boolean,那么就对应is和setter方法
获取JavaBean的属性,只需要通过.符号操作就可以了。
像这样
${hero.name} ,
就会自动调用getName方法了
还可以结合JSTL的forEach使用,比如原来的输出<c:out value="${hero}" /> ,现在就直接${name}就行了
取参:${param.name}
还能写三元表达式:
eq相等 ne、neq不相等,
gt大于, lt小于
gt大于, lt小于
gte、ge大于等于
lte、le 小于等于
not非 mod求模
is [not] div by是否能被某数整除
is [not] even是否为偶数
is [not] odd是否为奇
${killNumber ge 10? "超神":"还没超神" }