JavaWeb--服务器渲染技术(JSP+EL+JSTL)


JavaWeb--服务器渲染技术(JSP+EL+JSTL)

JSP

基本概念

  • JSP 全称是 Java Server Pages,Java 的服务器页面

  • JSP 这门技术的最大的特点在于,写 JSP 就像在写 HTML

    • 相比 html 而言,html 只能为用户提供静态数据,而 JSP 技术允许在页面中嵌套 java 代码,为用户提供动态数据
    • 相比 Servlet 而言,Servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产 生动态数据的同时,也很容易对数据进行排版
  • jsp 技术基于 Servlet, 你可以理解成 JSP 就是对 Servlet 的包装

  • 会使用 JSP 的程序员, 再使用 thymeleaf 是非常容易的事情, 几乎是无缝接轨

运行原理

  • jsp 页面本质是一个 Servlet 程序, 其性能是和 java 关联的, 只是长得丑

  • 第 1 次访问 jsp 页面的时候。Tomcat 服务器会把 jsp 页面解析成为一个 java 源文件。

    并 且 对 它 进 行 编 译 成 为 .class 字 节 码 程 序

  • 可以看出本质就是 Servlet

page指令

<%@ page contentType="text/html;charset=utf-8" language="java"%>
  • language: 表示jsp翻译后是什么语言文件,目前只支持java
  • contentType:表示jsp返回的数据类型,对应源码中 response.setContenttype()参数值
  • pageEncoding属性: 表示jsp页面文件本身的字符集
  • import 属性:用于导入包、类

三种常用脚本

声明脚本

语法: <%! 声明 java 代码 %>
作用: 定义jsp的需要属性、方法、静态代码块和内部类等
应用:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    jsp声明脚本


jsp声明脚本

<%! //这里我们可以声明该jsp需要使用的属性,方法,静态代码块, 内部类 //也就是给 statement.jsp 对应的 statement_jsp 类定义成员 //1. 属性 private String name = "jack"; private int age; private static String company; //2 方法 public String getName() { return name; } //3. 静态代码块 static { company = "字节跳动"; } %>

表达式脚本

语法:<%=表达式%>
作用:在jsp页面上输出数据
注意:其中的表达式不能以分号结束
应用:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    表达式脚本的使用


个人信息

<% String name = "老韩"; String email = request.getParameter("email"); %> 用户名: <%=name%>
工作是: <%="java工程师"%>
年龄: <%=request.getParameter("age")%>
电邮: <%=email%>

代码脚本

语法: <% java代码 %>
作用: 在JSP页面中,编写我们需要的功能(使用java,就像在servlet doGet等方法中)
注意: 可以由多个代码脚本块组合完成一个完整的java语句,也可以配合表达式脚本一起组合使用,输出数据
应用:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    演示代码脚本


演示代码脚本

<% //创建ArrayList ,放入两个monster对象 ArrayList monsterList = new ArrayList<>(); monsterList.add(new Monster(1, "牛魔王", "芭蕉扇")); monsterList.add(new Monster(2, "蜘蛛精", "吐口水")); %> <% for (int i = 0; i < monsterList.size(); i++) { //先取出monster对象 Monster monster = monsterList.get(i); %> <% } %>
id 名字 技能
<%=monster.getId()%> <%=monster.getName()%> <%=monster.getSkill()%>

注释

<%-- jsp注释 --%>

// java注释

内置对象

JSP内置对象(已经创建好的对象,直接使用inbuild),是指Tomcat在翻译jsp页面成为

Servlet后,内部提供的九大对象,叫内置对象,可以直接使用,不需要手动定义

  1. out向客户端输出数据,out.println("");

  2. request客户端的http请求

  3. response响应对象

  4. session会话对象

  5. application对应ServletContext

  6. pageContextjsp页面的上下文,是一个域对象,可以setAttribue(),作用范围只是本页面

  7. exception异常对象,getMessage()

  8. page代表jsp这个实例本身

  9. config对应ServletConfig

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    jsp内置对象


jsp内置对象

<% //老韩梳理jsp的内置对象 //out 类型是 JspWriter 父类就是 Writer. out.println("jsp out"); //request是HttpServletRequest request.getParameter("age"); //response就是 HttpServletResponse //response.sendRedirect("http://www.baidu.com"); //session 就是 HttpSession session.setAttribute("job", "PHP工程师"); //application类型就是ServletContext application.setAttribute("name", "老韩老师"); //pageContext 可以存放数据(属性), 但是该数据只能在本页面使用 pageContext.setAttribute("age", 100); //exception 异常对象 使用比较少 //page 内置对象,类似 this out.println("page=" + page); //config 内置对象的类型就是ServletConfig String pwd = config.getInitParameter("pwd"); %> age: <%=pageContext.getAttribute("age")%>

域对象

作用就是为了存取数据

  1. pageContext(域对象,存放的数据只能在当前页面使用)
  2. request(域对象,存放的数据在一次request请求有效)
  3. session(域对象,存放的数据在一次会话有效)
  4. application(域对象,存放的数据在整个web应用运行期间有效,范围更大)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    scope文件


<%
    //在不同的域对象中,放入数据
    //1. 因为四个域对象,是不同的对象,因此name(key) 相同时,并不会冲突
    pageContext.setAttribute("k1", "pageContext数据(k1)");
    request.setAttribute("k1", "request数据(k1)");
    session.setAttribute("k1", "session数据(k1)");
    application.setAttribute("k1", "application数据(k1)");

    //做一个请求转发的操作
    //路径应该怎么写,请不清楚地小伙伴,参考web路径笔记
    //request.getRequestDispatcher("/scope2.jsp").forward(request, response);

    //做一个重定向
    String contextPath = request.getContextPath();//返回的就是 web路径=>/jsp
    //response.sendRedirect("/jsp/scope2.jsp");
    response.sendRedirect(contextPath + "/scope2.jsp");
%>

四个域对象,在本页面获取数据的情况

pageContext-k1: <%=pageContext.getAttribute("k1")%>
request-k1: <%=request.getAttribute("k1")%>
session-k1: <%=session.getAttribute("k1")%>
application-k1: <%=application.getAttribute("k1")%>
----- <%@ page contentType="text/html;charset=UTF-8" language="java" %> scope2.js

在scope2页面获取数据的情况

pageContext-k1: <%=pageContext.getAttribute("k1")%>
request-k1: <%=request.getAttribute("k1")%>
session-k1: <%=session.getAttribute("k1")%>
application-k1: <%=application.getAttribute("k1")%>

注意事项

  • 域对象可以像map一样存取数据的对象,四个域对象功能一样,仅仅是它们对数据的存储范围有差别
  • 从存储范围(作用域)比较:pageContext < request < session < application

转发标签

它的功能就是请求转发page属性设置请求转发的路径

// 转发请求

EL表达式

EL表达式全称:ExpressionLanguage,是表达式语言

EL表达式主要是代替jsp页面的表达式脚本<%=request.getAttribute("xx")%>

EL表达式输出数据的时,比jsp的表达式脚本简洁

EL表达式基本语法:${key1},你可以理解就是一个语法糖

EL表达式在输出null时,输出的是"",jsp表达式脚本输出null的时,输出的是"null"字符串

EL表达式常用输出Bean的普通属性、数组属性、List集合属性和map集合属性

演示EL常用输出使用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    el 表达式输出数据演示


el 表达式输出数据演示

<% //创建Book 对象,放入相关的属性 //private String name;//书名 //private String[] writer;//作者 //private List reader;//读者 //private Map topics;//评讲 Book book = new Book(); book.setName("昆虫总动员"); book.setWriter(new String[]{"jack", "tom"}); ArrayList readers = new ArrayList<>(); readers.add("老韩"); readers.add("老李"); book.setReader(readers);//放入readers //创建topics HashMap topics = new HashMap<>(); topics.put("topic1", "这是我看过的最好的动画片"); topics.put("topic2", "不错的电影~~"); book.setTopics(topics); //把book 放入到request域对象 request.setAttribute("bookkey", book); %> book对象: ${bookkey}
book.name= ${bookkey.name}
book.writer= ${bookkey.writer}
book.writer[0]= ${bookkey.writer[0]}
book.readers= ${bookkey.reader}
book.readers第2个= ${bookkey.reader.get(1)}
book.readers第2个= ${bookkey.reader[1]}
book.topics= ${bookkey.topics}
book.topics第一个评论= ${bookkey.topics["topic1"]}

运算

  • 关系运算

  • 逻辑运算

  • 算数运算

  • empty运算

    • 可以判断一个数据是否为空,如果为空,返回true,否则返回false

    • 以下情况满足为空

      • 值为null
      • 值为空串的时
      • 值是Object类型数组,长度为零
      • list集合,元素个数为零
      • map集合,元素个数为零
    • 应用

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
          el empty的运算
      
      
      

      el empty的运算

      <% request.setAttribute("k1", null); request.setAttribute("k2", ""); request.setAttribute("k3", new Object[]{}); request.setAttribute("k4", new ArrayList<>()); request.setAttribute("k5", new HashMap<>()); request.setAttribute("score", 70); %> k1是否为空= ${empty k1}
      k2是否为空= ${empty k2}
      k3是否为空= ${empty k3}
      k4是否为空= ${empty k4}
      k5是否为空= ${empty k5}
      是否及格= ${score >= 60 ? "及格": "不及格"}
  • 三元运算

    ${布尔条件表达式 ? 真值:假值}
    

隐含对象

EL四个特定域变量

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    演示el的四个常用的隐藏对象(域对象)


演示el的四个常用的隐藏对象(域对象)

<% request.setAttribute("k1", "request-k1数据"); pageContext.setAttribute("k1", "pageContext-k1数据"); session.setAttribute("k1", "session-k1数据"); application.setAttribute("k1", "application-k1数据"); %>

jsp脚本方式获取

request域中的k1= <%=request.getAttribute("k1")%>

el方式来获取域对象的数据

request域中的k1= ${requestScope.k1}
pageContext域中的k1= ${pageScope.k1}
session域中的k1= ${sessionScope.k1}
application域中的k1= ${applicationScope.k1}

pageContext对象的使用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    pageContext 对象的使用


pageContext 对象的使用

<%-- //通过request对象来获取和HTTP协议相关的数据 request.getScheme() 它可以获取请求的协议 request.getServerName() 获取请求的服务器 ip 或域名 request.getServerPort() 获取请求的服务器端口号 getContextPath() 获取当前工程路径 request.getMethod() 获取请求的方式(GET 或 POST) request.getRemoteHost() 获取客户端的 ip 地址 session.getId() 获取会话的唯一标识 --%>
<%--老韩解读 1.我们可以通过pageContext.request.xx 俩获取和http协议相关的信息 2.相当于替代 request.getMethod().... --%> 协议: ${ pageContext.request.scheme }
服务器 ip:${ pageContext.request.serverName }
服务器端口:${ pageContext.request.serverPort }
工程路径:${ pageContext.request.contextPath }
请求方法:${ pageContext.request.method }
客户端 ip 地址:${ pageContext.request.remoteHost }
会话id :${ pageContext.session.id }

使用jsp表达式脚本获取如上信息

ip地址: <%=request.getRemoteHost() %>

使用el表达式形式获取信息-简化写法

<% pageContext.setAttribute("req", request); %> ip地址(简化获取): ${req.remoteHost}
获取请求方法(简化获取): ${req.method}

JSTL标签库

JSTL标签库是指JSPStandardTagLibraryJSP标准标签库

EL表达式是为了替换jsp中的表达式脚本,JSTL是为了替换代码脚本。这样jsp页面变得更佳简洁

五个标签库

使用需要导入jar包:taglibs-standard-impl-1.2.1.jar、taglibs-standard-spec-1.2.1.jar

快速入门

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    jstl的快速入门


jstl的快速入门

<%--老韩解读 1. c:if ... 类似 2. if(10>2){ out.println("

10 > 2 成立~

") } --%>

10 > 2 成立~

注意事项

  1. taglib引入标签,要放行首
  2. 导入jstl jar包后,要重新发布web工程,否则不识别jstl

core核心库

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    c:set标签的使用


c:set标签的使用

<%--<%--%> <%-- //Java代码--%> <%-- request.setAttribute("email", "hsp@sohu.com");--%> <%--%>--%> <%--老韩解读 set 标签可以往域中保存数据 1. 等价 域对象.setAttribute(key,value); 2. scope 属性设置保存到哪个域 page 表示 PageContext 域(默认值) request 表示 Request 域 session 表示 Session 域 application 表示 ServletContext 域 3. var 属性设置 key 是什么 4. value 属性设置值 --%> c:set-name的值${requestScope.name} ------ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%-- Created by IntelliJ IDEA. User: 韩顺平 Version: 1.0 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> c:if标签使用

${num1} > ${num2}

------ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%-- Created by IntelliJ IDEA. User: 韩顺平 Version: 1.0 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> c:choose标签的使用

c:choose标签的使用

<% request.setAttribute("score", 50); //request.setAttribute("k1", "request-k1的值"); //session.setAttribute("k1", "session-k1的值"); //application.setAttribute("k1", "application-k1的值"); //pageContext.setAttribute("k1", "pageContext-k1的值~"); %> <%--老师多说一句 1. 如果${requestScope.score} 那么就明确的指定从request域对象取出数据 2. 如果${score}, 这是就按照从小到大的域范围去获取 pageContext->request->session->application 3. 一会老韩给小伙伴验证一把. --%> k1=${k1}

${score}-成绩优秀

${score}-成绩一般, 及格了

${score}-没有及格,下次努力~

------ <%@ page import="java.util.Map" %> <%@ page import="java.util.HashMap" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <%@ page import="com.hspedu.entity.Monster" %> <%-- Created by IntelliJ IDEA. User: 韩顺平 Version: 1.0 --%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%-- Created by IntelliJ IDEA. User: 韩顺平 Version: 1.0 Filename: jstl_foreach --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> c:forEach 标签

c:forEach 标签


第1种遍历方式从i到j

    <%-- 1.遍历 1 到 5, 2. 输出 begin 属性设置开始的索引 end 属性设置结束的索引 3. var 属性表示循环的变量(也是当前正在遍历到的数据) 4. 等价 for (int i = 1; i <= 5; i++) {} 5. 在默认情况下, i 每次会递增1 --%>
  • 排名=${i}

第2种遍历方式:遍历数组

<% request.setAttribute("sports", new String[]{"打篮球", "乒乓球"}); %> <%-- 1. items 遍历的集合/数组 2. var 遍历到的数据 3. 等价 for (Object item: arr) {} --%> 运动名称= ${sport}

第3种遍历方式:遍历Map

<% Map map = new HashMap<>(); map.put("key1", "北京"); map.put("key2", "上海"); map.put("key3", "天津"); request.setAttribute("cities", map); %> <%-- 1. items 遍历的map集合 2. var 遍历到的数据 3. entry.key 取出key 4. entry.value 取出值 --%> 城市信息: ${city.key}--${city.value}

第4种遍历方式:遍历List

<% List monsters = new ArrayList<>(); monsters.add(new Monster(100, "小妖怪", "巡山的")); monsters.add(new Monster(200, "大妖怪", "做饭的")); monsters.add(new Monster(300, "老妖怪", "打扫位置的")); request.setAttribute("monsters", monsters); %> <%-- items 表示遍历的集合 var 表示遍历到的数据 begin 表示遍历的开始索引值 ,从0开始计算 end 表示结束的索引值 step 属性表示遍历的步长值 varStatus 属性表示当前遍历到的数据的状态,可以得到step,begin,end等属性值 //老师提示, 对于jstl标签,能看懂,会使用即可 --%> 妖怪的信息: ${monster.id}-${monster.name}-${monster.skill}