• 7_JSP


    目录

    一. 引言

    1.1 现有问题

    • 在之前学习Servlet时, 服务器通过Servlet响应客户端页面, 有什么不足之处?
      • 开发方式麻烦: 继承父类, 覆盖方法, 配置web.xml或注解
      • 代码修改麻烦: 重新编译, 部署, 重启服务
      • 显示方式麻烦: 获取流, 使用println("")逐行打印
      • 协同开发麻烦: UI负责美化页面, 程序员负责编写代码. UI不懂java, 程序员又不能将所有前端页面的内容通过流输出

    二. JSP (Java Server Pages)

    2.1 概念

    • 简化的Servlet设计, 在HTML标签中嵌套Java代码, 用来高效开发Web应用的动态网页

    2.2 作用

    • 替换显示页面部分的Servlet(使用*.jsp文件替换XxxJSP.java)

    三. JSP开发[重点]

    3.1 创建JSP

    • 在Web目录下新建*.jsp文件 (与WEB-INF平级)
    3.1.1 JSP编写Java代码
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>This is my first page!</title>
    </head>
    <body>
        Now:<%=new java.util.Date() %>
    </body>
    </html>
    
    • 使用<%=%>标签编写Java代码在页面中打印当前系统时间
    3.1.2 访问JSP
    • 在浏览器中输入http://ip:port/项目路径/资源名称

    3.2 JSP与Servlet

    • 关系
      • JSP文件在容器中会转换成Servlet执行
      • JSP是对Servlet的一种高级封装, 本质还是Servlet
    • 区别
      • 与Servlet相比LJSP可以很方便的编写或者修改HTML网页而不用去面对大量的println语句

    Servlet

    1. 编码:
      • 继承HttpServlet + 注解或配置web.xml
    2. 修改:
      • 重新部署, 重启服务器
    3. 访问:
    4. 标签:
      1. printWriter.println("< html>");

    JSP

    1. 编码
      • HTML中直接编写Java代码
    2. 修改:
      • 刷新页面
    3. 访问:
    4. 标签:
      • 直接编写HTML标签

    3.3 JSP实现原理

    • Tomcat会将xxx.jsp转换成Java代码, 进而编译成.class文件运行, 最终将运行结果通过response响应给客户端
    3.3.1 JSP.java源文件存放目录
    • 使用IDEA开发工具, Tomcat编译后的JSP文件(Xxx_jsp.class和Xxx_jsp.java)的存放地点:
      • C:用户名账户名AppDataLocalJetBrainsIntelliJIdea2020.1 omcat项目名称workCatalinalocalhost应用上下文orgapachejsp
      • AppData或许需要查看隐藏的项目
      • 可以在Tomcat启动后在控制台里找到路径

    四. JSP与HTML集成开发

    4.1 脚本

    • 脚本可以编写Java语句, 变量, 方法或表达式
    4.1.1 普通脚本
    • 语法: <% Java代码 &>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>脚本的使用</title>
    </head>
    <body>
        <%
        	//jsp中, 使用小脚本嵌入Java代码
            int a = 10;//普通脚本定义的是局部变量
            System.out.println(a);//打印内容在控制台
            out.println(a);//打印内容在客户端页面
        %>
    </body>
    </html>
    
    • 经验: 普通脚本可以使用所有Java语法, 除了定义函数
    • 注意: 脚本与脚本之间不可嵌套, 脚本与HTML标签不可嵌套
    4.1.2 声明脚本
    • 语法: <%! 定义变量., 函数 %>
    <%!
        int b = 20;//声明脚本定义的是全局变量
    	public void test() {//定义一个无返回值的方法
        System.out.println("你好");
    	}
    	public int test1() {//定义一个有返回值的方法
        return 100;
    	}
    %>
    
    • 注意: 声明脚本声明的变量是全局变量
    • 声明脚本的内容必须在普通脚本<% % >中调用
    • 如果声明脚本中的函数具有返回值, 可以使用输出脚本调用<%= %>
    4.1.3 输出脚本
    • 语法: <%= Java表达式 %>
    <%@ page import="java.util.Date" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>脚本的使用</title>
    </head>
    <body>
        <%=test1()%>
        <%="今天天气很好!"%>
        <%=666%>
        <%=new Date()%>
    </body>
    </html>
    
    • 经验: 输出脚本可以输出带有返回值的函数
    • 注意: 输出脚本中不能加分号;

    4.2 JSP注释

    • JSP注释有两个作用: 为脚本代码作注释以及HTML内容注释
    4.2.1 语法规则
    • <%--- 注释 ---%>
      • JSP注释, 注释内容不会被发送至浏览器甚至不会被编译
    • <%!--- 注释 ---%>
      • HTML注释, 通过浏览器查看网页源代码时可以看见注释内容
    4.2.2 注释
    <%-- JSP注释在网页中不会被显示 --%>
    <%!-- HTML注释在网页源代码中会显示 --%>
    

    4.3 JSP指令

    • JSP指令用来设置与整个JSP页面相关的属性
    • <%@ page ...%>: 定义页面的依赖属性, 比如脚本语言, error页面, 缓存需求等
    • <%@ include ...%>: 包含其他文件
    • <%@ taglib ...%>: 引入标签库的定义, 可以是自定义标签
    4.3.1 page指令
    • 语法: <%@ page attribute1="value1" attribute2="value2"%>
    • page指令为容器提供当前页面的使用说明, 一个JSP页面可以包含多个page指令
    • contentType: 指定当前JSP页面的MIME类型和字符编码格式
    • errorPage: 指定当JSP页面发生异常时需要转向的错误处理页面
    • isErrorPage: 指定当前页面是否可以作为另一个JSP页面的错误处理页面
    • import: 导入要使用的Java类
    • language: 定义JSP页面所用的脚本语言, 默认是Java
    • session: 指定JSP页面是否使用session, 默认为true立即创建, false为使用时创建
    • pageEncoding: 指定JSP页面的解码格式
    4.3.2 include指令
    • 语法: <%@ include file = "被包含的JSP路径"%>
    • 通过include指令来包含其他文件
    • 被包含的文件可以是JSP文件, HTML文件或文本文件. 包含的文件就好像是当前JSP文件的一部分, 会被同时编译执行(静态包含)
    <%@include file="header.jsp"%>
    ...
    ...
    <%@include file="footer.jsp"%>
    
    • 注意: 可能会有重名的冲突问题, 不建议使用
    4.3.3 taglib指令
    • 语法: <%@ taglib url = "外部标签库路径" prefix = "前缀"%>
    • 引入JSP的标准标签库
    <%@ taglib url="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    

    4.4 动作标签

    • 语法: <jsp: action_name attribute="value" />
    • 动作标签指的是JSP页面在运行期间的命令
    4.4.1 include
    • 语法: <jsp: include page = "相对 URL 地址" />
    • <jsp: include >动作元素会将外部文件输出结果包含在JSP中 (动态包含)
    • page: 包含在页面中的相对URL地址
    <jsp:include page="index.jsp"/>
    
    • 注意:前面已经介绍过include指令, 它是将外部文件的输出代码复制到了当前JSP文件中, 而这里的jsp:include动作不同, 是将外部文件的输出结果引入到了当前JSP文件中
    4.4.2 useBean
    • 语法: <jsp: useBean id="name" class="package.className" />
    • jsp:useBean 动作用来加载一个将在JSP页面中使用的JavaBean
    <jsp:useBean id="user" class="com.dz.entity.User" />
    
    • 在类载入后, 我们可以通过jsp:setProperty和jsp:getProperty动作来修改和获取bean的属性
    4.4.3 setProperty
    • 可以在jsp:useBean元素之后使用jsp:setProperty进行属性的赋值
    • name: name属性是必需的. 它表示要设置属性的是哪个Bean
    • property: property属性是必需的. 它表示要设置哪个属性
    • value: value属性是可选的. 该属性用来指定Bean属性的值
    <jsp:useBean id="user" class="com.dz.entity.User" />
    <jsp:setProperty name="user" property="name" value="mars">
    
    4.4.4 getProperty
    • jsp:getProperty动作提取指定Bean属性的值, 转换成字符串, 然后输出
    • name: 要检索的Bean属性名称. Bean必须已定义
    • property: 表示要提取Bean属性的值
    <jsp:useBean id="user" class="com.dz.entity.User" />
    <jsp:setProperty name="user" property="name" value="mars" />
    <jsp:getProperty name="user" property="name" />
    
    4.4.5 forward
    • 语法: <jsp: forward page="相对 URL 地址" />
    • jsp:forward动作把请求转到另外的页面
    • page: page属性包含的是一个相对URL
    <jsp:forward page="index.jsp" />
    
    4.4.6 param
    • 语法: <jsp: param name="" value="" />
    • 在转发动作内部使用. 做参数传递
    <jsp:forward page="index.jsp">
        <!--- http请求参数传递 --->
        <jsp:param name="sex" value="man" />
    </jsp:forward>
    
    • 获取参数的值: <%String result = request.getParameter("sex");%>

    4.5 内置对象

    • 由JSP自动创建的对象, 可以直接使用

      对象名 类型 说明

    • request javax.servlet.http.HttpServletRequest

    • response javax.servlet.http.HttpServletResponse

    • session javax.servlet.http.HttpSession 由session="true"开关

    • **application ** javax.servlet.ServletContext

    • config javax.servlet.ServletConfig

    • exception java.lang.Throwable 由isErrorPage="false"开关

    • out javax.servlet.jsp.JspWriter

    • **pageContext ** javax.servlet.jsp.PageContext

    • page java.lang.Object当前对象this 当前servlet实例

    4.5.1 四大域对象
    • JSP有四大作用域对象, 存储数据和获取数据的方式一样, 不同的是取值的范围有差别
      • pageContext: 当前JSP页面范围
      • request: 一次请求有效
      • session: 一次会话有效(关闭浏览器失效)
      • application: 整个Web应用有效(服务器重启或关闭失效)
    4.5.2 pageContext对象
    • pageContext对象是javax.servlet.jsp.PageContext类的实例, 拥有作用域, 用来代表整个JSP页面
    • 当前页面的作用域对象, 一旦页面跳转则失效
    • 通过setAttribute("name",value);存储值
    • 通过getAttribute("name");获取值
    • 用于获取其他8个内置对象或者操作其他对象的作用域
    <%
    	pageContext.setAttribute("name",value);//当前页面作用域有效
    %>
    
    4.5.3 pageContext获取其他内置对象
    <%
        pageContext.getRequest();//返回request内置对象
        pageContext.getResponse();//返回response内置对象
        pageContext.getSession();//返回session内置对象
        pageContext.getServletContext();//返回application内置对象
        pageContext.getOut();//返回out内置对象
        pageContext.getException();//返回exception内置对象
        pageContext.getPage();//返回page内置对象
        pageContext.getServletConfig();//返回config内置对象
    %>
    
    4.5.4 pageContext操作其他内置对象的作用域
    • pageContext对象可以操作其他作用域存储和获取
        <%
            /*操作其他作用域存储*/
            pageContext.setAttribute("page", "123", PageContext.PAGE_SCOPE);//当前页面作用域
            pageContext.setAttribute("req","aaa", PageContext.REQUEST_SCOPE);//request作用域
            pageContext.setAttribute("session","bbb", PageContext.SESSION_SCOPE);//session作用域
            pageContext.setAttribute("application","ccc", PageContext.APPLICATION_SCOPE);//application作用域
    
            /*操作其他作用域获取*/
            String value =  (String) pageContext.getAttribute("page");//当前页面作用域
            String value1 =  (String) request.getAttribute("req");//request作用域
            String value2 =  (String) session.getAttribute("session");//session作用域
            String value3 =  (String) application.getAttribute("application");//application作用域
    		String value4 = (String) pageContext.findAttribute("req");//从pageContext, request, session, application四个作用域中依次查找
        %>
    

    4.6 整合

    • 将EmpProject项目的所有显示页面JSP的Servlet替换为JSP页面, 使用脚本进行显示
    4.6.1 showAllEmp.jsp
    <%@ page import="com.dz.emp.entity.Emp" %>
    <%@ page import="java.util.List" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>查询所有员工页面</title>
    </head>
    <body>
    
    <form action='/EmpProject/manager/safe/showInsertEmp.jsp'>
    <p><input type='submit' value='新增'></p>
    </form>
    <table border='1'>
        <tr>
            <td>编号</td>
            <td>姓名</td>
            <td>工资</td>
            <td>年龄</td>
            <td colspan='2'>操作</td>
        </tr>
        <%
            List<Emp> empList = (List<Emp>) request.getAttribute("empList");//从request中拿数据
            for (Emp emp : empList) {
        %>
            <tr>
                <td><%=emp.getId()%></td>
                <td><%=emp.getName()%></td>
                <td><%=emp.getSalary()%></td>
                <td><%=emp.getAge()%></td>
                <td><a href="<%=request.getContextPath()+"/manager/safe/removeEmpController?id="+emp.getId()%>">删除</a></td>
                <td><a href="<%=request.getContextPath()+"/manager/safe/showEmpController?id="+emp.getId()%>">修改</a></td>
            </tr>
        <%
            }
        %>
    
    </table>
    
    </body>
    </html>
    
    
    4.6.2 showInsertEmp.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>新增员工信息页面</title>
    </head>
    <body>
    
    <form action='/EmpProject/manager/safe/insertEmpController' method='post'>
        <p>姓名:<input type='text' name='name'></p>
        <p>工资:<input type='text' name='salary'></p>
        <p>年龄:<input type='text' name='age'></p>
        <p><input type='submit' value='提交'></p>
    </form>
    
    </body>
    </html>
    
    
    4.6.3 showUpdateEmp.jsp
    <%@ page import="com.dz.emp.entity.Emp" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>修改员工信息页面</title>
    </head>
    <body>
    
    <%
        Emp emp = (Emp) request.getAttribute("emp");
    %>
    <form action='/EmpProject/manager/safe/updateEmpController' method='post'>
    <p>编号:<input type='text' name='id' value=<%=emp.getId()%> readonly></p>
    <p>姓名:<input type='text' name='name' value=<%=emp.getName()%>></p>
    <p>工资:<input type='text' name='salary' value=<%=emp.getSalary()%>></p>
    <p>年龄:<input type='text' name='age' value=<%=emp.getAge()%>></p>
    <p><input type='submit' value='修改'></p>
    </form>
    </body>
    </html>
    
    

    五. El表达式 (Expression Language)

    5.1 概念

    • EL使JSP写起来更简单, 简洁, 主要用于获取作用域中的数据

    5.2 作用

    • 用于替换作用域对象.getAttribute("name");

    5.3 EL的应用 (获取基本类型, 字符串)

    • ${scope.name} 获取具体某个作用域中的数据
    • ${name} 获取作用域中的数据, 逐级查找(pageContext, request, session, application) 注意: 使用此方法时要确保name在作用域中是唯一的
    5.3.1 EL应用案例
    <body>
        <%
            request.setAttribute("key1","value1");
            session.setAttribute("key2", "value2");
            application.setAttribute("key3", "value3");
        %>
        <%--通过作用域对象获取数据--%>
        <h1><%=request.getAttribute("key1")%></h1>
        <h1><%=session.getAttribute("key2")%></h1>
        <h1><%=application.getAttribute("key3")%></h1>
        <hr/>
        <%--通过EL表达式获取数据--%>
        <h1>${requestScope.key1}</h1>
        <h1>${sessionScope.key2}</h1>
        <h1>${applicationScope.key3}</h1>
        <hr/>
        <h1>${key1}</h1>
        <h1>${key2}</h1>
        <h1>${key3}</h1>
    </body>
    
    5.3.2 EL和JSP脚本的区别
    • <%=request.getAttribute()%>没有找到返回null
    • ${requestScope.name}没有找到返回""

    5.4 EL的应用 (获取引用类型)

    • 使用EL获取作用域中的对象调用属性时, 只能访问对象的get方法, 必须遵守命名规范定义
    <%@ page import="com.dz.entity.User" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>El获取对象</title>
    </head>
    <body>
        <%
            User user = new User("mars","123");
            request.setAttribute("user",user);
        %>
        ${user}<br>
        ${user.username}<br>
        ${user.password}<br>
    </body>
    </html>
    

    5.5 EL的应用 (获取数组, 集合的元素)

    • EL可以获取Array, List, Map 中的元素, Set由于无下标, 无法直接访问元素, 后续可遍历
    	<%
            int[] array = new int[]{1,2,3,4,5};
            request.setAttribute("array",array);
    
            List<String> nums = new ArrayList<>();
            nums.add("A");
            nums.add("B");
            nums.add("C");
            request.setAttribute("nums",nums);
    
            Map<String,String> maps = new HashMap<>();
            maps.put("CN","中国");
            maps.put("US","美国");
            maps.put("UK","英国");
            request.setAttribute("maps",maps);
        %>
        <%--EL访问数据--%>
        ${array[0]}<br>
        ${array[1]}<br>
        ${array[2]}<br>
        <hr>
        ${nums[0]}<br>
        ${nums[1]}<br>
        ${nums.get(2)}<br>
        <hr>
        ${maps["CN"]}<br>
        ${maps["US"]}<br>
        ${maps.UK}<br>
    

    5.6 EL的运算符

    操作符

    • .
      • 访问一个Bean属性或者一个映射条目
    • []
      • 访问一个数组或者链表的元素
    • / or div
    • % or mod
      • 取模
    • == or eq
      • 测试是否相等
    • != or ne
      • 测试是否不等
    • < or lt
      • 测试是否小于
    • (>) or gt
      • 测试是否大于
    • <= or le
      • 测试是否小于等于
    • (>=) or ge
      • 测试是否大于等于
    • && or and
      • 测试逻辑与
    • || or or
      • 测试逻辑或
    • ! or not
      • 测试取反
    • empty
      • 测试是否空值
    5.6.1 EL表达式执行运算
    	<%
            request.setAttribute("nums",100);
            request.setAttribute("n","");
            request.setAttribute("m",null);
        %>
        <h1>算数运算符</h1>
        <h1>${nums + 2}</h1>
        <h1>${nums - 2}</h1>
        <h1>${nums * 2}</h1>
        <h1>${nums div 2}</h1>
        <h1>${nums mod 2}</h1>
        <hr>
        <h1>关系运算符</h1>
        <h1>${nums eq 101}</h1><%-- = --%>
        <h1>${nums ne 101}</h1><%-- != --%>
        <h1>${nums lt 101}</h1><%-- < --%>
        <h1>${nums gt 101}</h1><%-- > --%>
        <h1>${nums le 101}</h1><%-- <= --%>
        <h1>${nums ge 101}</h1><%-- >= --%>
        <hr>
        <h1>逻辑运算符</h1>
        <h1>${nums > 100 and nums < 200}</h1>
        <h1>${nums > 100 or nums < 200}</h1>
        <h1>${not(nums > 100)}</h1>
        <hr>
        <h1>empty运算符</h1>
        <h1>${empty n}</h1>
        <h1>${empty m}</h1>
    
    5.6.2 empty关键字
    	<%
            request.setAttribute("n","");
            request.setAttribute("m",null);
        %>
    	<%--empty关键字 只要内容为空 就返回true--%>
    	<h1>empty运算符</h1>
        <h1>${empty n}</h1>
        <h1>${empty m}</h1>
    

    5.7 隐式对象

    • EL表达式语言定义了11个隐式对象
    1. pageScope
      • page作用域
    2. requestScope
      • request作用域
    3. sessionScope
      • session作用域
    4. applicationScope
      • application作用域
    5. param
      • Request对象的参数, 字符串
    6. paramValues
      • Request对象的参数, 字符串
    7. header
      • HTTP信息头, 字符串
    8. headerValues
      • HTTP信息头, 字符串集合
    9. initParam
      • 上下文初始化参数
    10. cookie
      • Cookie值
    11. pageContext
      • 当前页面的pageContext
    5.7.1 获得应用上下文
    <%=request.getContextPath()%>
    ${pageContext.request.contextPath}
    
    5.7.2 获取Cookie对象
        <h1>${cookie.username}</h1><%--获取名为username的cookie对象--%>
        <h1>${cookie.password}</h1><%--获取名为password的cookie对象--%>
        <h1>${cookie.username.value}</h1><%--获取名为username的cookie对象的value值--%>
        <h1>${cookie.password.value}</h1><%--获取名为password的cookie对象的value值--%>
    

    六. JSTL标准标签库

    6.1 现有问题

    • EL主要是用于作用域获取数据, 虽然可以做运算判断, 但是得到的都是一个结果, 做展示
    • EL不存在流程控制, 比如判断
    • EL对于集合只能做单点访问, 不能实现遍历操作, 比如循环

    6.2 什么是JSTL

    • JSTL: 全称Java Server Pages Standard Tag Library
    • JSP标准标签库(JSTL) 是一个JSP标签集合

    6.3 JSTL的作用

    • 可对EL获取到的数据进行逻辑操作
    • 与EL合作完成数据的展示

    6.4 JSTL使用

    • 导入两个jar文件: standard.jar 和 jstl.jar 文件拷贝到 /WEB-INF/lib/ 下
    • 在JSP页面引入标签库<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

    6.5 核心标签

    6.5.1 条件标签if判断
    • 语法: <c:if test="条件">< /c:if>
    	<%
            request.setAttribute("username","dz");
        %>
        ${username}
    	<%-- test属性中是条件, 但是条件需要使用EL表达式来书写 --%>
        <c:if test="${username eq 'dz'}">
            <h1>欢迎您, ${username}</h1>
        </c:if>
        <c:if test="${username ne 'dz'}">
            <h1>请您重新登陆!</h1>
        </c:if>
    
    6.5.2 多条件choose判断

    语法: < c:choose>

    <c:when test="条件1">结果1< /c:when>

    <c:when test="条件2">结果2< /c:when>

    <c:when test="条件3">结果3< /c:when>

    < c:otherwise>结果4< /c:otherwise>

    < /c:choose>

    	<%
            request.setAttribute("age",18);
        %>    
    	<c:choose>
            <c:when test="${age < 18}"><h1>少年</h1></c:when>
            <c:when test="${age >= 18 and age < 30}"><h1>中年</h1></c:when>
            <c:when test="${age >= 30 and age < 50}"><h1>中年</h1></c:when>
            <c:otherwise><h1>老年</h1></c:otherwise>
        </c:choose>
    
    6.5.3 迭代foreach标签

    语法

    <c:forEach 
    var="变量名" 
    items="集合"
    begin="起始下标"
    end="结束下标"
    step="间隔长度"
    varstatus="遍历状态">    
    </c:forEach>
    
        <%
            List<String> list = new ArrayList<>();
            list.add("A");
            list.add("B");
            list.add("C");
            list.add("D");
            list.add("E");
            request.setAttribute("list",list);
        %>
        <%-- varStatus: 变量状态: 遍历出每一项内容的状态
            first: 是否是第一行
            last: 是否是最后一行
            count: 当前行数
            index: 当前元素的下标
         --%>
        <%-- var: 遍历出的每一项使用变量先存储
            items: 集合(使用EL表达式)
         --%>
        <c:forEach var="v" items="${list}" begin="0" end="4" step="1" varStatus="vs">
            <h1>${v}&nbsp;&nbsp;${vs.first}&nbsp;&nbsp;${vs.last}&nbsp;&nbsp;${vs.count}&nbsp;&nbsp;${vs.index}</h1>
        </c:forEach>
    
    6.5.4 url标签
    • 在Cookie禁用的情况下, 通过重写URL拼接JSESSION来传递ID值, 便于下一次访问时仍可查到上一次的Session对象
        <%--重写URL,拼接jsessionid(旧方法)--%>
        <%
            String newURL = response.encodeRedirectURL(request.getContextPath()+"/jstl/jstl1.jsp");
        %>
        <%=newURL%>
        <a href="<%=response.encodeRedirectURL(request.getContextPath()+"/jstl/jstl1.jsp")%>">跳转</a><br>
    
        <%--重写URL,拼接jsessionid(新方法,使用url标签)--%>
        <c:url context='${pageContext.request.contextPath}' value='/jstl/jstl1.jsp'></c:url>
        <a href="<c:url context='${pageContext.request.contextPath}' value='/jstl/jstl1.jsp'></c:url>">跳转2</a>
    
        <%--在form表单的action中嵌套动态路径--%>
        <form action="<c:url context='${pageContext.request.contextPath}' value='/jstl/jstl1.jsp'></c:url>">
            <input type="submit" value="提交">
        </form>
    
    • 经验: 所有涉及到页面跳转或者重定向跳转时, 都应该使用URL重写

    6.6 整合

    • 将现有的EmpProject项目进行整合, 使用EL+JSTL替换脚本代码
    6.6.1 showAllEmp.jsp
    <%@ page import="com.dz.emp.entity.Emp" %>
    <%@ page import="java.util.List" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>查询所有员工页面</title>
    </head>
    <body>
    
    <form action="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showInsertEmp.jsp'></c:url>">
    <p><input type='submit' value='新增'></p>
    </form>
    <table border='1'>
        <tr>
            <td>编号</td>
            <td>姓名</td>
            <td>工资</td>
            <td>年龄</td>
            <td colspan='2'>操作</td>
        </tr>
    
        <c:forEach var="emp" items="${empList}">
            <tr>
                <td>${emp.id}</td>
                <td>${emp.name}</td>
                <td>${emp.salary}</td>
                <td>${emp.age}</td>
    
                <td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/removeEmpController?id=${emp.id}'></c:url>">删除</a></td>
                <td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showEmpController?id=${emp.id}'></c:url>">修改</a></td>
            </tr>
        </c:forEach>
    
    </table>
    
    </body>
    </html>
    
    
    6.6.2 showUpdateEmpInfo.jsp
    <%@ page import="com.dz.emp.entity.Emp" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>修改员工信息页面</title>
    </head>
    <body>
    
    
    <form action="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/updateEmpController'></c:url>" method='post'>
        <p>编号:<input type='text' name='id' value=${emp.id} readonly></p>
        <p>姓名:<input type='text' name='name' value=${emp.name}></p>
        <p>工资:<input type='text' name='salary' value=${emp.salary}></p>
        <p>年龄:<input type='text' name='age' value=${emp.age}></p>
        <p><input type='submit' value='修改'></p>
    </form>
    
    </body>
    </html>
    
    
    6.6.3 showInsertEmp.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>新增员工信息页面</title>
    </head>
    <body>
    
    <form action='<c:url context="${pageContext.request.contextPath}" value="/manager/safe/insertEmpController"></c:url>' method='post'>
        <p>姓名:<input type='text' name='name'></p>
        <p>工资:<input type='text' name='salary'></p>
        <p>年龄:<input type='text' name='age'></p>
        <p><input type='submit' value='提交'></p>
    </form>
    
    </body>
    </html>
    
    

    七. MVC框架(Model-View-Controller)

    7.1 MVC概念

    • MVC又称为编程模式, 是一种软件设计思想, 将数据操作, 页面展示, 业务逻辑分为三个层级(模块), 独立完成, 相互调用
      • 模型层(Model)
      • 视图(View)
      • 控制器(Controller)

    7.2 MVC模式详解

    • MVC并不是Java独有的, 现在几乎所有的B/S架构都采用MVC模式
      • 视图View层:
        • 视图即是用户看到并与之交互的界面, 比如HTML(静态资源), JSP(动态资源) 等等
      • 控制器Controller层:
        • 控制器即是控制请求的处理逻辑, 对请求进行处理, 负责流程跳转(转发和重定向)
      • 模型Model层(Service+DAO+Entity):
        • 对客观世界的一种代表和模拟(业务模拟, 对象模拟)

    7.3 优点

    • 低耦合性: 模块与模块之间的关联性不强, 不与某一种具体实现产生密不可分的关联性
    • 高维护性: 基于低耦合性, 可做到不同层级的功能模块灵活更换, 插拔
    • 高重用性: 相同的数据库操作, 可以服务于不同的业务处理, 将数据作为独立模块, 提高重用性

    7.4 MVC在框架中应用

    • MVC模式被广泛用于Java的各种框架中, 比如Struct2, SpringMVC等都用到了这种思想

    7.5 三层架构与MVC

    7.5.1 三层架构
    • View层 (表示|界面层)、Service层 (业务逻辑层)、DAO层(数据访问层)

    • 表示层(UI, Main)

      • 职责:
        1. 收集用户输入数据
        2. 调用业务逻辑层, 完成业务方法
        3. 展示数据或展示操作结果
    • 业务逻辑层(service)

      • 职责:
        1. 开启事务
        2. 调用DAO层
        3. 处理数据
        4. 提交或回滚
    • 数据访问层(DAO)

      • 职责:
        1. 查询相关业务逻辑的数据
        2. 根据相关业务逻辑修改的数据
    7.5.2 MVC与三层架构的区别
    • MVC强调的是视图和业务代码的分离, 严格的说MVC其实关注的是Web层, View就是单独的页面, 如JSP, HTML等, 不负责业务处理, 只负责数据的展示. 而数据封装到Model里, 由Controller负责在View和Model之间传递, MVC强调业务和视图分离
    • 三层架构是 数据访问层(DAO), 业务逻辑层(Service), 表示层(View), 指的是代码之间的解耦, 方便维护和复用

    八. 分页

    8.1 概念

    • 分页是Web应用程序非常重要的一个技术. 数据库中的数据可能是成千上万的, 不可能把这么多的数据一次显示在浏览器上面, 一般根据每行数据在页面上所占的空间设置每页显示若干行, 比如一般20行是一个比较理想的显示状态

    8.2 分页实现思路

    • 对于海量的数据查询, 需要多少就取多少, 显然是最佳的解决方案, 假如某个表中有200万条记录, 第一页取前20条, 第二页取21~40条记录
    select * from 表名 limit 0,20;//第一页
    select * from 表名 limit 20,20;//第二页
    select * from 表名 limit 40,20;//第三页
    

    8.3 分页代码实现

    • 步骤
      1. 确定每页显示的数据数量
      2. 确定分页显示所需的总页数
      3. 编写SQL查询语句, 实现数据查询
      4. 在JSP页面中进行分页显示设置
    8.3.1 数据库准备
    CREATE TABLE emp(
    	id INT PRIMARY KEY AUTO_INCREMENT,
    	NAME VARCHAR(20) NOT NULL,
    	salary DOUBLE NOT NULL,
    	age INT NOT NULL
    )CHARSET=utf8;
    #向数据库中添加100条数据
    INSERT INTO emp(NAME,salary,age) VALUES('dz1',1000,18);
    ......(此处省略,请自行插入数据)
    
    8.3.2 数据库配置文件db.properties
    #<!-- 连接设置 -->
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/emp?useUnicode=true&characterEncoding=UTF-8
    username=root
    password=root
    #<!-- 初始化连接 -->
    initialSize=10
    #<!-- 最大连接数量 -->
    maxActive=50
    #<!-- 最小空闲连接 -->
    minIdle=5
    #<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -->
    maxWait=5000
    
    8.3.3 PageBean类
    • 分页数据所需要的实体类! 其包含页码, 页大小, 总条数, 总页数, 起始行
    package com.dz.emp.entity;
    
    public class Page {
        private Integer pageIndex;//页码, 第几页
    
        private Integer pageSize;//页大小, 每页显示多少行数据
    
        private Integer totalCounts;//数据的总行数, 一共有多少条数据
    
        private Integer totalPages;//总页数, 数据一共可以分为多少页
    
        private Integer startRows;//起始行, 用户从第几行开始查数据
    
        //单参构造方法,参数为 页码pageIndex,内部调用两参构造方法,且把 页大小pageSize 的值固定为5
        public Page(Integer pageIndex) {
            this(pageIndex,5);
        }
    
        //两参构造方法,参数为 页码pageIndex, 页大小pageSize,并且设置 起始行startRows 为(pageIndex-1)*pageSize
        public Page(Integer pageIndex, Integer pageSize) {
            this.pageIndex = pageIndex;
            this.pageSize = pageSize;
            this.setStartRows((pageIndex-1)*pageSize);
        }
    
        public Integer getPageIndex() {
            return pageIndex;
        }
    
        public void setPageIndex(Integer pageIndex) {
            this.pageIndex = pageIndex;
        }
    
        public Integer getPageSize() {
            return pageSize;
        }
    
        public void setPageSize(Integer pageSize) {
            this.pageSize = pageSize;
        }
    
        public Integer getTotalCounts() {
            return totalCounts;
        }
    
        //通过数据总行数对页大小取模是否为0, 从而判断总页数为多少
        public void setTotalCounts(Integer totalCounts) {
            this.totalCounts = totalCounts;
    
            this.setTotalPages(totalCounts % pageSize == 0?totalCounts/pageSize:totalCounts/pageSize + 1 );
        }
    
        public Integer getTotalPages() {
            return totalPages;
        }
    
        public void setTotalPages(Integer totalPages) {
            this.totalPages = totalPages;
        }
    
        public Integer getStartRows() {
            return startRows;
        }
    
        public void setStartRows(Integer startRows) {
            this.startRows = startRows;
        }
    }
    
    
    8.3.4 创建EmpDao接口
    package com.dz.emp.dao;
    
    import com.dz.emp.entity.Emp;
    import com.dz.emp.entity.Page;
    
    import java.util.List;
    
    public interface EmpDao {
        int insert(Emp emp);
        int delete(int id);
        int update(Emp emp);
        Emp select(int id);
        List<Emp> selectAll();
        //分页查询所有
        List<Emp> selectAll(Page page);
        //查询数据总行数
        long selectCounts();
    }
    
    
    8.3.5 EmpDaoImpl实现类
    public class EmpDaoImpl implements EmpDao {
        private QueryRunner queryRunner = new QueryRunner();
        //此处省略其他方法
        
        //分页查询所有
        @Override
        public List<Emp> selectAll(Page page) {
            try {
                List<Emp> empList = queryRunner.query(DbUtils.getConnection(), "select * from emp limit ?,?", new BeanListHandler<Emp>(Emp.class), page.getStartRows(),page.getPageSize());//两个参数分别为起始行和页大小
                return empList;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return null;
        }
    	//查询数据总行数
        @Override
        public long selectCounts() {
            try {
                long counts = queryRunner.query(DbUtils.getConnection(), "select count(*) from emp", new ScalarHandler<>());
                return counts;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return 0;
        }
    }
    
    8.3.6 创建EmpService接口
    package com.dz.emp.service;
    
    import com.dz.emp.entity.Emp;
    import com.dz.emp.entity.Page;
    
    import java.util.List;
    
    public interface EmpService {
        int addEmp(Emp emp);
        int removeEmp(int id);
        int modify(Emp emp);
        Emp showEmp(int id);
        List<Emp> showAllEmp();
        List<Emp> showAllEmp(Page page);
    }
    
    
    8.3.7 EmpServiceImpl实现类
        
    public class EmpServiceImpl implements EmpService {
        private EmpDao empDao = new EmpDaoImpl();
        //此处省略其他方法
        
        @Override
        public List<Emp> showAllEmp(Page page) {
            List<Emp> empList = new ArrayList<>();
            try {
                DbUtils.begin();
                long counts = empDao.selectCounts();//查询共有多少条数据
                page.setTotalCounts((int)counts);//将long类型的counts转换为int,并赋值给totalCounts
                List<Emp> temp = empDao.selectAll(page);
                if (temp != null) {
                    empList = temp;
                }
                DbUtils.commit();
            } catch (Exception e) {
                DbUtils.rollback();
                e.printStackTrace();
            }
    
            return empList;
        }
    }
    
    8.3.8 showAllEmpController实现
    package com.dz.emp.controller;
    
    import com.dz.emp.entity.Emp;
    import com.dz.emp.entity.Page;
    import com.dz.emp.service.EmpService;
    import com.dz.emp.service.impl.EmpServiceImpl;
    
    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;
    import java.util.List;
    
    @WebServlet(name = "ShowAllEmpController",value = "/manager/safe/showAllEmpController")
    public class ShowAllEmpController extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String pageIndex = request.getParameter("pageIndex");//获取到页码的值
            if (pageIndex == null) {//用户第一次访问页码为空时
                pageIndex = "1";//为页码赋值为1
            }
            Page page = new Page(Integer.valueOf(pageIndex));//将字符串格式的页码转换为Integer类型
    
            EmpService empService = new EmpServiceImpl();
            List<Emp> empList = empService.showAllEmp(page);
            if (empList != null) {
                request.setAttribute("page",page);
                request.setAttribute("empList",empList);//存到request作用域中,临时存储
                request.getRequestDispatcher("/manager/safe/showAllEmp.jsp").forward(request,response);
            }
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request,response);
        }
    }
    
    
    8.3.9 showAllEmp.jsp
    <%@ page import="com.dz.emp.entity.Emp" %>
    <%@ page import="java.util.List" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>查询所有员工页面</title>
    </head>
    <body>
    
    <form action="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showInsertEmp.jsp'></c:url>">
    <p><input type='submit' value='新增'></p>
    </form>
    <table border='1'>
        <tr>
            <td>编号</td>
            <td>姓名</td>
            <td>工资</td>
            <td>年龄</td>
            <td colspan='2'>操作</td>
        </tr>
    
        <c:forEach var="emp" items="${empList}">
            <tr>
                <td>${emp.id}</td>
                <td>${emp.name}</td>
                <td>${emp.salary}</td>
                <td>${emp.age}</td>
    
                <td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/removeEmpController?id=${emp.id}'></c:url>">删除</a></td>
                <td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showEmpController?id=${emp.id}'></c:url>">修改</a></td>
            </tr>
        </c:forEach>
        <tr>
            <td colspan="6">
                <a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=1'/> ">首页</a>
                <c:if test="${page.pageIndex > 1}">
                    <a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=${page.pageIndex-1}'></c:url> ">上一页</a>
                </c:if>
                <c:if test="${page.pageIndex == 1}">
                    <a>上一页</a>
                </c:if>
                <c:if test="${page.pageIndex < page.totalPages}">
                    <a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=${page.pageIndex+1}'></c:url> ">下一页</a>
                </c:if>
                <c:if test="${page.pageIndex == page.totalPages}">
                    <a>下一页</a>
                </c:if>
                <a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=${page.totalPages}'/> ">尾页</a>
            </td>
        </tr>
    
    </table>
    
    </body>
    </html>
    
    
    8.3.10 运行效果图

  • 相关阅读:
    初识软件工程
    00.JS前言
    01.JS语法规范、变量与常量
    02.JS数据类型与数据类型转换
    03.JS运算符
    04.JS逻辑结构
    05.JS函数
    06.JS对象-1
    08.JS单词整理
    00.ES6简介
  • 原文地址:https://www.cnblogs.com/MRASdoubleZ/p/14669013.html
Copyright © 2020-2023  润新知