Java进阶学习第六天(Jsp)

一、 Jsp基础

1、Jsp引入
① Servlet的作用: 用java语言开发动态资源的技术!!!
② Jsp的作用:用java语言(+html语言)开发动态资源的技术!!!
Jsp就是servlet!

2、Jsp的特点
① jsp的运行必须交给tomcat服务器!
tomcat的work目录: tomcat服务器存放jsp运行时的临时文件
① jsp页面既可以写html代码,也可以写java代码
(html页面不能写java代码,而jsp页面可以写java代码)

3、体验jsp页面作用
需求:显示当前时间到浏览器上
可以把jsp页面当做html页面在tomcat中访问!!!

<%@ page language="java" import="java.util.*,java.text.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head> 
    <title>第一个jsp页面</title>  
  </head>
  <body>
    <%
        //写java代码
        //获取当前时间
        SimpleDateFormat sdf = new SimpleDateFormat();
        String curDate = sdf.format(new Date());
        //输出内容到浏览器
        //response.getWriter().write("");
        out.write("当前时间为2:"+curDate);
     %>
  </body>
</html>

4、Jsp的执行过程
问题: 访问http://localhost:8080/day12/hello.jsp 如何显示效果?

① 访问到01.hello.jsp页面,tomcat扫描到jsp文件,在%tomcat%/work把jsp文件翻译成java源文件:(hello.jsp > _hello_jsp.java) (翻译)
② tomcat服务器把java源文件编译成class字节码文件 :(_hello_jsp.java > _hello_jsp.class)(编译)
③ tomcat服务器构造_hello_jsp类对象
④ tomcat服务器调用_hello_jsp类里面方法,返回内容显示到浏览器

第一次访问jsp:走①②③④
第n次访问jsp:走④

注意:jsp文件修改了或jsp的临时文件被删除了,就要重新走翻译①和编译②过程

5、问题: 为什么Jsp就是servlet!!!

jsp翻译的java文件:
public final class _hello_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent {}

HttpJspBase类:
public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage {}

结论: Jsp就是一个servlet程序!!!
servlet的技术可以用在jsp程序中,jsp的技术并不是全部适用于servlet程序!

Servlet的生命周期:
    1)构造方法(第1次访问)
    2)init方法(第1次访问)
    3)service方法
    4)destroy方法     
Jsp的生命周期
    1)翻译: jsp->java文件
    2)编译: java文件->class文件(servlet程序)
    3)构造方法(第1次访问)
    4)init方法(第1次访问):_jspInit()
    5)service方法:_jspService()
    6)destroy方法:_jspDestroy()

6、Jsp语法
① Jsp模板:jsp页面中的html代码就是jsp的模板
② Jsp表达式
◆ 语法:<%=变量或表达式%>
◆ 作用: 向浏览器输出变量的值或表达式计算的结果
◆ 注意:
◇ 表达式的原理就是翻译成out.print(“变量”);通过该方法向浏览器写出内容
◇ 表达式后面不需要带分号结束
③ Jsp的脚本
◆ 语法:<%java代码 %>
◆ 作用: 执行java代码
原理:就是把脚本中java代码原封不动拷贝到_jspService方法中执行

 <!-- 练习: 使用脚本和html代码显示99乘法表 -->
<%
    for(int i=1;i<=9;i++){//行
        for(int j=1;j<=i;j++){//公式
%>          
    <%=i %> x <%=j %>=<%=(i*j) %>&nbsp;
<%          
    }
%>
<br/>
<%  
    }
%>

④ Jsp的声明
◆ 语法:<%! 变量或方法 %>
◆ 作用: 声明jsp的变量或方法
注意:变量翻译成成员变量,方法翻译成成员方法
⑤ Jsp的注释
◆ 语法: <%!--jsp注释--%>
注意:html的注释<!--html注释-->会被翻译和执行,而jsp的注释不能被翻译和执行

7、Jsp的三大指令
① include指令
◆ 作用: 在当前页面用于包含其他页面
◆ 语法: <%@include file="common/header.jsp"%>
◆ 注意:
◇ 原理是把被包含的页面(header.jsp)的内容翻译到包含页面(index.jsp)中,合并成翻译成1个java源文件,再编译运行,这种包含叫静态包含(源码包含)
◇ 如果使用静态包含,被包含页面中不需要出现全局的html标签了!(如html、head、body)
② page指令
◆ 作用: 告诉tomcat服务器如何翻译jsp文件
注意:在开发工具中,以后只需要设置pageEncoding即可解决中文乱码问题

<%@ page 
    language="java"   -- 告诉服务器使用什么动态语言来翻译jsp文件
    import="java.util.*" -- 告诉服务器java文件使用什么包;多个包的导入之间用逗号分割

    pageEncoding="utf-8"  -- 告诉服务器使用什么编码翻译成jsp文件
    contentType="text/html; charset=utf-8" -- 服务器发送浏览器的数据类型和内容编码,这个属性可以省略,如果不写就参考pageEncoding

    errorPage="error.jsp" -- 指定当前jsp页面的错误处理页面
    isErrorPage="false" -- 指定当前页面是否为错误处理页面。false,不是错误处理页面,则不能使用exception内置对象;true,是错误处理页面,可以使用exception内置对象

    buffer="8kb" -- jsp页面的缓存区大小
    session="true"  --是否开启session功能。false,不能用session内置对象;true,可以使用session内置对象
    isELIgnored="false" -- 是否忽略EL表达式
%>

配置全局的错误处理页面

 <!-- 全局错误处理页面配置 -->
  <error-page>
    <error-code>500</error-code>
    <location>/common/500.jsp</location>
  </error-page>
  <error-page>
    <error-code>404</error-code>
    <location>/common/404.html</location>
  </error-page>

③ taglib指令
<%@taglib uri="tld文件的uri名称" prefix="标签库的简写" %>

二、Jsp的内置对象(重点)

1、什么是内置对象?
在jsp开发中,会频繁使用到一些对象,例如HttpSession、ServletContext、ServletContext、HttpServletRequet。如果我们每次要使用这些对象都去创建这些对象就显示非常麻烦。所以Sun公司设计Jsp时,在jsp页面加载完毕之后就会自动帮开发者创建好这些对象,而开发者只需要直接使用这些对象调用方法即可,这些创建好的对象就叫内置对象。

举例使用HttpSession对象:
① servlet:
HttpSession session = request.getSession(true); (需要开发者做)
② jsp:
tomcat服务器:HttpSession session = request.getSession(true);(不需要开发者做)
开发者做的: session.getId();

2、九大内置对象

内置对象名 类型 注释
request HttpServletRequest 获取一些请求信息
response HttpServletResponse 设置响应信息
config ServletConfig 加载配置信息
application ServletContext web资源
session HttpSession 会话对象
exception Throwable 异常
page Object(this) 翻译过来的java的类对象
out JspWriter 带缓存
pageContext PageContext 上下文对象

3、Out对象
① out对象类型是JspWriter类,相当于带缓存的PrintWriter
② PrintWriter: wrier(内容): 直接向浏览器写出内容
③ JspWriter:writer(内容):向jsp缓冲区写出内容
④ 当满足以下条件之一,缓冲区内容写出:
◆ 缓冲区满了
◆ 刷新缓存区out.flush()
◆ 关闭缓存区buffer="0kb"
◆ 执行完毕jsp页面

4、pageContext对象
① pageContext对象的类型是PageContext,叫jsp的上下文对象
② 可以获取其他八个内置对象
使用场景: 在自定义标签的时候,PageContext对象频繁使用到!

//伪代码
public class _hello_jsp {
    public void _jspService(request,response){
        //创建内置对象
        HttpSession session =....;
        ServletConfig config = ....;
        //把8个经常使用的内置对象封装到PageContext对象中
        PageContext pageContext = 封装;
        //调用method1方法
        method1(pageContext);
    }
    public void method1(PageContext pageContext){
        //希望使用内置对象
        //从PageContext对象中获取其他8个内置对象
        JspWriter out =pageContext.getOut();
        HttpServletRequest rquest = pageContext.getRequest();
        ........
    }
}

② 本身是一个域对象

ServletContext:context-- Servlet学习的
HttpServletRequet:request域   -- Servlet学习的
HttpSession:session域         -- Servlet学习的
PageContext:page域            -- jsp学习的

◆ 作用: 保存数据和获取数据,用于不同资源之间的共享数据
◆ 保存数据
◇ 默认情况下,保存到page域pageContext.setAttribute("name","value");
◇ 可以向四个域对象保存数据pageContext.setAttribute("name","value",域范围常量)
◆ 获取数据
◇ 默认情况下,从page域获取pageContext.getAttribute("name")
◇ 可以从四个域中获取数据pageContext.getAttribute("name",域范围常量)
◆ 域范围常量

PageContext.PAGE_SCOPE
PageContext.REQUEST_SCOPE
PageContext..SESSION_SCOPE
PageContext.APPLICATION_SCOPE

findAttribute()自动在四个域中搜索数据
pageContext.findAttribute("name");
自动搜索的顺序: page域 > request域 > session域 > context域(application域)

三、Jsp中的四个域对象

pageContext:page域               
requestrequest域
session:session域
application:context域

1、域对象作用:保存数据 和 获取数据 ,用于数据共享

2、域对象方法:

setAttribute("name",Object):保存数据
getAttribute("name"):获取数据
removeAttribute("name"):清除数据

3、域对象作用范围:
page域: 只能在当前jsp页面中使用(当前页面)【不同页面的转发也不能使用】
request域: 只能在同一个请求中使用【转发可以使用,重定向不行】
session域: 只能在同一个会话(session对象)中使用(私有的)
context域: 只能在同一个web应用中使用(全局的)
范围从上到下越来越大

四、Jsp的最佳实践

1、Servlet技术: 开发动态资源,是一个java类,最擅长写java代码

2、jsp技术: 开发动态资源,通过java代码最擅长输出html代码

3、各取所长:
在web项目中涉及到逻辑:

 接收参数 -- servlet做
 处理业务逻辑,返回结果 -- servlet做
 显示数据到浏览器 -- jsp做
 跳转到其他页面 -- servlet做

4、以后做项目:servlet+jsp模式
① servlet:
◆ 接收参数◆ 处理业务逻辑◆ 把结果保存到域对象中◆ 跳转到jsp页面
②Jsp:
◆ 从域对象取出数据◆ 把数据显示到浏览器

五、EL表达式

1、EL作用: 向浏览器输出域对象中的变量值或表达式计算的结果!
jsp的核心语法: jsp表达式 <%= %>和 jsp脚本<% %>
以后开发jsp的原则: 尽量在jsp页面中少写甚至不写java代码
所以,使用EL表达式替换掉jsp表达式

2、EL语法: ${变量或表达式}
① 输出基本数据类型变量
◆ 从四个域中获取${name}
◆ 指定域获取${pageScope.name}
◆ 域范围: pageScoep、requestScope 、sessionScope 、applicationScope
② 输出对象的属性值Student
③ 输出集合对象 List 和 Map

<%
        //保存数据
        Student student = new Student("eric",20);
        //放入域中
        pageContext.setAttribute("student",student);

        //List
        List<Student>  list = new ArrayList<Student>();
        list.add(new Student("rose",18));
        list.add(new Student("jack",28));
        list.add(new Student("lucy",38));
        //放入域中
        pageContext.setAttribute("list",list);

        //Map
        Map<String,Student> map = new HashMap<String,Student>();
        map.put("100",new Student("mark",20));
        map.put("101",new Student("maxwell",30));
        map.put("102",new Student("narci",40));
        //放入域中
        pageContext.setAttribute("map",map);
%>

 <%--使用EL获取对象 --%>
    ${student.name} - ${student.age }
    <%--${student.name} 等价于(点相对于调用getXX()方法)
    <%=((Student)pageContext.findAttribute("student")).getName()%>
    --%>    
<hr/>
<%--使用EL获取List对象 --%>
       ${list[0].name } - ${list[0].age }<br/>
       ${list[1].name } - ${list[1].age }<br/>
       ${list[2].name } - ${list[2].age }
       <%--
       list[0]等价于(中括号相对于调用get(参数)方法)
       ((List)pageContext.findAttribute("list")).get(0)
        --%>
<hr/>
<%--使用EL获取Map对象 --%>
        ${map['100'].name } -  ${map['100'].age }<br/>
        ${map['101'].name } -  ${map['101'].age }<br/>
        ${map['102'].name } -  ${map['102'].age }<br/>

④ EL表达式计算

<%--1)算术表达式 +  -  *  / --%>
    ${10+5 }<br/>
    ${10*5 }
<hr/>
<%--2)比较运算 >  <  >=  <=  ==   != --%>
     ${10>5 }<br/>
     ${10<5 }<br/>
     ${10!=10 }
<hr/>
<%-- 3)逻辑运算 &&  ||  ! --%>
     ${true && false }<br/>
     ${true || false }<br/>
     ${!false }<br/>
<hr/>
<%-- 4)判空 null或空字符串  empty --%>
     <%
        //String name = null;
        String name = "";
        pageContext.setAttribute("name",name);
      %>
     判断null: ${name==null }<br/>
     判断空字符: ${name=="" }<br/>
     判空: ${name==null || name=="" }
     另一种判空写法: ${empty name }  

五、Jsp标签

1、jsp标签的作用:替换jsp脚本
① 流程判断(if、for循环)
② 跳转页面(转发、重定向)
③ 。。。。。

2、Jsp标签分类
① 内置标签(动作标签):不需要在jsp页面导入标签
② jstl标签:需要在jsp页面中导入标签
③ 自定义标签:开发者自行定义,需要在jsp页面导入标签

3、动作标签
① 转发标签:<jsp:forward />
② 参数标签:<jsp:pararm />
③ 包含标签:<jsp:include />

<%--转发 --%>
    <%
        //request.getRequestDispatcher("/09.action2.jsp?name=eric").forward(request,response);
    %>
<%-- 参数 --%>
    <%--
    <jsp:forward page="/09.action2.jsp">
        <jsp:param value="jacky" name="name"/>
        <jsp:param value="123456" name="password"/>
    </jsp:forward>
    --%>
<%-- 包含 --%>
    <%--
    <jsp:include page="/common/header.jsp">
        <jsp:param value="lucy" name="name"/>
    </jsp:include>
    --%>

原理: 包含与被包含的页面先各自翻译成java源文件,然后再运行时合并在一起
(先翻译再合并),叫做动态包含

4、静态包含(指令)和动态包含(标签)的区别
① 语法不同
◆ 静态包含语法:<%@inclue file="被包含的页面"%>
◆ 动态包含语法:<jsp:include page="被包含的页面">
② 参数传递不同
◆ 静态包含不能向被包含页面传递参数
◆ 动态包含可以向被包含页面传递参数
③ 原理不同
◆ 静态包含: 先合并再翻译
◆ 动态包含: 先翻译再合并

5、JSTL标签
① JSTL (全名:java standard tag libarary: java标准标签库 )
◆ 核心标签库 (c标签库) 天天用
◆ 国际化标签(fmt标签库)
◆ EL函数库(fn函数库)

◆ xml标签库(x标签库) 不重要
◆ sql标签库(sql标签库) 不重要

② 使用JSTL标签步骤
◆ 导入jstl支持的jar包(标签背后隐藏的java代码)
注意:如果是javaee5.0的项目会自动导入jstl支持jar包
◆ 使用taglib指令导入标签库
<%@taglib uri="tld文件的uri名称" prefix="标签库的简写" %>
<uri>http://java.sun.com/jsp/jstl/core</uri><short-name>c</short-name>
◆ 在jsp中使用标签
③ 核心标签库的重点标签

保存数据:
    <c:set></c:set>   
获取数据: 
    <c:out value=""></c:out>
单条件判断:
    <c:if test=""></c:if>
多条件判断:
    <c:choose></c:choose>
    <c:when test=""></c:when>
    <c:otherwise></c:otherwise>
循环数据:
    <c:forEach></c:forEach>
    <c:forTokens items="" delims=""></c:forTokens>
重定向:
    <c:redirect></c:redirect>
 <%--使用标签 --%>
    <%--set标签 :保存数据(保存到域中)默认保存到page域 --%>
    <c:set var="name" value="rose" scope="request"></c:set>
    <%
        String msg = null;
        pageContext.setAttribute("msg",msg);
     %>
    ${msg}
    <br/>
    <%--out标签: 获取数据(从域中) 
    default: 当value值为null时,使用默认值
    escapeXml: 是否对value值进行转义,false,不转义,true,转义(默认)
    --%>
    <c:out value="${msg}" default="<h3>标题3</h3>" escapeXml="true"></c:out> 
    <hr/>

    <%--if标签 :单条件判断--%>
    <c:if test="${!empty msg}"> //test返回true或者false
        条件成立
    </c:if>
    <hr/>

    <%--choose标签+when标签+otherwirse标签: 多条件判断 --%>
    <c:set var="score" value="100"></c:set>  
    <c:choose>
        <c:when test="${score>=90 && score<=100}">
            优秀
        </c:when>
        <c:when test="${score>=80 && score<90}">
            良好
        </c:when>
        <c:when test="${score>=70 && score<80}">
            一般
        </c:when>
        <c:when test="${score>=60 && score<70}">
            及格
        </c:when>
        <c:otherwise>
            不及格
        </c:otherwise>
    </c:choose>

    <%-- forEach标签:循环 --%>
    <%
        //List
        List<Student>  list = new ArrayList<Student>();
        list.add(new Student("rose",18));
        list.add(new Student("jack",28));
        list.add(new Student("lucy",38));
        //放入域中
        pageContext.setAttribute("list",list);

        //Map
        Map<String,Student> map = new HashMap<String,Student>();
        map.put("100",new Student("mark",20));
        map.put("101",new Student("maxwell",30));
        map.put("102",new Student("narci",40));
        //放入域中
        pageContext.setAttribute("map",map);
     %>
     <%--
     begin="":从哪个元素开始遍历,从0开始.默认从0开始
     end="":到哪个元素结束,默认到最后一个元素
     step="":步长(每次加几),默认1
     items="":需要遍历的数据(集合) 
     var="":每个元素的名称 
     varStatus="":当前正在遍历元素的状态对象(count属性:当前位置,从1开始)     
     --%>

    <c:forEach items="${list}" var="student" varStatus="varSta">
        序号:${varSta.count} - 姓名:${student.name } - 年龄:${student.age}<br/>
    </c:forEach>
    <hr/>

    <c:forEach items="${map}" var="entry">
        ${entry.key } - 姓名: ${entry.value.name } - 年龄:${entry.value.age }<br/>
    </c:forEach>
    <hr/>

    <%-- forToken标签: 循环特殊字符串 --%>
    <%
        String str = "java-php-net-平面";
        pageContext.setAttribute("str",str);
     %>
    <c:forTokens items="${str}" delims="-" var="s">
        ${s }<br/>
    </c:forTokens>
    <hr/>

    <%--redrict:重定向 --%>
    <c:redirect url="http://www.baidu.com"></c:redirect> 

猜你喜欢

转载自blog.csdn.net/Mr_GaoYang/article/details/82421055