7. JSP

1 JSP

  1. java server page,是一种动态网页技术,可以根据用户请求,生成不同页面
  2. jsp本质上是servlet,是java类,tomcat会通过jsp引擎将jsp转为servlet,jsp里一般不写业务逻辑
  3. jsp≈java+html
1.1 JSP与Servlet区别
  1. servlet
    1. 逻辑处理方便
    2. 页面表现麻烦
  2. jsp
    1. 页面表现方便
    2. 逻辑处理麻烦
  3. 初级web项目,通常采用jsp+servlet+javabean(用于将数据库中数据转为对象),高级项目通常使用SSM框架
1.2 JSP执行过程
  1. Tomcat收到请求:http://localhost:8080/jsp/1.jsp
  2. Tomcat根据conf/web.xml中的配置,找到org.apache.jasper.servlet.JspServlet类处理
<!--conf/web.xml-->
<servlet-mapping>
	<servlet-name>jsp</servlet-name>
	<url-pattern>*.jsp</url-pattern>
	<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
<servlet>
	<servlet-name>jsp</servlet-name>
	<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>
  1. JspServlet类会根据你的输入的jsp文件名,使用JSP引擎,动态的生成"JSP文件名_jsp.class"与"JSP文件名_jsp.java"文件,并执行class文件
//对于Intellij IDEA文件所在路径如下
C:\Users\含低调\.IntelliJIdea2019.3\system\tomcat\Unnamed_myfirstServletWu\work\Catalina\localhost\myfirstServlet\org\apache\jsp

注:由于JSP对应的java文件,是收到请求时动态生成的,因此修改JSP后,不需要重启Tomcat就能生效,但对于Intellij IDEA需要对Tomcat服务器进行如下设置
在这里插入图片描述

1.3 编译器指令:<%@ %>
  1. 告诉JSP引擎如何将JSP转译成servlet
1.3.1 page
  1. 用来设置转义成servlet文件时的参数
  2. 属性
    1. contentType:表示浏览器解析响应时候使用的编码和解析格式
    2. language:表示jsp转译成的文件类型
    3. import:导入需要的jar包,使用逗号分隔
    4. pageEncoding:设置页面编码格式,设置了他,就可以不设置contentType中的charset,但如果都设置,必须保持一致
    5. session:用来控制servlet中是否创建session对象
    6. errorPage:当页面发生逻辑错误时,跳转的页面
    7. extends:选择要转译的servlet类要继承的父类(包名+类名)
  3. 示例
...
<%@page contentType="text/html;charset=UTF-8" language="java" import ="java.util.*" pageEncoding="utf-8" %>
<%@page session="false" errorPage="error.jsp" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

</body>
</html>
1.3.2 include
  1. 用于导入另一个jsp页面
    1. 页面一般头尾都不变,可以将头尾抽象成一个jsp,另一个jsp直接导入该jsp,减少样板代码
  2. 静态导入:<%@include file=“jsp相对路径”%>
    1. 不会将静态导入页面生成一个新的servlet文件,而是单纯的将两个文件合并
    2. 优点:运行效率高
    3. 缺点:两个页面会耦合到一起,不利于维护,两个页面中不能存在相同名称的变量
  3. 动态导入:<jsp:include page=“danamic.jsp”></jsp:include>
    1. 两个页面不会进行合并,分别生成自己的servlet文件,但页面在最终展示的时候是合并到一起的
    2. 优点:没有耦合,可以存在同名的变量
  4. 示例
...
<html>
<head>
    <base href="<%=basePath%>">
    <title>Title</title>
</head>
<body>
<%@include file="static.jsp"%>
<jsp:include page="danamic.jsp"></jsp:include>
</body>
</html>
1.3.3 taglib
  1. taglib用于导入标签库
  2. 标签库:指一堆标签
  3. 标签库描述文件:定义了标签名与java类对应关系的tld文件
  4. JSP引擎会根据tld文件中的标签名,将其转为对应的java类并进行处理
<%--prefix:表示为标签库设定了一个简短的别名--%>
<%--uri表示要导入的标签库的地址,这个地址指向一个tld文件--%>
<%--tld文件为标签库的描述文件,里面有标签名与java类的对应关系,它告诉服务器如何将这些标签转为java类并进行处理--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
1.4 JSP中嵌入java代码
  1. 局部代码块:<%%>
    1. 相当于在service方法中加代码
    2. 缺点:代码可读性差,开发麻烦。一般不使用
  2. 全局代码块:<%!%>
    1. 相当于在servlet类中定义公共的方法
    2. 可以使用局部代码块对其进行调用
  3. 脚本调用方法:<%=%>
    1. 相当于在servlet中生成out.write(变量/方法)这种代码,要求write内的方法必须有返回值,且不能在变量或方法后加";"
    2. 正常想用out.write打印某个值,直接写汉字即可,但如果想利用out.write打印变量值或打印函数返回值,就需要使用<%=%>
  4. 示例
...
<%!
    String str = "含低调";
    public String test(){
        return "含低调test";
    }
%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    int i = new Random().nextInt(10);
    if(i>5){
%>
//相当于直接调用out.write(“今天天气很好”)
今天天气很好
<%
    }else{
        //没法直接在jsp中写out.write(test());,因为压根没有response对象,也无法调用它的方法
%>
<%=test()%>
<%}%>
</body>
</html>
1.5 JSP中的请求转发
  1. <jsp:forward page=“forward.jsp”></jsp:forward>
  2. page内填写的是jsp的相对路径
  3. 注:在标签中间不可以添加任何字符,除了<jsp:param name=“00001” value=“beijing”/>,这相当于发送请求"/forward.jsp?00001=beijing"
  4. 在转发的页面中想要获取属性值,可以通过request.getParameter(“00001”)
  5. 示例
<%--原页面代码--%>
...
<jsp:forward page="forward.jsp">
    <jsp:param name="00001" value="beijing"/>
    <jsp:param name="00002" value="shanghai"/>
</jsp:forward>

<%--转发到的页面获取属性--%>
...
<%=request.getParameter("00001")%>
<%=request.getParameter("00002")%>
1.6 JSP九大内置对象
  1. jsp页面在转译成其对应的servlet文件的时候,会在service方法中自动声明一些对象,在jsp页面中可以直接使用
  2. 能在局部代码块和脚本调用中使用,但是不能在全局代码块中使用,因为全局代码块相当于定义在了service方法外,而service方法外部还没创建这九大对象
  3. 九大对象
    1. pageContext:表示页面的上下文对象,封存了其他的内置对象,封存了当前页面的运行信息。每一个页面都有一个对应的pageContext对象,伴随着当前页面的结束而结束
    2. request
    3. session
    4. application:ServletContext
    5. response
    6. page:代表当前jsp对象,跟java中的this类似
    7. exception:异常对象,存储当前运行的异常信息,必须在page指令中添加属性isErrorPage=“true”,service中才会创建该对象
    8. config:ServletConfig
    9. out:响应对象,jsp内部使用,带有缓存区的响应对象,比response高效
1.7 JSP四大作用域
  1. pageContext:当前页面
  2. request:请求
  3. session:一次会话
  4. application:项目内
<%--有了作用域,就可以在EL表达式中使用,效果与直接使用九大内置对象相同--%>
pageContext:<%=pageContext.getAttribute("key")%><br>
pageContext:${pageScope.key}<br>
1.8 JSP中路径问题
  1. 想要获得项目中的资源,可以使用相对路径,也可以使用绝对路径
  2. 相对路径:相对于当前页面的路径
    1. 资源的位置不可以随便更改
    2. 需要使用…/的方式进行文件夹跳出,如果目录比较深,操作起来麻烦
  3. 绝对路径:在请求的资源前面加/,表示当前服务器的根路径(http://localhost:8080/),使用的时候"/虚拟项目名/资源目录"
  4. 使用jsp自带的全局路径声明
    1. 相当于使用的相对路径不再是当前jsp路径,而是自定义的路径,一般改到"虚拟项目名"这层,使用时直接"资源目录",相当于改良了绝对路径表示法
  5. 示例
<%--
<%
    //http :// 127.0.0.1 8080 /myfirstServlet
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>
<html>

<head>
    <base href="<%=basePath%>">
    <title>Title</title>
</head>
<body>
<a href="wsh.jsp">tiaozhuan</a>
</body>
</html>

2 EL表达式

  1. 简化在jsp中获取作用域或请求数据的写法
2.1 传统方式的缺点
  1. 由于servlet与jsp二者不在同一个类中,jsp无法获取servlet中的泛型信息,因此必须进行强制转换
  2. 必须要导包
  3. 层次结构比较复杂
2.2 EL表达式
  1. Expression Language:一种表达式语言,语法简单
  2. 可以简化在jsp中获取作用域或请求数据的写法
  3. 替代getParameter(key)、getAttribute(key):${key}
  4. 不同作用域中,如果都通过addAttribute放入相同的key时,EL表达式取值顺序
    1. 以小的作用域的属性值为准
    2. 可以通过pageScope、requestScope、sessionScope、applicationScope获取指定作用域的数据,例:${requestScope.key}
    3. pageContext–>request–>session–>application
  5. 进行算数运算、关系运算、逻辑运算
    1. 如果是关系运算,返回true或false
    2. 此处"+"不能当做字符串连接符
      1. ${1+“abc”},执行时报错
      2. ${1+“2”},显式3
  6. 替代request.getHeader(key)
    1. ${header}:将请求头中信息封装为一个map对象并返回,注意setAttribute放入的属性值,无法通过该方法获取
    2. ${header[key]}或${header.host}:获取该map中,指定key的value值,如果一个host对应多个值报错
    3. ${headerValues[“accept-language”]}:获取一个数组,获得指定key值的一组value值,返回类型为String[]
    4. ${headerValues[“accept-language”][0]}:获得数组中的元素
  7. 替代request.getCookies
    1. ${cookie}:将cookie中信息封装为一个map对象并返回
    2. ${cookie.JSESSIONID}:获取该map中,指定key的value值,这个value是一个Cookie对象
    3. ${cookie.JSESSIONID.name}:获取该Cookie对象的name属性
    4. ${cookie.JSESSIONID.value}:获取该Cookie对象的value属性
2.3 EL表达式示例
  1. ELServlet
import entity.Address;
import entity.User;

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

public class ElServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String name = req.getParameter("name");
        String pwd = req.getParameter("pwd");
        System.out.println(name+":"+pwd);
        req.setAttribute("a1","beijing");
        User u = new User(1,"吴思含",new Address("辽宁省","沈阳市","皇姑区"));
        User u2 = new User(2,"刘雪婷",new Address("辽宁省","大连市","普兰店"));
        req.setAttribute("user",u);
        ArrayList<User> list = new ArrayList<>();
        list.add(u);
        list.add(u2);
        req.setAttribute("listwu",list);

        HashMap<String,String> map = new HashMap<>();
        map.put("china","beijing");
        map.put("liaoning","shenyang");
        req.setAttribute("mapwu",map);

        HashMap<String,User> map2 = new HashMap<>();
        map2.put("a1",u);
        map2.put("a2",u2);
        req.setAttribute("mapwu2",map2);
        req.getRequestDispatcher("el.jsp").forward(req,resp);
    }
}

  1. el.jsp
<%@ page import="entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--1. 使用传统写法获取作用域中的值--%>
<%--注意getParameter获取值时,必须是头或体中的数据,而不是通过setAttribute放入的数据--%>
name:<%=request.getParameter("name")%>
pwd:<%=request.getParameter("pwd")%>
00001:<%=request.getAttribute("a1")%>
皇姑区:<%=((User)request.getAttribute("user")).getAddress().getTown()%>
普兰店:<%=(((User)((ArrayList)request.getAttribute("listwu")).get(1)).getAddress()).getTown()%>
beijing:<%=((HashMap)request.getAttribute("mapwu")).get("china")%>
皇姑区:<%=((User)((HashMap)request.getAttribute("mapwu2")).get("a1")).getAddress().getTown()%>
<br/>
<%--2. 使用EL表达式获取作用域中的值--%>
name:${name}
pwd:${pwd}
00001:${a1}
皇姑区:${user.address.town}
普兰店:${listwu[1].address.town}
beijing:${mapwu.china}
皇姑区:${mapwu2.a1.address.town}
<!--两者相同-->
皇姑区:${mapwu2["a1"].address.town}
<br>
<%
//必须先导入jsp—api.jar,否则编译无法通过
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
key:${key}<br>
pageContext:${pageScope.key}<br>
request:${requestScope.key}<br>
session:${sessionScope.key}<br>
application:${applicationScope.key}<br>
${1+2}<br>
${1>2}<br>
<%--
执行时会报错
${1+"ab"}<br>
--%>
${1+"2"}<br>
${1+2}<br>
${1>2?"男":"女"}<br>
${true&&false}<br>

<!--一个包含所有头信息的map-->
${header}<br>
<!--两者用法相同-->
${header.host}<br>
${header["host"]}<br>
<!--当header中,有两个key值相同,value不同的属性时,可以用该方法,获取属性值的字符串数组,因此此处是一个String[]对象,打印[Ljava.lang.String; @ 6fba1c17-->
${headerValues["accept-language"]}<br>
<!--取String[]中的第一个元素,是String类型,因此打印zh-CN,zh; q = 0.9,zh-TW; q = 0.8,en-US; q = 0.7,en; q = 0.6-->
${headerValues["accept-language"][0]}<br>
<!--与${header["cookie"]}不同,header方式获取到的是cookie作为key的value的字符串,而后者,是包含所有cookie的map对象-->
${cookie}<br>
${cookie.JSESSIONID}<br>
${cookie.JSESSIONID.name}<br>
${cookie.JSESSIONID.value}<br>
</body>
</html>

3 JSTL

  1. Java server pages standarded tag library,即JSP标准标签库
  2. 帮助我们在jsp页面中添加复杂的逻辑判断,避免逻辑代码与页面标签混为一谈,即尽量不在jsp中编写java代码
  3. JSTL是EL的扩展,同时JSTL依赖于EL,可以方便的从作用域中获取值
  4. JSTL标签库导入
    1. 需下载jakarta-taglibs-standard-1.1.2.zip,将其内的jstl.jar、standard.jar放入WEB-INF/lib:因为标签实际上会被转为这两个jar包中的java类
    2. taglib导入标签库
    3. 有时标签库地址无法访问,可以人为设定标签库对应的tld文件:File-Settings-Schemas and DTDs
      1. uri:http://java.sun.com/jsp/jstl/core
      2. File:E:/sonar/jakarta-taglibs-standard-1.1.2/tld/c.tld
      3. 注意c.tld只是JSTL核心标签库的描述文件,此处相当于只能使用核心标签库
  5. 示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
</body>
</html>

3.1 JSTL内部分类
  1. 核心标签库:必须掌握
  2. 格式化标签库:掌握
  3. 函数标签库:了解
  4. XML标签库:了解
  5. SQL标签库:了解
3.2 JSTL中核心标签库中的标签
  1. out:输出标签
    1. value:要输出的值
    2. default:value为空时的默认值
  2. set:向作用域设置属性值
    1. var:表示参数的key
    2. value:参数的value
    3. scope:向哪个作用域设置属性值
    4. 注意:未配置scope时,默认向pageContext作用域中设置属性
  3. remove:删除作用域中的数据
    1. var:参数的key
    2. scope:指定作用域
    3. 注意:未配置scope时,默认删除所有作用域中数据
  4. if:
    1. test:填写逻辑判断表达式
    2. var:将条件表达式的结果,存储到新的变量
    3. scope:结果变量存储的作用域
  5. choose:
    1. 进行多重逻辑判断,类似于switch
  6. forEach
    1. begin:起始值
    2. end:结束值
    3. step:步长
    4. varStatus:表示循环状态的对象,其包含index、count等属性,表示当前循环的索引、值等
    5. var:集合、map中本次循环所对应的的那条数据。对于map,begin的值,表示map中的第几条数据,但要注意map无序,因此不会按一定顺序循环
    6. items:从作用域中获取的数据
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<br>
    <%request.setAttribute("att","value");%>
    <c:out value="${att}" default="嘿嘿"></c:out><br>

    <c:set var="java" value="page" scope="page" ></c:set>
    <c:set var="java" value="request" scope="request" ></c:set>
    <c:set var="java" value="session" scope="session" ></c:set>
    <c:set var="java" value="application" scope="application" ></c:set>

    <c:out value="${pageScope.java}"></c:out><br>
    <c:out value="${requestScope.java}"></c:out><br>
    <c:out value="${sessionScope.java}"></c:out><br>
    <c:out value="${applicationScope.java}"></c:out><br>

    <c:remove var="java" scope="request"></c:remove>
    <c:out value="${pageScope.java}"></c:out><br>
    <c:out value="${requestScope.java}"></c:out><br>
    <c:out value="${sessionScope.java}"></c:out><br>
    <c:out value="${applicationScope.java}"></c:out><br>

    <c:set var="a" value="6" ></c:set>
    <c:if test="${a>5}" var="flag" scope="request">
        大于5</c:if>

    <c:set var="b" value="40" ></c:set>
    <c:choose>
        <c:when test="${b<10}">
            少年<br>
        </c:when>
        <c:when test="${b<30}">
            青年<br>
        </c:when>
        <c:when test="${b<50}">
            中年<br>
        </c:when>
        <c:otherwise>
            老年<br>
        </c:otherwise>


    </c:choose>

    <table border="1px">
        <tr>
            <td>1</td>
            <td>111</td>
        </tr>
        <tr>
            <td>2</td>
            <td>222</td>
        </tr>
        <tr>
            <td>3</td>
            <td>333</td>
        </tr>
    </table>
    <c:forEach begin="0" end="5">
        wusihan<br>
    </c:forEach>
    <c:forEach begin="0" end="3" step="2" varStatus="stats">
        ${stats.index}--${stats.count}--${stats.first}--${stats.last}<br>
    </c:forEach>
<%
    ArrayList<String> arrayList = new ArrayList<String>();
    arrayList.add("wusihan");
    arrayList.add("liuxueting");
    arrayList.add("wuzijin");
    request.setAttribute("list",arrayList);
%>
    <c:forEach begin="0" end="2" var="abc" items="${list}">
        ${abc}<br>
    </c:forEach>
<%
    HashMap<String,String> map = new HashMap<String,String>();
    map.put("1","111");
    map.put("2","222");
    map.put("3","333");
    request.setAttribute("map",map);
%>
    <table border="1px">
        <c:forEach begin="0" end="2" var="i" items="${map}">
            <tr>
                <td>${i.key}</td>
                <td>${i.value}</td>
            </tr>

        </c:forEach>
    </table>
</body>
</html>

3.3 自学JSTL
  1. 菜鸟教程
https://www.runoob.com/jsp/jsp-jstl.html
  1. 需要时再看就可以
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值