JSP

之前我们写登录的时候,为了响应登录失败的错误信息,特意创建一个LoginErrorServlet用来动态拼接错误信息。
【总结一下】
在servlet中,能够直接获取后台服务器中的数据:获取数据方便。
通过拼接字符串的形式,给浏览器响应html:操作麻烦,效率太低,阅读性差。

现在可以用JSP技术,既能直接书写html代码,又能书写servlet代码。这样就能够在客户端直接进行数据交互了。

JSP全名为Java Server Pages,中文名叫java服务器页面,其本质是一个简化的Servlet 设计,它是由Sun 公司倡导、许多公司参与一起建立的一种动态网页 技术标准。其实就是一个既能书写Servlet代码又能书写HTML代码的文件。

新建的JSP文件长这样:

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

</body>
</html>

试着在JSP中写代码

<head>
    <title>Title</title>
</head>
<body>
<%--在jsp页面上获取当前日期,将其格式化成字符串“yyyy-MM-dd HH:mm:ss”--%>
<%
    LocalDateTime now=LocalDateTime.now();
    LocalDate now1= LocalDate.now();
    LocalTime now2=LocalTime.now();
    System.out.println(now);
%>
</body>
</html>

JSP运行原理
我们通过浏览器访问到的jsp页面,最终访问的是tomcat服务器中的jsp页面。所以,我们可以到tomcat中查看一下上面案例中的jsp页面是怎么样的一种存在。IntilliJ IDEA借助tomcat发布web项目的机制是动态发布(为每一个web项目创建一个单独的发布文件)。
我们可以通过tomcat其中日志中的CATALINA_BASE路径找到我们当前这个JSP页面在tomcat中的位置,打开之后会发现demo01.jsp编译为demo01.java文件,再编译成.class文件运行。
打开demo01_jsp.java文件后,发现我们在JSP页面上写的代码都在_jspService方法中:

  1. <% %> 中书写的代码被直接解析成java代码;
  2. html部分都被out.write("")方法以字符串的形式拼接,然后响应给浏览器;
  3. 在这个java文件中有个_jspService,这个方法有两个参数request,response。由此可看出JSP本质上就是一个Servlet。

JSP中写java代码的三种方式
在JSP页面的body标签中,可以直接书写html代码和JS代码。但是,如果在JSP页面中书写java代码。必须遵循固定的格式,才能够生效;JSP页面中书写java代码有三种方式:1.脚本片段;2.脚本声明;3.脚本表达式;

方式一:脚本片段
脚本片段指的是一段java代码。书写格式:<% java 代码 %>
方式二:脚本声明
脚本片段虽然可以嵌入java代码,但是如果,我们要给当前的jsp中定义一些成员方法或者成员变量,就行需要一个新的技术——脚本声明.
脚本声明的格式:<%! 书写Java代码 %>

<%!
    int a = 46;
    public void method(){
        System.out.print("");
    }
%>

方式三:脚本表达式
虽然脚本声明和脚本片段已经可以书写Java代码了,但是如果我们要使用java代码向页面输出一些内容,还是需要 使用原来的response对象,比较繁琐,因此,我们需要一个更加简便的方式,可以代替response向页面输出内容 ——这个就是脚本表达式。
脚本表达式的格式:<%= 内容 %> 等价于:out.print(内容)

<%="开发使人聪明"%>

JSP页面常用对象
在JSP页面中写的代码最终都会翻译到_jspService()方法中,这个方法中有两个入参:HttpServletRequest对象 ,HttpServletResponse对象 。所以说,JSP的本质就是一个Servlet。我们可以直接在JSP页面上使用这两个对象。

EL表达式
因为,脚本表达式在JSP页面上书写起来比较麻烦。而在页面上取值在开发中使用的又比较多,所以Sun公司为了简化在页面上的取值操作。
EL表达式从session中取值:${sessionScope.msg}
——记得:要去Java中访问LoginServlet,才能访问JSP页面

<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>登录页面</title>

    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="css/login.css" rel="stylesheet">
    <script src="js/jquery.js"></script>
    <script src="js/bootstrap.js"></script>
</head>
<body>
<%
//    String msg = (String) request.getAttribute("msg");
%>
<%--
EL表达式${msg}  从域对象中取值 session  servletContext request
<%=%> 浏览器输出内容
优势:方便  简化开发  pageContext--%>
<div class="container text-center">
    <form class="form-signin" action="/loginServlet" method="post">
        <h2 class="form-signin-heading">登录页面</h2>
        <%--<font color="red"><%=msg%></font>--%>
        <font color="red">${msg}</font>
        <input type="text"  name="username" class="form-control" placeholder="用户名" required autofocus>
        <input type="password"  name="password" class="form-control" placeholder="密码" required>
        <button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
    </form>
</div>
</body>

EL简介
全称:Expression Language
作用:代替jsp中脚本表达式的功能,简化对java代码的操作,从【域对象】中取值。EL表达式简化<%= %>方法取值。
EL语法表达式:${表达式内容}

EL取值

JSP的四大域对象:
page域、request域、session域、application域。我们通常使用EL表达式从这四大域对象取值。四大域对象的详细信息:
JSP与EL与JSTLEL表达式从这四大域中取值
JSP与EL与JSTL实践:
在一个jsp页面中,使用脚本表达式分别往request域、session域、ServletContext域和pageContext域中存取数据。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>四大域对象</title>
</head>
<body>
<%
    //向四大域对象中存储值   EL表达式来获取值  ${}
    pageContext.setAttribute("pageValue","page的值");
    request.setAttribute("requestValue","request的值");
    request.setAttribute("pageValue","request储存的其他值");
    session.setAttribute("sessionValue","session的值");
    application.setAttribute("applicationValue","application的值");
%>
<%--
直接通过KEY来获取域对象中的值-->key相同的时候
默认从范围小的开始检索,取值。
--%>
pageContext:${pageScope.pageValue}<br>
request:${requestScope.requestValue}<br>
session:${sessionScope.sessionValue}<br>
application:${applicationScope.applicationValue}<br>

request:${requestValue}<br>

相同key情况:${pageValue}
</body>
</html>

EL表达式搜索数据
EL表达式取值的时候也可以不指定域,如果取值的时候不指定域对象。就会按照从page域—>request域—>session域—>servletContext域从小到大逐级根据name属性值查找。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL表达式运算符</title>
</head>
<body>
<%
    request.setAttribute("n1",40);
    request.setAttribute("n2",30);
    request.setAttribute("n3","20");
    request.setAttribute("n4","10");

    String str = "";
    request.setAttribute("str",str);
    User user = null;
    request.setAttribute("user",user);
    List<String> list = new ArrayList<>();
    list.add("a");
    request.setAttribute("list",list);
%>
<%--
三元运算符:表达式1?表达式2:表达式3
empty 空
String str=""
User user   null  empty  true
List<T>  size() 0  empty  true
--%>
算数运算符:<br>
n1+n2:${n1+n2}<br>
n3-n4:${n3-n4}<br>
n1*n3:${n1*n3}<br>
关系运算符:<br>
n1==n2:${n1==n2}<br>
n4>=n3:${n4>=n3}<br>
n2!=n3:${n2 ne n3}<br>
逻辑运算符:<br>
false && true:${false && true}<br>
!true:${!true}<br>
三元运算符:<br>
${n1!=n2?"不等于":"等于"}<br>
empty运算符<br>
${empty str}<br>
${empty user}<br>
${not empty list}<br>
</body>
</html>

EL表达式从cookie中取值
servlet生成cookie
要去访问Java代码CreatCookieServlet,才能将cookie存储在浏览器中。

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取用户提交信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String check = request.getParameter("check");
        //用户是否点击
        if ("on".equals(check)){
            //用户点击了  创建cookie
            //创建cookieAPI
            Cookie cookieName = new Cookie("username",username);
            cookieName.getValue();
            Cookie cookiePwd = new Cookie("pwd",password);
            cookieName.setMaxAge(60*60*24*7);
            cookiePwd.setMaxAge(60*60*24*7);
            //将cookie响应回浏览器
            response.addCookie(cookieName);
            response.addCookie(cookiePwd);
        }else {
            //没有记住用户名和密码
        }
    }
}

empty运算(判空运算)
empyt运算符对以下数据运算返回true:

  1. 字符串:"";
  2. 空集合(size=0):List list = new ArrayList();
  3. 空对象(null):Student stu = null;
    【注】not empty可以用在EL表达式中,判断非空的情况。

EL表达式小结:

  • EL:Expression Language;
  • EL语法:${ }
  • 作用:简化脚本表达式的取值,简化<%= request.getAttribute(“name”) %> ===> ${name}
  • jsp的四大域对象
    • page域:pageContext pageContext.setAttrubute() pageContext.getAttribute() JSP特有 作用范围:当前的JSP页面
    • requst域:request request.setAttribute() request.getAttribute() 作用范围:一次请求和响应之间
    • session域: session session.setAttribute() session.getAttribute() 作用范围:会话期间(多次请求和响应)
    • servletContext域:application application.setAttribute() application.getAttribute() 作用范围:整个项目;
  • jsp从四大域中取值(指定域对象):
    • ${pageScope .name}
    • ${requestScope .name}
    • ${sessionScope .name}
    • ${applicationScope .name}
  • JSP搜索域对象中的值:page — request — session — servletContext
    • ${name}
  • 运算
    • 算术运算
    • 关系运算
    • 逻辑运算:&& || !
    • 三元运算
    • empty运算:empty notempty
      • 空字符串:""
      • 空对象:null
      • 空集合:list.size = 0;

JSTL标签库

举个栗子:在页面中遍历数组

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSTL</title>
</head>
<body>
//缺点
代码复杂出现问题,前端工程师,后端工程师,维护成本过高。
java程序员抽取,方便复用,节约时间
JSTL 
jsp页面尽量都是标签,不要出现java代码
标签底层都是java代码实现 实现了复用

<%
    int[] arr = {123,456,789};
    for (int i : arr) {
        out.println("<h1>"+i+"</h1>");
    }
%>
</body>
</html>

JSTL是什么
从JSP 1.1规范开始JSP就支持使用自定义标签,使用自定义标签大大降低了JSP页面的复杂度,同时增强了代码的重用性,因此自定义标签在WEB应用中被广泛使用。

许多WEB应用厂商都开发出了自己的一套标签库提供给用户使用,这导致出现了许多功能相同的标签,令网页制作者无所适从,不知道选择哪一家的好。

为了解决这个问题,
Apache Jakarta小组归纳汇总了那些网页设计人员经常遇到的问题,
开发了一套用于解决这些常用问题的自定义标签库,
这套标签库被SUN公司定义为标准标签库(The JavaServer Pages Standard Tag Library),简称JSTL。

使用JSTL可以解决用户选用不同WEB厂商的自定义标签时的困惑,JSP规范同时也允许WEB容器厂商按JSTL标签库的
标准提供自己的实现,以获取最佳性能

JSTL核心标签库
JSP与EL与JSTL需要两个包(依赖)
javax.servlet.jsp.jar
jstl-impl.jar

将标签库资源引入jsp页面
在JSP页面中通过以下标签,通过taglib标签引入JSTL资源:
<%@taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
注意:prefix:是jstl标签在使用的时候的前缀
uri:是标签库的资源路径。

在JSP页面中使用JSTL标签
在JSP页面中书写"<c: ",如果出现如下图的提示则说明标签库引入成功,我们可以根据提示信息使用自己需要的标签。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<c:out value="你爱柳岩"></c:out>
</body>
</html>

常用的JSTL标签
<c:if test="">标签的作用相当于java中的if判断语句。
【需求】在success.jsp页面上进行如下判断

  1. 使用<c:if> 标签判断session中的用户信息是否为空;
  2. 如果不为空:获取session中的用户信息,并将其展示在页面上;
  3. 如果为空:提示用户登录;
<%
    session.setAttribute("user",new User());
    session.setAttribute("users",null);
    int[] arr = {1,2,3,4,5};
    for(int i: arr){

    }
    for(int i=0; i< 10; i++){

    }
    request.setAttribute("arr",arr);

%>
<c:if test="${user == null}">
    用户登陆
</c:if>
<c:if test="${users == null}">
    请登陆
</c:if>
<br>
<c:forEach var="i" items="${arr}">
    ${i}
</c:forEach>

<c:foreach>标签的作用相当于java中的for循环。主要是对数据和集合进行遍历。
c:foreach标签的属性
JSP与EL与JSTL

var:在不循环对象的时候,保存的是控制循环的变量;在循环对象的时候,保存的是被循环对象中的元素
items:指定要循环的对象
varStatus:保存了当前循环过程中的信息(循环的开始、结束、步长、次数等)
begin:设置循环的开始
end:设置循环的结束
step:设置步长——间隔几次循环,执行一次循环体中的内容

【案例】c:foreach遍历案例

【需求】

  1. 遍历普通数组;
  2. 遍历实体类对象list集合;
  3. 遍历map集合;
<html>
<head>
    <title>商品列表</title>
</head>
<body>
<c:forEach var="item" items="${list}">
    商品名:${item.name}--惊爆价:<font color="red">${item.price}</font><br>
</c:forEach>
</body>
</html>

@WebServlet("/product")
public class ProductServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //去数据库查询所有商品信息
        //页面展示5  select * from product limit 0,5
        List<Product> list = new ArrayList<>();
        list.add(new Product("电脑",9.9));
        list.add(new Product("手机",2.8));
        list.add(new Product("键盘",1.3));

        //将查询的数据存放request域中
        request.setAttribute("list",list);
        //使用jsp来展示页面
        request.getRequestDispatcher("list.jsp").forward(request,response);
    }
}

遍历map集合

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    Map map = new HashMap();
    map.put("one","抹茶妹妹");
    map.put("two","刘强东");
    map.put("thr","王宝强");

    request.setAttribute("beiju",map);
%>
<c:forEach var="item" items="${beiju}">
    map的key:${item.key}:map的value值:${item.value}<br>
</c:forEach>
</body>
</html>

choose标签
用于指定多个条件选择的组合边界,它必须与c:when和c:otherwise标签一起使用。三个标签组合与switch语法类似。

choose标签子标签
介绍 c:when,相当于case。
c:when标签含有test属性,作用与if相同 c:otherwise,相当于default。

choose标签注意事项
三个标签必须组合使用,一组标签中不能出现两个c:otherwise

相关文章: