JSP的基本使用

JSP

1.JSP的基础语法

1.1.简介

JSP:Java Server Page SUN 公司提供的动态网页编程技术,是Java Web 服务器端的动态资源。

它相比 html而言,htm! 只能为用户提供静态数据,而Jsp 技术允许在页面中嵌套java 代码,为用户提供动态数据。

相比 servet 而言,servlet 很难对数据进行排版,而jsp 除了可以用java 代码产生动态数据的同时,也很容易对数据进行排版。

不管是JSP 还是 Servlet,虽然都可以用于开发动态 web 资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把 servlet 作为 web 应用中的控制器组件来使用, 而把JSP 技术作为数据显示模板来使用。

其实Jsp 就是一个 Servlet,当我们第一次访问Jsp 的时候,Jsp 引擎都会将这个Jsp 翻译成一个 Servlet,这个文件存放在tomcat(源码目录)中的work 目录中

1.2注释

JSP中支持两种注释的语法操作

一种是显示注释,这种注释是允许客户端看见的;另一种是隐式注释,此种注释是客户端无法看见的

1.显示注释语法 从HTML风格继承而来

2.隐式注释语法 从JAVA风格继承 JSP自己的注释

JSP的三种注释方法

1.// 注释 单行注释 /* 多行注释*/

1.3 Scriptlet 基础语法

三种基础语法

目前不建议JAVA写JSP中

在JSP中最重要的部分就是Scriptlet(脚本小程序),所有嵌入在HTML代码中的JAVA程序

在JSP中一共有三种Scriptlet代码 都必须使用Scriptlet标记胡来

<%--第一种:Java脚本段,可以写Java代码,定义局部变量,编写语句等--%>
<%--生成代码在servlet中的service方法体中--%>
<%
    //定义局部变量
    String str = "Hello JSP";
    //输出到控制台
    System.out.println(str);
    //输出到浏览器
    out.print(str);
    //输出全局变量
    out.write("全局变量" + num);
%>

<%--第二种:声明,声明全局变量,方法,类等--%>
<%--生成代码在servlet的类体中--%>
<%!
    int num = 10;
%>

<%--第三种:输出表达式,可以输出变量或字面量--%>
<%--生成代码在servlet中的service方法体中,相当于out.print()--%>
<%= num %>

2.JSP的指令标签

使用包含操作,可以将一些重复的代码包含进来继续使用,从正常的页面组成来看,有时可能分为几个区域。而其中的一些区域可能是一直不需要改变的,改变的就是其中一个具体内容区域,现在有两种方法可以实现上述功能。

将工具栏,头部信息 尾部信息都分成各个独立的文件,使用的时候直接导入

静态包含 动态包含 静态包含使用include 指令即可,动态包含则需要使用Include动作标签

静态包含

将网页内容进行拼接,最终只有一个资源文件,内容全在jsp Service方法体中

<%@include file=“要包含文件的相对路径”%>

  1. 将内容进行了直接的替换
  2. 静态包含只会生成一个源码文件,最终的内容都在_jspService方法体中(源码文件中)
  3. 不可以出现同名变量

动态包含

  1. 动态包含相当于方法调用
  2. 动态包含会生成多个源码文件
  3. 可以定义同名变量
  4. 效率高 耦合度低
  5. 当动态包含不需要传递参数时,include 双标签之间不要有任何内容,包括换行和空格
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<jsp:include page="04头.jsp"></jsp:include>
<h2>主体</h2>>
<%
String str = "hello";
%>
<jsp:include page="04脚.jsp">
    <%--page支持表达式--%>
    <jsp:param name="uname" value="admin"/>
    <jsp:param name="msg" value="<%=str%>"/>
    <%--name不支持表达式,value支持表达式--%>
</jsp:include>
</body>
</html>

3.JSP的四大域对象

  1. pageContext:只在一个页面中保存属性,跳转之后无效
  2. request:只在一次请求中保存,服务器跳转后依然有效
  3. session:在一次会话范围中,无论何种跳转都可以使用
  4. application:在整个服务器上保存
方法描述
public void setAttribute(String name, Object o)设置属性的名称及内容
public Object getAttribute(String name)根据属性名称取属性
public void removeAttribute(String name)删除指定的属性

验证属性范围的特点

在合理的条件下尽可能的小,一般request

  1. page

本页面取得,服务器端跳转(jsp:forward)后无效

2.request

服务器跳转有效,客户端跳转无效如果是客户端跳转,则相当于发出了两次请求,那么第一次的请求将不存在了;如果希望不管是客户端还是服务器跳转,都能保存的话,就需要继续扩大范围

3.session

无论客户端还是服务器端都可以取得,但是现在重新开启一个新的浏览器,则无法取得之前设置的session了,因为每一个session只保存在当前的浏览器当中,并在相关的页面取得对于服务器而言,每一个连接到它的客户端都是一个session如果想要让属性设置一次之后,不管是否是新的浏览器打开都能取得则可以使用application

4.application

所有的application属性直接保存在服务器上,所有的用户(每一个session)都可以直接访问取得只要是通过application设置的属性,则所有的session都可以取得,表示公共的内容,但是如果此时服务器重启了,则无法取得了,因为关闭服务器后,所有的属性都消失了,所以需要重新设置

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    //设置page范围的域对象
    pageContext.setAttribute("name1","zhangsan");
    //设置request范围的域对象
    request.setAttribute("name2","zhangsan");
    //设置session范围的域对象
    session.setAttribute("name3","zhangsan");
    //设置application范围的域对象
    application.setAttribute("name4","zhangsan");
%>

<%--jsp中服务端跳转--%>
<jsp:forward page="04静态包含.jsp"></jsp:forward>
</body>
</html>

简易版登录

loginServlert.java

package com.xxxx.controller;

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

@WebServlet("/loginServlert")
public class loginServlert extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");
        String uname=req.getParameter("uname");
        //  接受客户端传递的参数
        String upwd=req.getParameter("upwd");
        // 判断参数是否为空
        if (uname == null || "".equals(uname.trim())){
            // 提示用户信息
            req.setAttribute("msg","用户姓名不能为空");
            // 请求转发跳转到
            System.out.println(uname);
            req.getRequestDispatcher("login.jsp").forward(req,resp);
             return;
        }
        if (upwd == null || "".equals(upwd.trim())){
            // 提示用户信息
            req.setAttribute("msg","用户密码不能为空");
            //请求转发
            req.getRequestDispatcher("login.jsp").forward(req,resp);
            System.out.println(uname);
            return;
        }
        // 判断账号密码是否正确 uname=admin upwd=admin

        if (!"admin".equals(uname) || !"admin".equals(upwd)){
            req.setAttribute("msg","登录失败");
            req.getRequestDispatcher("login.jsp").forward(req,resp);
            return;
        }
        //登录成功
        // 设置登录信息保存到Session作用域
        req.getSession().setAttribute("uname",uname);
        resp.sendRedirect("index.jsp");

    }
}
<%--
  Created by IntelliJ IDEA.
  User: 86159
  Date: 2024/2/18
  Time: 21:51
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
    <form action="loginServlert" method="post">
        姓名: <input type="text" name="uname"><br>
        密码: <input type="password" name="upwd"><br>
        <button>登录</button>
        <span style="color: red;font-size: 12px"><%=request.getAttribute("msg")%></span>
    </form>
</body>
</html>

4.EL表达式的使用

4.1EL表达式的语法

EL(Expression Language)是为了使JSP写起来更加简单。表达式语言的灵感来自于ECMAScript和XPath表达式语言,他提供了在JSP中简化表达式的方法 ,让JSP的代码更加简化

语法结构非常简单: ${expression}

EL表达式一般操作的都是域对象中的数据,操作不了局部变量

域对象在JSp中一共有四个 pageContext request session application

当需要指定从某个特定的域对象中查找数据时可以使用四个域对象对应 的空间对象,分别是 pageScope requestScope sessionScope applicationScope

而EL默认的查找方式是从小到大查找,找到即可 当域对象全找完了还未找到则返回空字符串"".

4.2 EL表达式的使用

4.2.1 获取数据

设置域对象中的数据

<%--
  Created by IntelliJ IDEA.
  User: 86159
  Date: 2024/2/20
  Time: 12:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL表达式</title>
</head>
<body>
<%--  EL表达式
         作用  简化JSP代码
      格式
         ${域对象的名称}
      操作对象
         EL表达式一般操作的是域对象 不能操作局部变量
--%>
<%  pageContext.setAttribute("uname","zhangsan");  // page作用域
    request.setAttribute("uname","lisi");
    session.setAttribute("uname","wangwu");
    application.setAttribute("uname","zhaoliu");

    //  定义局部变量
    String str="Hello";

%>
<%--获取变量--%>
获取局部变量:${str}<br>
获取域对象${uname} <br>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    List<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    request.setAttribute("list", list);
%>
<h4>获取List</h4>
获取List的size:${list.size()}<br>
获取List指定下标的值:${list[1]}<br>

<%
    Map map = new HashMap<>();
    map.put("aaa", "111");
    map.put("bbb", 222);
    map.put("ccc", 3330);
    request.setAttribute("map", map);
%>
<h4>获取Map</h4>
获取Map指定key的value:${map.aaa}<br>${map["bbb"]}

<h4>获取JavaBean</h4>
获取JavaBean中的属性:${person.name}<br>${person.getName()}
</body>
</html>
Empty

${empty xxx},判断域中对象是否为空,为空返回true

EL运算

${xxx == yyy}or${xxx eq yyy}两个是否相等

${xxx ? yyy}`,? =`+ - * /`or`> < ≥ ≤ 可以有&&||

JSTL

1.1标签的使用

Jar包的引用

在web\WEB-INF下创建lib文件夹,把以下的Jar包复制到新建的lib下,添加为库

<%@taglib uri="" prefix=""%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <c:if test="${1==1}">
        Hello JSTL
    </c:if>
</body>
</html>

JSTL标签

if 标签

if标签操作的一般都是域对象

if标签没有else 如果想要else的效果 就需要设置两个完全想法到条件

属性描述是否必要默认
test条件
var用于储存条件结果的变量(限域变量名)
scopevar属性的作用域
可取值 page | request | session | application
pag
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("num", 10);
%>
<c:if test="${num > 0}">
    数字大于0
</c:if>
<c:if test="${num > 10}" var="flag" scope="request"></c:if>
<%--test条件,var限域变量名,scope限域变量的作用范围--%>
<%--没有else效果--%>
${flag}
${requestScope.flag}
${sessionScope.flag}
</body>
</html>
choose、when和otherwise标签

switch语句中中有case 而 choose标签中对应有When ,switch语句中域default 而choose标签中有otherwise

when 有一个test属性 其他的没有

## JSTL标签

#### if标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("num", 10);
%>
<c:if test="${num > 0}">
    数字大于0
</c:if>
<c:if test="${num > 10}" var="flag" scope="request"></c:if>
<%--test条件,var限域变量名,scope限域变量的作用范围--%>
<%--没有else效果--%>
${flag}
${requestScope.flag}
${sessionScope.flag}
</body>
</html>
```


#### choose、when和otherwise标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("score", 80);
%>
<c:choose>
    <c:when test="${score<60}">
        <h2>6</h2>
    </c:when>
    <c:when test="${score==60}">
        <c:if test="${1==1}">
            <h2>6</h2>
        </c:if>
        <h2>及格就行</h2>
    </c:when>
    <c:when test="${score>60 && score<80}">
        <h2>6</h2>
    </c:when>
    <c:when test="${score>=80}">
        <h2>6</h2>
    </c:when>
    <c:otherwise>
        <h2>6</h2>
    </c:otherwise>
</c:choose>
</body>
</html>
```


#### forEach标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--语法格式--%>
<%--
    <c:forEach
        items="要被循环的数据"
        begin="开始的元素"
        end="最后一个元素"
        step="迭代的步长"
        var="当前条目的变量名称"
        varStatus="循环状态的变量名称"></c:forEach>
--%>
<c:forEach var="" items="" step="" end="" begin="" varStatus=""></c:forEach>
<%--1.迭代主体内容多次,相当于普通for--%>
<c:forEach var="i" begin="1" end="10" step="2">
    ${i}&nbsp;
</c:forEach>
<hr>

<%--2.循环,相当于增强for--%>
<%
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add("A" + i);
    }
    pageContext.setAttribute("li", list);
%>
<c:forEach items="${li}" var="item">
    ${item}&nbsp;
</c:forEach>
<hr>

<table align="center" border="1" style="border-collapse: collapse;" width="800">
    <tr>
        <th>名称</th>
        <th>当前成员下标</th>
        <th>当前成员循环数</th>
        <th>是否第一次被循环</th>
        <th>是否最后一次被循环</th>
    </tr>
    <c:forEach items="${li}" var="item" varStatus="itemp">
        <tr>
            <td>${item}</td>
            <td>${itemp.index}</td>
            <td>${itemp.count}</td>
            <td>${itemp.first}</td>
            <td>${itemp.last}</td>
        </tr>
    </c:forEach>
</table>
<%--循环对象集合--%>
<%
    List<User> userList = new ArrayList<>();
    User user1 = new User(1, "zhangsan", "123");
    User user2 = new User(1, "lisi", "456");
    User user3 = new User(1, "wangwu", "798");
    Collections.addAll(userList, user1, user2, user3);
    request.setAttribute("userList", userList);
%>
<%--判断集合是否为空--%>
<c:if test="${!empty userList}">
    <table align="center" border="1" style="border-collapse: collapse;" width="800">
        <tr>
            <th>编号</th>
            <th>名称</th>
            <th>密码</th>
            <th>操作</th>
        </tr>
        <c:forEach items="${userList}" var="user">
            <tr>
                <td>${user.userId}</td>
                <td>${user.uname}</td>
                <td>${user.upwd}</td>
                <td>
                    <button>修改</button>
                </td>
            </tr>
        </c:forEach>
    </table>
    >
</c:if>
<%--循环map--%>
<%
    Map<String, Object> map = new HashMap<>();
    map.put("map1", "aaa");
    map.put("map2", "bbb");
    map.put("map3", "ccc");
    pageContext.setAttribute("map", map);
%>
<c:forEach items="${map}" var="m">
    ${m.key}+${m.value}
</c:forEach>
</body>
</html>
```


#### 格式化动作标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--
    formatNumber标签
        语法格式:<fmt:formatNumber
            value="要格式化的数值"
            type="要格式化成的数值,number(数值,默认),percent(百分比),currency(货币)"
            var="限域变量名,用来接收结果"
            scope="限域变量的范围">
            注:使用了var属性,格式化后不会直接输出数值
--%>
<fmt:formatNumber value="10" type="number" var="num"/>${num}

<fmt:setLocale value="en_US"/>
<fmt:formatNumber value="10" type="currency"/>

<fmt:formatNumber value="10" type="percent"/>
<%--
    formatDate标签
        语法格式:
            <fmt:formatDate
                value="要格式化的日期"
                type="格式化成的类型,date(年月日),time(时分秒),both(年月日时分秒)"
                dateStyle="日期的格式"
                timeStyle="时间的格式"
                pattern="自定义格式"
                timeZone="时区"
                var="限域变量名"
                scope="限域变量的域"></fmt:formatDate>

--%>
<%
    request.setAttribute("myData", new Date());
%>
${myData}<br>
<fmt:formatDate value="${myData}"/><br>
<fmt:formatDate value="${myData}" type="date"/><br>
<fmt:formatDate value="${myData}" type="time"/><br>
<fmt:formatDate value="${myData}" type="both"/><br>
<fmt:formatDate value="${myData}" type="both" dateStyle="FULL"/><br>
<fmt:formatDate value="${myData}" type="both" timeStyle="short"/><br>
<fmt:formatDate value="${myData}" pattern="yyyy-MM-dd"/><br>
<%--
    parseNumber
--%>
<fmt:parseNumber value="100"/>
<fmt:parseNumber value="100" type="number"/>
<fmt:parseNumber value="100%" type="percent"/>
<fmt:parseNumber value="¥10.00" type="currency"/>

<%--
    parseDate
--%>
<fmt:parseDate value="2020-01-01" type="date"/>
<fmt:parseDate value="2020/01/01" pattern="yyyy/MM/dd"/>
</body>
</html>
```


## JSTL标签

#### if标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("num", 10);
%>
<c:if test="${num > 0}">
    数字大于0
</c:if>
<c:if test="${num > 10}" var="flag" scope="request"></c:if>
<%--test条件,var限域变量名,scope限域变量的作用范围--%>
<%--没有else效果--%>
${flag}
${requestScope.flag}
${sessionScope.flag}
</body>
</html>
```


#### choose、when和otherwise标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("score", 80);
%>
<c:choose>
    <c:when test="${score<60}">
        <h2>6</h2>
    </c:when>
    <c:when test="${score==60}">
        <c:if test="${1==1}">
            <h2>6</h2>
        </c:if>
        <h2>及格就行</h2>
    </c:when>
    <c:when test="${score>60 && score<80}">
        <h2>6</h2>
    </c:when>
    <c:when test="${score>=80}">
        <h2>6</h2>
    </c:when>
    <c:otherwise>
        <h2>6</h2>
    </c:otherwise>
</c:choose>
</body>
</html>
```
forEach标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--语法格式--%>
<%--
    <c:forEach
        items="要被循环的数据"
        begin="开始的元素"
        end="最后一个元素"
        step="迭代的步长"
        var="当前条目的变量名称"
        varStatus="循环状态的变量名称"></c:forEach>
--%>
<c:forEach var="" items="" step="" end="" begin="" varStatus=""></c:forEach>
<%--1.迭代主体内容多次,相当于普通for--%>
<c:forEach var="i" begin="1" end="10" step="2">
    ${i}&nbsp;
</c:forEach>
<hr>

<%--2.循环,相当于增强for--%>
<%
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add("A" + i);
    }
    pageContext.setAttribute("li", list);
%>
<c:forEach items="${li}" var="item">
    ${item}&nbsp;
</c:forEach>
<hr>

<table align="center" border="1" style="border-collapse: collapse;" width="800">
    <tr>
        <th>名称</th>
        <th>当前成员下标</th>
        <th>当前成员循环数</th>
        <th>是否第一次被循环</th>
        <th>是否最后一次被循环</th>
    </tr>
    <c:forEach items="${li}" var="item" varStatus="itemp">
        <tr>
            <td>${item}</td>
            <td>${itemp.index}</td>
            <td>${itemp.count}</td>
            <td>${itemp.first}</td>
            <td>${itemp.last}</td>
        </tr>
    </c:forEach>
</table>
<%--循环对象集合--%>
<%
    List<User> userList = new ArrayList<>();
    User user1 = new User(1, "zhangsan", "123");
    User user2 = new User(1, "lisi", "456");
    User user3 = new User(1, "wangwu", "798");
    Collections.addAll(userList, user1, user2, user3);
    request.setAttribute("userList", userList);
%>
<%--判断集合是否为空--%>
<c:if test="${!empty userList}">
    <table align="center" border="1" style="border-collapse: collapse;" width="800">
        <tr>
            <th>编号</th>
            <th>名称</th>
            <th>密码</th>
            <th>操作</th>
        </tr>
        <c:forEach items="${userList}" var="user">
            <tr>
                <td>${user.userId}</td>
                <td>${user.uname}</td>
                <td>${user.upwd}</td>
                <td>
                    <button>修改</button>
                </td>
            </tr>
        </c:forEach>
    </table>
    >
</c:if>
<%--循环map--%>
<%
    Map<String, Object> map = new HashMap<>();
    map.put("map1", "aaa");
    map.put("map2", "bbb");
    map.put("map3", "ccc");
    pageContext.setAttribute("map", map);
%>
<c:forEach items="${map}" var="m">
    ${m.key}+${m.value}
</c:forEach>
</body>
</html>
格式化动作标签

formatNumber标签.

formatDate标签

parseNumber

parseDates

#### 格式化动作标签

```Java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--
    formatNumber标签
        语法格式:<fmt:formatNumber
            value="要格式化的数值"
            type="要格式化成的数值,number(数值,默认),percent(百分比),currency(货币)"
            var="限域变量名,用来接收结果"
            scope="限域变量的范围">
            注:使用了var属性,格式化后不会直接输出数值
--%>
<fmt:formatNumber value="10" type="number" var="num"/>${num}

<fmt:setLocale value="en_US"/>
<fmt:formatNumber value="10" type="currency"/>

<fmt:formatNumber value="10" type="percent"/>
<%--
    formatDate标签
        语法格式:
            <fmt:formatDate
                value="要格式化的日期"
                type="格式化成的类型,date(年月日),time(时分秒),both(年月日时分秒)"
                dateStyle="日期的格式"
                timeStyle="时间的格式"
                pattern="自定义格式"
                timeZone="时区"
                var="限域变量名"
                scope="限域变量的域"></fmt:formatDate>

--%>
<%
    request.setAttribute("myData", new Date());
%>
${myData}<br>
<fmt:formatDate value="${myData}"/><br>
<fmt:formatDate value="${myData}" type="date"/><br>
<fmt:formatDate value="${myData}" type="time"/><br>
<fmt:formatDate value="${myData}" type="both"/><br>
<fmt:formatDate value="${myData}" type="both" dateStyle="FULL"/><br>
<fmt:formatDate value="${myData}" type="both" timeStyle="short"/><br>
<fmt:formatDate value="${myData}" pattern="yyyy-MM-dd"/><br>
<%--
    parseNumber
--%>
<fmt:parseNumber value="100"/>
<fmt:parseNumber value="100" type="number"/>
<fmt:parseNumber value="100%" type="percent"/>
<fmt:parseNumber value="¥10.00" type="currency"/>

<%--
    parseDate
--%>
<fmt:parseDate value="2020-01-01" type="date"/>
<fmt:parseDate value="2020/01/01" pattern="yyyy/MM/dd"/>
</body>
</html>
```


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--
    formatNumber标签
        语法格式:<fmt:formatNumber
            value="要格式化的数值"
            type="要格式化成的数值,number(数值,默认),percent(百分比),currency(货币)"
            var="限域变量名,用来接收结果"
            scope="限域变量的范围">
            注:使用了var属性,格式化后不会直接输出数值
--%>
<fmt:formatNumber value="10" type="number" var="num"/>${num}

<fmt:setLocale value="en_US"/>
<fmt:formatNumber value="10" type="currency"/>

<fmt:formatNumber value="10" type="percent"/>
<%--
    formatDate标签
        语法格式:
            <fmt:formatDate
                value="要格式化的日期"
                type="格式化成的类型,date(年月日),time(时分秒),both(年月日时分秒)"
                dateStyle="日期的格式"
                timeStyle="时间的格式"
                pattern="自定义格式"
                timeZone="时区"
                var="限域变量名"
                scope="限域变量的域"></fmt:formatDate>

--%>
<%
    request.setAttribute("myData", new Date());
%>
${myData}<br>
<fmt:formatDate value="${myData}"/><br>
<fmt:formatDate value="${myData}" type="date"/><br>
<fmt:formatDate value="${myData}" type="time"/><br>
<fmt:formatDate value="${myData}" type="both"/><br>
<fmt:formatDate value="${myData}" type="both" dateStyle="FULL"/><br>
<fmt:formatDate value="${myData}" type="both" timeStyle="short"/><br>
<fmt:formatDate value="${myData}" pattern="yyyy-MM-dd"/><br>
<%--
    parseNumber
--%>
<fmt:parseNumber value="100"/>
<fmt:parseNumber value="100" type="number"/>
<fmt:parseNumber value="100%" type="percent"/>
<fmt:parseNumber value="¥10.00" type="currency"/>

<%--
    parseDate
--%>
<fmt:parseDate value="2020-01-01" type="date"/>
<fmt:parseDate value="2020/01/01" pattern="yyyy/MM/dd"/>
</body>
</html>

登录页面的实现

计划

用户登录
  1.数据库创建对应的用户表  tb_user  (Mysql)
  2.前台页面
      登录页面  login.jsp
         用户登录 JS效验
            登录表单验证
              1.给登录按钮绑定点击事件
              2.获取用户姓名和密码的值
              3.判断姓名是否为空
                   如果为空 提示用户(span标签赋值),并且return
              4.判断密码是否为空
                   如果为空 提示用户(span标签赋值),并且return
              5.如果都不为空 则手动提交表单

      首页    index.jsp
  3.后代实现
      登录功能
        思路
              1.接收客户端请求(接收参数和密码)
                        2.参数的判断
                            如果参数为空
                                通过消息模型对象返回结果(设置状态,设置提示信息,回显数据)
                                将消息模型对象设置到request作用域中
                                请求转发到登录页面
                                return
                        3.通过用户姓名查询用户对象
                        4.判断用户对象是否为空
                            如果为空
                                通过消息模型对象返回结果(设置状态、设置提示信息、回显数据)
                                将消息模型对象设置到request作用域中
                                请求转发到登录页面
                                return
                        5.将数据库中查询到的用户密码与前台传递的密码作比较
                            如果为空不相等
                                通过消息模型对象返回结果(设置状态、设置提示信息、回显数据)
                                将消息模型对象设置到request作用域中
                                请求转发到登录页面
                                return
                            如果相等,表示登录成功
                                将用户信息设置到session作用域中
                                重定向跳转到首页

分层思想(解耦:高内聚低耦合)
    controller层(接收请求、响应结果)
           1.接收请求(接收参数:姓名、密码)
           2.调用service层,返回结果消息模型对象
           3.判断消息模型状态码
               如果失败
                   将消息模型对象设置到request中,请求转发到login.jsp
               如果成功
                   将消息模型的用户信息设置到session作用域中,重定向到index.jsp
       service层(业务逻辑判断)
           1.参数的非空判断
               如果为空
                   将状态码、提示信息、回显数据设置到消息模型对象中
           2.调用Dao层的查询方法,通过用户名查询用户
           3.判断用户对象是否为空
               将状态码、提示信息、回显数据设置到消息模型对象中,返回消息对象模型
           4.判断数据库密码和用户输入密码作比较
               如果不相等,将状态码、提示信息、回显数据设置到消息模型对象中,返回消息对象模型
           5.将成功状态、提示信息、用户对象设置到消息模型对象中
        mapper
          接口类
          mapper.xml mybatis与数据库的相关操作
        pojo
          JavaBean实体
      util
          工具类(通用的方法/类)
      test
          测试类/方法
```

Login.jsp

<%--
  Created by IntelliJ IDEA.
  User: 86159
  Date: 2024/2/20
  Time: 16:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登录</title>
</head>
<body>
<div style="text-align: center">
    <form action="/login" method="post" id="loginForm">
        用户:<input type="text" name="uname" id="uname" value="${massageModel.object.userName}"><br>
        密码:<input type="password" name="upwd" id="upwd" value="${massageModel.object.userPwd}"><br>
        <span id="msg" style="font-size: 12px;color: red">${massageModel.msg}</span><br>
        <button type="button" id="loginBtn">登录</button>
        <button type="button">注册</button>
    </form>
</div>
</body>
<%--引入Jquery的js文件--%>
<script type="text/javascript" src="js/jquery-3.7.1.min.js"></script>
<script>
    $("#loginBtn").click(function (){
        //获取用户和密码的值
        let uname = $("#uname").val();
        let upwd = $("#upwd").val();
        //判断姓名和密码是否为空
        if (isEmpty(uname)){
            $("#msg").html("用户名不可为空");
            console.log(uname);
            return;
        }
        if (isEmpty(upwd)){
            $("#msg").html("密码不可为空");
            return;
        }
        //如果都不为空则手动提交表单
        $("#loginForm").submit();
    });
    //判断字符串是否为空的方法
    function isEmpty(str){
        if (str==null||str.trim()==""){
            return true;
        }
        return false;
    }
</script>
</html>

mysql.properties(mysql部署文件)

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/java_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username=root
password=248690

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- properties  标签中的配置可以供整个配置文件使用,在任何位置都可以引入其中配置的值
标签可以通过子标签property 标签来配置一些子元素信息  也可以配置外部的动态文件-->
    <properties resource="mysql.properties"/><!--也可以配置url 但url和resource只能存在一个-->
    <!--类型别名-->
    <!--  <typeAliases>
      <typeAlias alias="User" type="com.xxxx.entity.User"/>
      </typeAliases> -->
    <!--对事物的管理和连接池的配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- mappers映射器-->
    <mappers>
        <!--映射文件方式1  一个一个的配置-->
        <!-- <mapper resource="com/xxxx/mapper/UserMapper.xml"/>
        <mapper class="com.xxxx.mapper.UserMapper"/>-->
        <!--映射文件方式2 自动扫描包内的Mapper接口与配置文件-->
        <package name="com.xxxx.mapper"/>
    </mappers>
</configuration>

UserMapper.xml(接口文件)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 首先解析 namespace: 命名空间 此属性通常用来映射Dao层接口-->
<mapper namespace="com.xxxx.mapper.UserMapper">
<!--     id  对应Dao层接口方法名  paraneterType-->
    <select id="queryUserByName" parameterType="String" resultType="com.xxxx.entity.User">
        select * from tb_user where userName = #{userName}
    </select>
</mapper>

UserMapper

package com.xxxx.mapper;

import com.xxxx.entity.User;

//用户接口类
public interface UserMapper {
    public User queryUserByName(String userName);
}

UserServlet

package com.xxxx.controller;

import com.xxxx.entity.vo.MessageModel;
import com.xxxx.service.UserService;

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

@WebServlet("/login")
public class UserServlet extends HttpServlet {
    // 实例化UserService对象
    private UserService userService = new UserService();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("1111111111");
//1.接收请求(接收参数:姓名、密码)
        String uname = req.getParameter("uname");
        String upwd = req.getParameter("upwd");
        //2.调用service层,返回结果消息模型对象
        MessageModel messageModel= userService.userLogin(uname,upwd);
        //3.判断消息模型状态码
        if (messageModel.getCode() == 1) { //成功
            // 将消息模型中的用户信息设置到session作用域中 重定向跳转到Index.jsp中
            req.getSession().setAttribute("user", messageModel.getObject());
            System.out.println("1222222");
            resp.sendRedirect("index1.jsp");
        } else {  // 失败
            // 将消息模型对象设置到request作用域中 请求跳转到Login.jsp
            req.setAttribute("messageModel", messageModel);
            req.getRequestDispatcher("login.jsp").forward(req, resp);
        }
    }
}

MessageModel

package com.xxxx.entity.vo;

/*
* 消息模型对象(数据相应)
* 状态码
* 1=成功  0=失败
* 提示信息
* 字符串
* 回显数据、
* object对象
* */
public class MessageModel {
    private Integer code=1;   // 状态码  1=成功 0=失败
    private String  msg="成功";  //  提示信息
    private Object  object;  // 回显对象 基本数据类型 字符串类型 list map

    public Integer getCode() {
        return code;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

User 实体类

package com.xxxx.entity;

/* User实体类
*/
public class User {
    private Integer userId; //用户编号
    private String userName;   //  姓名
    private String userPwd;   //  密码
    private Integer userAge;   //  年龄

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPwd() {
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }

    public Integer getUserAge() {
        return userAge;
    }

    public void setUserAge(Integer userAge) {
        this.userAge = userAge;
    }
}

UserService

package com.xxxx.service;

import com.xxxx.entity.User;
import com.xxxx.entity.vo.MessageModel;
import com.xxxx.mapper.UserMapper;
import com.xxxx.util.GetSqlSession;
import com.xxxx.util.StringUtil;
import org.apache.ibatis.session.SqlSession;

public class UserService {
    public MessageModel userLogin(String uname,String upwd){
        MessageModel messageModel=new MessageModel();
        //  回显数据
        User u=new User();
        u.setUserName(uname);
        u.setUserPwd(upwd);
        messageModel.setObject(u);
        // 参数的非空判断
        if (StringUtil.isEmpty(uname) || StringUtil.isEmpty(upwd)){
            //将状态码 提示信息  回显数据设置到消息模型对象中 返回消息模型对象
            messageModel.setCode(0);
            messageModel.setMsg("用户名和密码不能为空!");
            return messageModel;
        }
        // 调用dao层的查询方法 通过用户名查询用户对象
        SqlSession session= GetSqlSession.createSqlSession();
        UserMapper userMapper=session.getMapper(UserMapper.class);
        User user=userMapper.queryUserByName(uname);
        // 判断用户对象是否为空
        if (user==null){
            //将状态码 提示信息  回显数据设置到消息模型对象中 返回消息模型对象
            messageModel.setCode(0);
            messageModel.setMsg("用户不存在");
            return messageModel;
        }
        //4.判断密码
        if (!upwd.equals(user.getUserPwd())){
            messageModel.setCode(0);
            messageModel.setMsg("用户密码不正确!");
            return messageModel;
        }
        //5.登录成功,将用户信息设置到消息模型中
        return messageModel;
    }
}

GetSqlSession

package com.xxxx.util;


import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/*
* 获取SqlSession对象
* @return
* */
public class GetSqlSession {
    public static SqlSession createSqlSession(){
        SqlSessionFactory sqlSessionFactory=null;
        InputStream input=null;
        SqlSession session=null;
        try {
            // 获得mybatis的环境配置文件
            String resource="mybatis-config.xml";
            //以流的方式获取recource(mybatis的环境配置文件)
            input = Resources.getResourceAsStream(resource);
            //创建会话工厂
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(input);
            // 通过工厂得到SqlSession
            session=sqlSessionFactory.openSession();
            return session;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        System.out.println(createSqlSession());
    }
}

StringUtil

package com.xxxx.util;

/*
* 字符串工具类*/
public class StringUtil {
    public static boolean isEmpty(String str){
        if (str==null || "".equals(str.trim()) ){
            return true;
        }
        return false;
    }
}

过滤器与监听器

过滤器介绍

  1. Filter即为过滤器,用于在Servlet之外对Request或者Response进行修改
  2. 主要用于对用户的请求进行预处理,也可以对HttpServletResponse进行后处理
  3. 使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后Filter再对服务器响应进行后处理
  4. 在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链

过滤器实现

/*
* 过滤器
*   1.@WebFilter("/*") 配置拦截路径
*   2.doFilter() 方法设置放行,否则请求无法到达资源 filterChain.doFilter(servletRequest, servletResponse);
*   3.如果是过滤器链,则先配置的先执行(首字母在前的),响应时反过来执行
* */
//拦截"/s01"
//@WebFilter("/s01")
//拦截所有
@WebFilter("/*")
public class Filter01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter01 init");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter1前拦截中");
        //放行资源
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filter1后响应中");
    }
    @Override
    public void destroy() {
        System.out.println("Filter01 destroy");
    }
}

请求乱码

<filter>
  	<filter-name>CharacterEncoding</filter-name>
  	<filter-class>com.suo.CharacterEncodingFilter</filter-class>
  	<init-param>
  		<param-name>encoding</param-name>
  		<param-value>utf-8</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncoding</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter
{
	protected String encoding=null;
	protected FilterConfig filterConfig=null;
	protected boolean ignore=true;
	
	public CharacterEncodingFilter(){}
	
	public void destroy()
	{
		this.encoding=null;
		this.filterConfig=null;
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		if(ignore || request.getCharacterEncoding()==null)
		{
			if(encoding!=null)
				request.setCharacterEncoding(encoding);
		}
		chain.doFilter(request, response);
	}
 
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		this.filterConfig=filterConfig;//从web.xml中取得参数。
		this.encoding=filterConfig.getInitParameter("encoding");
		String value=filterConfig.getInitParameter("ignore");
		if(value==null)
		{
			ignore=true;
		}
		else if(value.equalsIgnoreCase("true"))
		{
			ignore=true;
		}
		else if(value.equalsIgnoreCase("yes"))
		{
			ignore=true;
		}
		else
		{
			ignore=false;
		}
	}
	
}

非法请求拦截

@WebFilter("/*")
public class Feifa implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //基于Http请求
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //放行登录界面
        //获取请求的路径
        String uri = request.getRequestURI();
        System.out.println(uri);
        //放行指定界面(登陆界面,注册界面)
        if (uri.contains("/login.jsp")) {
            filterChain.doFilter(request, response);
            return;
        }
        //放行静态资源(img、js、css)
        if (uri.contains("/js") || uri.contains("/img") || uri.contains("/css")) {
            filterChain.doFilter(request, response);
            return;
        }
        //指定操作放行(登录操作、注册操作)
        if (uri.contains("/login")) {
            filterChain.doFilter(request, response);
            return;
        }
        //登录状态放行(servlet确认成功后将用户信息存到域中然后在filter判断)
        if (request.getSession().getAttribute("user") != null) {
            filterChain.doFilter(request, response);
        }
        //当用户未登录时拦截请求跳转到登录界面
        response.sendRedirect("login.jsp");
    }
    @Override
    public void destroy() {}
}

监听器

web 监听器是Servlet 中一种的特殊的类,能帮助开发者监听 web 中的特定事件,比如 ServletContext,HttpSession,ServletRequest 的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。例如可以用来统计在线人数等。

监听器有三类八种

1.监听生命周期

ServletRequestListener

HttpSessionListener

ServletContextListener

2.监听值的变化:

ServletRequestAttributeListener
HttpSessionAttributeListener
ServletContextAttributeListener

3.针对Session中的对象

监听Session中的java对象 Javabean直接实现监听器的接口

Listener

@WebListener
public class Listener01 implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("session被创建时执行");
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("session被销毁时执行");
    }
}

监听器的使用

@WebServlet("/s01")
public class ServletT extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("session创建");
        HttpSession session = req.getSession();
    }
}
//
@WebServlet("/s02")
public class ServletX extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("session销毁");
        req.getSession().invalidate();
    }
}

监听在线人数

/*
 * 在线人数统计
 *   当有新的session创建时,人数加1
 *   当有session对象销毁时,人数减1
 * */
@WebListener
public class OnlineListener implements HttpSessionListener {
    private Integer onlineNumber = 0;
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        onlineNumber++;
        //将人数设置到作用域中
        //httpSessionEvent.getSession().setAttribute("onlineNumber",onlineNumber);
        httpSessionEvent.getSession().getServletContext().setAttribute("onlineNumber",onlineNumber);
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        onlineNumber--;
        httpSessionEvent.getSession().getServletContext().setAttribute("onlineNumber",onlineNumber);
    }
}

Servlet

@WebServlet("/online")
public class OnlineServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //获取参数值key
        String key = req.getParameter("key");
        //判断是否为空,如果不为空,则表示退出操作
        if (key != null && "logout".equals(key)) {
            //销毁session对象
            session.invalidate();
            return;
        }
        //得到当前作用域的人数
        Integer number = (Integer) session.getServletContext().getAttribute("onlineNumber");
        //设置响应类型及编码
        resp.setContentType("text/html;charset=UTF-8");
        //输出人数
        resp.getWriter().write("<h2>当前在线人数:" + number + "</h2><a href='online?key=logout'>退出</a>");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遗落-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值