1:需要使用el表达式,专门替代 <%= %>
2:使用jstl技术专门替代 <% 这里的循环和判断 %>

1 el

1.1 el表达式概述

EL(Expression Language) 是为了使JSP写起来更加简单。是独立的语言。
在jsp页面可以直接编写el表达式的代码,用于获取jsp4大域中的数据或其他地方的数据。

1.2 el表达式的基本语法

在jsp页面上直接使用
${ 4大域中的属性名 };
取值之后,会自动将数据值输出到浏览器。
注意:
如果取不到值,则会返回一个空字符串。

1.3 el表达式的内置对象(红色为常用,但是面试建议全背下来)

就是在${在这里可以直接写的对象名就是el的内置对象}
el的内置对象一共有11个,每一个内置对象都有不同的作用:
具体的:
pageScope
requestScope
sessionScope
applicationScope
上面这4个分别与jsp中的4大域对象相对应

param 就是将浏览器传递过来的所有参数,封装成了一个param对象。使用格式: ${ param.参数名 }
paramValues
Header
headerValues
initParam 获取web.xml中的配置的全局参数

cookie 获取浏览器携带过来的cookie 格式: ${ cookie.cookie的名称 }
pageContext 就是jsp中的pageContext,在el表达式中,通常会使用这个对象来获取jsp中的其他8个对象。
例如: ${ pageContext.request.contextPath } 获取工程的绝对路径!!!(通过内置对象pageContext拿request对象,通过request对象拿getContestPath方法)

1.3.1 内置对象param的使用

目录结构
image.png
login.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>Insert title here</title>
  8. </head>
  9. <body>
  10. <font color="red" size="7">${msg }</font>
  11. <form action="${pageContext.request.contextPath }/LoginServlet" method="get">
  12. 用户名:<input type="text" value="${param.username }" name="username">
  13. <br>
  14. <input type="submit">
  15. </form>
  16. </body>
  17. </html>

LoginServlet.java

package com.itheima.demo01_El练习;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 模拟用户登录失败,进行数据回显的效果
 */
public class LoginServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //提示不对  ......
        request.setAttribute("msg","用户名或密码错误");
        request.getRequestDispatcher("/el/login.jsp").forward(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

1.3.2 内置对象cookie的使用

cookie.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>练习获取cookie</title>
</head>
<body>
    <!--  根据cookie名称获取cookie对象,进一步获取cookie保存的值 -->
    用户请求中的cookie值是:${ cookie.remember.value }
    <br>
    <!--    了解即可,因为本身就是根据cookie的名称获取的cookie对象 -->
    用户请求中的cookie的名是:${ cookie.remember.name }
</body>
</html>

CookieServlet.java

package com.itheima.demo01_El练习;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 创建cookie的servlet
 */
public class CookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1:创建cookie
        Cookie c = new Cookie("remember","helloworld.......................");
        //2:设置cookie的路径
        c.setPath("/");
        //3:添加cookie到响应对象中
        response.addCookie(c);
        response.getWriter().print("ok..");
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

1.4 EL表达式的运算符

支持的运算符:
算术运算符 注意: 这里面的加号,仅仅是数学上的加法运算,不存在字符串的连接运算!!!
如果字符串进行连接运算的时候,el会自动将字符串转成数字进行运算,如果转换失败,则会抛异常!!!且不区分单双引号。
逻辑运算符
比较运算符
三元运算符
empty关键字运算符 判断空的格式:
${ empty 变量名 }
通常用于判断集合或数组,如果集合不存在或者存在但是长度为0都会返回true。
判断不为空的判断格式:
${ not empty 变量名 }
通常用于判断集合或数组,必须集合存在且长度大于0才会返回true。
el运算符.jpg

1.5 el表达式获取引用数据类型的值

引用数据类型:
${属性名.引用数据类型中的成员变量名} 实质上找的是getName方法
特殊情况取值:
1:集合取值
2:数组取值
3:如果属性名中包含了特殊符号的值,例如:User-Agent
使用通用的取值格式:(了解)
${ el的4个域对象名[“属性名”] }
[] 与 . 取值的区别:
[]是任意时候都能用,建议在获取数组或集合中的数据时使用。
.是名称不包含特殊符号的时候可以使用,因为格式简单,建议优先考虑使用 .
试验代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    import="java.util.ArrayList,com.itheima.demo01_El练习.User"
    %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>引用数据类型取值</title>
</head>
<body>
    <%
        ArrayList<User> li = new ArrayList<User>();
        li.add(new User("马尔扎哈",3));
        li.add(new User("古力娜扎",30));
        request.setAttribute("lii",li);
        request.setAttribute("u1",new User("马尔扎哈",3));
    %>
    user对象的名称:${ u1.name },年龄是:${u1.age }
    <br>
    获取用户的浏览器相关信息:${ header["User-Agent"] }
    <br>
    获取集合中的0索引元素值:${ lii[0]['name'] }
    <br>
    获取集合中的1索引元素值:${ lii[1]['name'] }
</body>
</html>

2 jstl

2.1 jstl概述

JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)
可以在jsp页面上,编写其他的标签,实现相应的功能。
例如:使用jstl标签完成逻辑判断,循环操作等。

2.2 jstl的使用步骤

1: 需要从网上下载并解压zip文件,得到两个jar包。
2: 将两个jar包引入到工程的WEB-INF/lib目录下。
3: 在jsp页面上使用taglib指令引入jstl的核心标签库即可。
这个格式是固定死的,一点不能变(<%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core“ %>)
4: 使用固定的标签格式,完成相关的效果。

2.3 jstl的判断语句

格式:

如果el运算的结果为true,则会显示这里的代码,否则不显示

扩展:(了解)
在c:if的开头标签中,有一个可选属性:var
var 可以保存el表达式判断的结果,默认会将判断的结果保存到page域中。(是true或者false)

2.4 jstl的循环语句

在jstl中可以使用c:forEach语句完成循环的操作;
格式1:(专门用于操作数字)

循环体

其中:
begin 代表开始的数字值(包含这个值)
end 代表结束的数字值(包含这个值)
step 代表步进的数字值(相当于 += )
var 代表迭代出来的每一个数字值变量名,可以通过el表达式根据变量名获取每一个元素值。
varStatus 代表循环的状态对象,在该对象中有4个常用属性:
1: first 当前是第一次循环吗
2: last 当前是最后一次循环吗
3: count 当前循环的次数
4: index 当前循环的索引是(注意:在操作数字的时候,索引与元素值是一样的)
格式2:(专门用于操作数组或集合)(包含map集合)

循环体

其中:
items 代表的就是使用el表达式从域中获取的集合或数组,也可以是map集合,如果是map默认采用entrySet的方式进行迭代。

2.5 试验代码

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

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jstl的核心标签库练习---循环--判断</title>
</head>
<body>
    <%
        request.setAttribute("username","旺财");
    %>
    <h1>jstl的判断语句</h1>
    <c:if test="${username==null}" var="a">
        <font color="red">亲,数据空空如也...</font> 
    </c:if>
    <c:if test="${username!=null}" var="b">
        域中的username是:<div style="font-size: 50px;color: red">${username }</div>
    </c:if>
    <hr>
    第一个if语句的表达式判断的结果是:${a }  <!-- false -->
    <br>
    第二个if语句的表达式判断的结果是:${b }  <!-- true -->
    <h1>forEach循环的第一种方式(操作数字)</h1>
    <c:forEach begin="1" end="50" step="7" var="i" varStatus="st">
        <br>
        当前这一次循环的元素值是:${i}
        <br>
        当前是第一次循环吗:${st.first}
        <br>
        当前是最后一次循环吗:${st.last}
        <br>
        当前循环的次数是:${st.count}
        <br>
        当前循环的索引是(注意:在操作数字的时候,索引与元素值是一样的):${st.index}    
        <hr>
    </c:forEach>

    <%
        //保存数组
        String[] arr = {"小明","小花","小强"};
        request.setAttribute("myArr",arr);
        //保存map集合
        HashMap<String,Integer> map = new HashMap<String,Integer>();
        map.put("程程",28);
        map.put("文强",29);
        map.put("阿力",27);
        request.setAttribute("myMap",map);
    %>
    <h1>迭代数组</h1>
    <c:forEach items="${myArr }" var="s">
        ${s} &nbsp;&nbsp;&nbsp;
    </c:forEach>
    <h1>迭代map</h1>
    <c:forEach items="${myMap }" var="en" >
        ${en.key}===>${en.value } &nbsp;&nbsp;&nbsp;   <%--  此处的en.value也可以写成en.getValue()不过没有必要,这种写法一般都是在调取不是get开头的方法时使用   --%>
    </c:forEach>
</body>
</html>

3 MVC与三层架构的开发模式

3.1 mvc思想-站在模型视图和控制的角度来说的

1:jsp的model1时代,一个jsp把所有的事情做完。
缺点:
维护非常困难,扩展很不方便。
2:jsp的model2时代,把jsp用于页面数据展示,数据收集,逻辑处理,数据库操作,把数据模型类分离出来了。
缺点:
jsp的事情太多了,代码的耦合度太高了。
3:现在使用的开发模式—-MVC架构模式
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,是一个通用的软件设计思想。
好处:
可以让功能与数据和界面展示分离开,分别开发,便于维护和扩展。
流程示意图:
image.png

3.2 三层架构思想-站在整个业务流程来说的

软件开发的3层架构模式:
三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。区分层次的目的即为了“高内聚低耦合”的思想。
一高一低三可:
高内聚: 一个模块应该做完自己相关的事情。
低耦合:不同模块不应该有太多的紧密联系,可以分别开发,同时进行,最后结合在一起即可。
可扩展
可维护
可重用
MVC与三层结构的关系示意图.png
说明:个人感觉好像这个图不太对。

4 案例—重写昨天的商品列表展示

4.1 需求

将昨天使用脚本标签展示的商品信息,采用el和jstl技术,实现即可;

4.2 技术分析

1:需要使用el表达式,专门替代 <%=%>
2:使用jstl技术专门替代 <% 这里的循环和判断 %>

4.3 案例代码步骤

1:将昨天完成的案例复制一份;
2:修改jsp页面的技术为el和jstl即可;

4.4 部分参考代码

image.png
list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    import="java.util.*,com.itheima.anli04_domain.Product"
    %>
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品列表页面</title>
</head>
<body>
    <table border="1px" width="100%">
        <tr>
            <th>编号</th>
            <th>名称</th>
            <th>市场价</th>
            <th>商城价</th>
            <th>图片</th>
            <th>上架日期</th>
            <th>描述</th>
        </tr>
        <c:forEach items="${li}" var="p">
            <tr>
                <td>${p.pid }</td>
                <td>${p.pname }</td>
                <td>${p.market_price }</td>
                <td>${p.shop_price }</td>
                <td>
                    <img alt="" width="50px" height="50px" src="${pageContext.request.contextPath }/${p.pimage}">
                </td>
                <td>${p.pdate }</td>
                <td>${p.pdesc }</td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>