Jsp1


通过Servlet进行整个网站的开发是可以的。 不过在Servlet中输出html代码,特别是稍微复杂一点的html代码,就会给人一种很````````的感觉。
如果能够直接使用Html代码,然后在html中写java代码,就好了~

JSP … 就可以干这个事情。

Hello JSP

1 在web目录下下新建一个文件hello.jsp
访问网页

http://127.0.0.1/hello.jsp
<%@page contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
 
<h1>你好 JSP</h1>
<br>
<%=new Date().toLocaleString()%>

注: 不需要重启tomcat
在这里插入图片描述
2 代码解释

<%@page contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8" import="java.util.*"%>

是JSP的<%@page指令

contentType="text/html; charset=UTF-8" 

相当于response.setContentType("text/html; charset=UTF-8"); 通知浏览器以UTF-8进行中文解码

pageEncoding="UTF-8" 

如果jsp文件中出现了中文,这些中文使用UTF-8进行编码

 import="java.util.* 

导入其他类,如果导入多个类,彼此用,逗号隔开,像这样 import="java.util.*,java.sql.*"
3 <%=

<%=new Date().toLocaleString()%>

输出当前时间,相当于在Servlet中使用response.getWriter()进行输出

response.getWriter().println(new Date().toLocaleString());

执行过程

为什么JSP可以在html中运行java代码? 这是因为JSP被转译成了Servlet

  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 响应返回给浏览器
    在这里插入图片描述

hello_jsp.java 为什么是Servlet

在Servlet章节中,我们说HelloServlet是一个Servlet,不是因为它的类名里有一个"Servlet",而是因为它继承了 HttpServlet
打开转译hello.jsp 后得到的hello_jsp.java,可以发现它继承了类(D:\tomcat\work\Catalina\localhost\_\org\apache\jsp\hello_jsp.java)

org.apache.jasper.runtime.HttpJspBase

而HttpJspBase 继承了HttpServlet
所以我们说hello_.jsp.java 是一个Servlet

页面元素

页面元素:

1. 静态内容
就是html,css,javascript等内容
2. 指令
以<%@开始 %> 结尾,比如<%@page import="java.util.*"%>
3. 表达式 <%=%>
用于输出一段html
4. Scriptlet
在<%%> 之间,可以写任何java 代码
5. 声明
在<%!%> 之间可以声明字段或者方法。但是不建议这么做。
6. 动作
<jsp:include page="Filename" > 在jsp页面中包含另一个页面。在包含的章节有详细的讲解
7. 注释 <%-- -- %>
不同于 html的注释 <!-- --> 通过jsp的注释,浏览器也看不到相应的代码,相当于在servlet中注释掉了

在这里插入图片描述

<%=%>和 <%out.println()%>

<%="hello jsp"%> 

就相当于

<%out.println("hello jsp");%>

out是jsp的隐式对象,可以直接使用。一共有9种隐式对象,参考 隐式对象 章节
注: <%=%> 不需要分号结尾,<%%> 需要以分号结尾,和java代码一样

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
 
<%="hello jsp"%>
<br>
<% out.println("hello jsp");%>

for循环

结合for循环在jsp里输出html是常见的做法。 只是第一次这么写会稍显别扭

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" import="java.util.*" %>
<html>
    <head>
        <title>第一个页面</title>
        <style>
            table{text-align: center}
        </style>
    </head>
    <body>
        <%
            List<String> words = new ArrayList<>();
            words.add("今天");
            words.add("是个");
            words.add("好日");
            words.add("子啊");
            words.add("啷哩咯啷");
        %>
        <table width="200px" align="center" border="1px" cellspacing="">
            <%for (String word:words){%>
                  <tr>
                <td><%=word%></td>
                 </tr>
        <%}%>
        </table>
    </body>
</html>

include

每个网页的最下方都有 版权声明等信息。 如果不使用包含,那么每个网页都需要单独写,如果版权声明要修改,则需要很大的工作量。
使用include的办法,只需要准备一个footer.jsp,然后在其他页面包含footer.jsp即可。
修改的时候,只需要修改footer.jsp所有的页面就都修改了,维护成本降低了很多。
include有两种方式指令include和动作include
1 准备footer.jsp

<hr>
<p style="text-align:center">copyright@2016
</p>

2 指令include
通过指令

<%@include file="footer.jsp" %>

在hello.jsp中包含该页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>   
你好  JSP
<%@include file="footer.jsp" %>

3 动作include
通过动作

<jsp:include page="footer.jsp" />

在hello.jsp中包含该页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>   
你好  JSP 
<jsp:include page="footer.jsp" />

4 指令include和动作include的区别
指令:
通过之前的学习,JSP最后会被转译成Servlet
如果是指令include

<%@include file="footer.jsp" %>

footer.jsp的内容会被插入到 hello.jsp 转译 成的hello_jsp.java中,最后只会生成一个hello_jsp.java文件
动作include

<jsp:include page="footer.jsp" />

footer.jsp的内容不会被插入到 hello.jsp 转译成的hello_jsp.java中,还会有一个footer_jsp.java独立存在。 hello_jsp.java 会在服务端访问footer_jsp.java,然后把返回的结果,嵌入到响应中
5 传参
因为指令<%@include 会导致两个jsp合并成为同一个java文件,所以就不存在传参的问题,在发出hello.jsp 里定义的变量,直接可以在footer.jsp中访问。
而动作<jsp:include />其实是对footer.jsp进行了一次独立的访问,那么就有传参的需要。
如本例:

  1. 在hello.jsp中使用动作<jsp:include,并通过<jsp:param 带上参数
<jsp:include page="footer.jsp">
	<jsp:param  name="year" value="2017" />
</jsp:include>
  1. 在footer.jsp中,使用request.getParameter("year")取出year
'hello.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>
'footer.jsp'
<hr>
    <p style="text-align:center">copyright@<%=request.getParameter("year")%>
</p>

跳转

1 首先准备 jump.jsp

客户端跳转

jsp的客户端跳转和Servlet中是一样的。

response.sendRedirect("hello.jsp");

可以通过firefox的调试工具可以观察到访问jump.jsp返回302(临时客户端跳转),跳转到了hello.jsp

<%
    response.sendRedirect("hello.jsp");
%>

服务端跳转

与Servlet的服务端跳转一样,也可以使用

request.getRequestDispatcher("hello.jsp").forward(request, response);

或者使用动作,简化代码

<jsp:forward page="hello.jsp"/>

在这里插入图片描述

cookie

cookie 在平时生活中的运用

有的网站,登陆的时候,会出现一个选项,问你是否要一周内或者一个月内保持登陆状态。
如果你选了,那么一周之内,都不需要再输入账号密码。
这个功能,就是靠cookie来实现的

什么是cookie

Cookie是一种浏览器和服务器交互数据的方式。
Cookie是由服务器端创建,但是不会保存在服务器。
创建好之后,发送给浏览器。浏览器保存在用户本地。
下一次访问网站的时候,就会把该Cookie发送给服务器。

setCookie.jsp

在web目录下创建一个文件 setCookie.jsp

Cookie c = new Cookie("name", "Gareen");

创建了一个cookie,名字是"name" 值是"Gareen"

c.setMaxAge(24 * 60 * 60);

表示这个cookie可以保留一天,如果是0,表示浏览器一关闭就销毁

c.setPath("/");

Path表示访问服务器的所有应用都会提交这个cookie到服务端,如果其值是 /a, 那么就表示仅仅访问 /a 路径的时候才会提交 cookie

response.addCookie(c);

通过response把这个cookie保存在浏览器端
访问地址:

http://127.0.0.1/setCookie.jsp

通过HTTP调试工具也可以在Cookies这一栏看到:
在这里插入图片描述

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="javax.servlet.http.Cookie"%>
<%
    Cookie c = new Cookie("name", "Gareen");
    c.setMaxAge(60 * 24 * 60);
    c.setPath("/");
    response.addCookie(c);
%>
<a href="getCookie.jsp">跳转到获取cookie的页面</a>

getCookie.jsp

在web目录下创建文件getCookie.jsp
然后访问网页:

http://127.0.0.1/getCookie.jsp
Cookie[] cookies  = request.getCookies();

表示获取所有浏览器传递过来的cookie

if (null != cookies )

如果浏览器端没有任何cookie,得到的Cookie数组是null

for (int d = 0; d <= cookies.length - 1; d++) {
   out.print(cookies[d].getName() + ":" + cookies[d].getValue() + "<br>");
}

可以看到name:Gareen,这个在setCookie.jsp中设置的cookie
注; JSESSIONID 这个不是自己设置的cookie,这是tomcat设置的cookie,会在session的学习中用到
通过HTTP调试工具也可以看到浏览器在请求信息里提交了这个Cookie。
在这里插入图片描述

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="javax.servlet.http.Cookie"%>
 
<%
    Cookie[] cookies = request.getCookies();
    if (null != cookies)
        for (int d = 0; d <= cookies.length - 1; d++) {
            out.print(cookies[d].getName() + ":" + cookies[d].getValue() + "<br>");
        }
%>

cookie原理示意图

在这里插入图片描述

session

类比

考虑这个场景:
李佳汜到健身房去练胸肌,首先领了钥匙(注册了个帐号),然后进了更衣间,把衣服,裤子,手机,钱包都放在盒子里面
毛竞也到健身房,去练翘臀。首先领了钥匙,然后 进了更衣间,把衣服,裤子,手机,《Java 21天从入门到精通》也放在了一个盒子里,但是这个盒子是和李佳汜的是不同的
健身房,就相当于服务器,盒子,就是会话Session
切换到我们常见的购物网站的场景
李佳汜登陆天猫之后,在购物车里看到的物品是蜡烛和皮鞭
毛竞登陆天猫之后,在购物车里看到的物品是手铐和《Java 21天从入门到精通》

什么是Session

Session对应的中文翻译是会话。
会话指的是从用户打开浏览器访问一个网站开始,无论在这个网站中访问了多少页面,点击了多少链接,都属于同一个会话。 直到该用户关闭浏览器为止,都属于同一个会话。

setSession.jsp

session.setAttribute("name", "teemo");

session对象保存数据的方式,有点像Map的键值对(key-value)"name"是键,“teemo” 是值

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="javax.servlet.http.Cookie"%>
<%
   session.setAttribute("name", "teemo");
%>
<a href="getSession.jsp">跳转到获取session的页面</a>

getSession.jsp

session.getAttribute("name");

通过session,根据"name" 取出对应的名称

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="javax.servlet.http.Cookie"%>
 
<%
    String name = (String)session.getAttribute("name");
%>
session中的name: <%=name%>

在这里插入图片描述

Session和Cookie的关系

回到健身房的储物柜这一段:
李佳汜和毛竞都有自己的盒子,那么他们怎么知道哪个盒子是自己的呢?
通过钥匙就能找到自己的盒子了。
盒子对应服务器上的Session。
钥匙对应浏览器上的Cookie。

Session 原理示意图

在这里插入图片描述

如果没有cookie,session如何工作

如果浏览器把cookie功能关闭,那么服务端就无法获取jsessionid,每一次访问,都会生成一个新的session对象。
为了解决这个问题,可以使用

response.encodeURL("getSession.jsp")

response.encodeURL方法会把getSession.jsp这个url转换为:

getSession.jsp;jsessionid=22424AEA86ADBE89F335EEB649D997A8

通过这个方式,提交jsessionid到服务器。 服务器根据这个jsessionid(jsessionid只是tomcat中对session id的叫法,在其它容器里面,不一定就是叫jsessionid了)匹配到对应的session. 与session相关的功能,就可以正常工作了。(cookie里的值就是jsessionid)jsessionid理解

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="javax.servlet.http.Cookie"%>
 
<%
   session.setAttribute("name", "teemo");
%>
 
<a href="<%=response.encodeURL("getSession.jsp")%>">跳转到获取session的页面</a>

session的有效期

比如登录一个网站,登录后,在短时间内,依然可以继续访问而不用重新登录。
但是较长时间不登录,依然会要求重新登录,这是因为服务端的session在一段时间不使用后,就失效了。
这个时间,在Tomcat默认配置下,是30分钟。
可以通过 d:/tomcat/conf/web.xml 中的session-config 配置进行调整

作用域

JSP有4个作用域,分别是

pageContext 当前页面
requestContext 一次请求
sessionContext 当前会话
applicationContext 全局,所有用户共享

pageContext

准备setContext.jspgetContext.jsp,分别表示向作用域设置数据,和从作用域获取数据。
pageContext表示当前页面作用域
通过pageContext.setAttribute(key,value)的数据,只能在当前页面访问,在其他页面就不能访问了。

'setContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    pageContext.setAttribute("name","gareen");
%>
 
<%=pageContext.getAttribute("name")%>
'getContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%=pageContext.getAttribute("name")%>

requestContext(表示一次请求)

requestContext 表示一次请求。随着本次请求结束,其中的数据也就被回收。
常用写法是

request.setAttribute("name","gareen"); 
request.getAttribute("name")

但是也可以用pageContext来做,写成

pageContext.setAttribute("name","gareen",pageContext.REQUEST_SCOPE);
pageContext.getAttribute("name",pageContext.REQUEST_SCOPE)

requestContext与服务端跳转

requestContext指的是一次请求
如果发生了服务端跳转,从setContext.jsp跳转到getContext.jsp,这其实,还是一次请求。 所以在getContext.jsp中,可以取到在requestContext中设置的值
这也是一种页面间传递数据的方式

'setContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    request.setAttribute("name","gareen");
%>
<jsp:forward page="getContext.jsp"/>
'getContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%=request.getAttribute("name")%>

requestContext与客户端跳转

客户端跳转,浏览器会发生一次新的访问,新的访问会产生一个新的request对象。
所以页面间客户端跳转的情况下,是无法通过request传递数据的.

'setContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    request.setAttribute("name","gareen");
    response.sendRedirect("getContext.jsp");
%>
'getContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%=request.getAttribute("name")%>

sessionContext

sessionContext 指的是会话,从一个用户打开网站的那一刻起,无论访问了多少网页,链接都属于同一个会话,直到浏览器关闭。
所以页面间传递数据,也是可以通过session传递的。
但是,不同用户对应的session是不一样的,所以session无法在不同的用户之间共享数据。

与requestContext类似的,也可以用如下方式来做

pageContext.setAttribute("name","gareen",pageContext.SESSION_SCOPE);
pageContext.getAttribute("name",pageContext.SESSION_SCOPE)
'setContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    session.setAttribute("name","gareen");
    response.sendRedirect("getContext.jsp");
%>
'getContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%=session.getAttribute("name")%>

applicationContext

applicationContext 指的是全局,所有用户共享同一个数据
在JSP中使用application对象, application对象是ServletContext接口的实例
也可以通过 request.getServletContext()来获取。
所以 application == request.getServletContext() 会返回true
application映射的就是web应用本身。
requestContext类似的,也可以用如下方式来做

pageContext.setAttribute("name","gareen",pageContext.APPLICATION_SCOPE);
pageContext.getAttribute("name",pageContext.APPLICATION_SCOPE)
'setContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    application.setAttribute("name","gareen");
    System.out.println(application == request.getServletContext());
    response.sendRedirect("getContext.jsp");
%>
'getContext.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%=application.getAttribute("name")%>

隐式对象

JSP的隐式对象指的是不需要显示定义,直接就可以使用的对象,比如request,response
JSP一共有9个隐式对象,分别是:

request,response,out
pageContext, session,application
page,config,exception

1. request,response,out

request 代表请求 请参考
response 代表响应 请参考
out 代表 输出

2. pageContext, session,application

pageContext 代表当前页面作用域
session 代表当会话作用域
application 代表当全局作用域

page

page 对象即表示当前对象
JSP 会被编译为一个Servlet类 ,运行的时候是一个Servlet实例。 page即代表this

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>   
page:<%=page%>
<br>
this:<%=this%>

在这里插入图片描述

config

config可以获取一些在web.xml中初始化的参数。
在JSP中使用config比较复杂,需要如下几个步骤

  1. web.xml中进行配置
  2. 创建一个testconfig.jsp
    通过config.getInitParameter("database-ip") 获取参数
  3. 访问路径,获取web.xml中配置的参数
http://127.0.0.1/testconfig 

注1: 不能通过 http://127.0.0.1/testconfig.jsp 获取参数,只能通过/testconfig路径
注2:这种用法不常见,不推荐使用

'web.xml'
<servlet>
    <!-- 把 testconfig.jsp配置为一个 servlet -->
    <servlet-name>testconfig</servlet-name>
    <jsp-file>/testconfig.jsp</jsp-file>
    <!-- 配置初始化参数 -->
    <init-param>
        <param-name>database-ip</param-name>
        <param-value>127.0.0.1</param-value>
    </init-param>
</servlet>
<!-- 将路径 testconfig映射到testconfig.jsp -->
<servlet-mapping>
    <servlet-name>testconfig</servlet-name>
    <url-pattern>/testconfig</url-pattern>
</servlet-mapping>
'testconfig.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
      
database-ip: <%=config.getInitParameter("database-ip")%>

exception

exception 对象只有当前页面的<%@page 指令设置为isErrorPage="true"的时候才可以使用。
同时,在其他页面也需要设置 <%@page 指令 errorPage="" 来指定一个专门处理异常的页面。

  1. 准备一个try.jsp
    设置errorPage="catch.jsp",表示有异常产生的话,就交给catch.jsp处理
    故意在里面造成数组越界异常
  2. 准备一个catch.jsp
    设置 isErrorPage="true",表示当前页面可以使用exception对象
'try.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" errorPage="catch.jsp"%>
 
<%
    int[] a = new int[10];
    a[20] = 5;
%>
'catch.jsp'
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isErrorPage="true"%>     
<%=exception%>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值