今日内容
零、 复习昨日
一、JSP
二、EL
三、JSTL
四、MVC
零、 复习昨日
一、JSP
1.0 引言
现有问题
在之前学习Servlet时,服务端通过Servlet响应客户端页面,有什么不足之处?
- 开发方式麻烦:继承父类、覆盖方法、配置Web.xml或注解
- 代码修改麻烦:重新编译、部署、重启服务
- 显示方式麻烦:获取流、使用println(“”);逐行打印
- 协同开发麻烦:UI负责美化页面,程序员负责编写代码。UI不懂Java,程序员又不能将所有前端页面的内容通过流输出
1.1 介绍
JSP: Java Server Pages,简单编写页面.
JSP可以简化之前响应时写页面的步骤.
JSP本质是Servlet.
JSP = html + java
1.2 入门示例
需求: 编写index.jsp作为登录页面,登录页输入用户名,发请求登录,将登录信息展现到ok.jsp页面
登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<form action="/login" method="post">
用户名<input type="text" name="username"><br>
<input type="submit" value="登录"><br>
</form>
</body>
</html>
后台Servlet
package com.qf.servlet;
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;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
// 接收请求数据
String username = req.getParameter("username");
System.out.println(username );
// 调用业务层...
// 假设直接登录成功,跳转页面至ok.jsp
req.setAttribute("username",username);
// 因为是请求域,只能使用请求转发,否则另一个servlet接收不到数据
req.getRequestDispatcher("/ok.jsp").forward(req,resp);
}
}
ok.jsp
<%--
+------------------+
天 道 酬 勤
+------------------+
Created by QiuShiju.
Date: 2023/5/26
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>登录成功,欢迎...<%=request.getAttribute("username")%></h1>
</body>
</html>
1.3 原理[重点]
JSP = HTML+Java , JSP是Servlet
JSP实现原理 |
---|
服务器启动,将编写的jsp文件,转译成java文件,再编译成class文件运行
转译后的文件在
C:\Users\用户名\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\684fa9cd-6aa0-42f4-a531-5bd22be4fbf5\work\Catalina\localhost\day43\org\apache\jsp
打开转译后文件,发现原本在jsp写的标签,其实是使用响应对象在拼接字符串
另外, 转译后的jsp文件继承了org.apache.jasper.runtime.HttpJspBase类,该类又继承HttpServlet,那么就说明我们编写JSP本质就是Servlet
1.4 脚本[重点]
jsp内的脚本,可以在标签内写java代码.
有两种
-
<% java代码 %>
<body> <hr> <hr> <h2>java脚本1</h2> <% Object obj = new Object(); System.out.println(obj ); out.write(obj.toString()); %> <hr> <hr> <% out.write(obj.toString()); %> </body>
ps: 注意结合转译 后的index_jsp.java去查看
-
<%=代码 %>,这种方式是一种简化,简化输出用的
<%-- <%= 相当于out,直接将结果输出到浏览器 --%> <%=new Object() %>
应用: 产生10行表格
ID Username Password <table border="2" align="center"> <tr> <td>ID</td> <td>Username</td> <td>password</td> </tr> <% for (int i = 0; i < 10; i++) { %> <tr> <td>ID</td> <td>Username</td> <td>password</td> </tr> <% } %>
1.5 指令
JSP的指令,主要是对当前JSP页面设置属性.
page: 设置当前当前jsp的属性 [重要]
taglib: 用来给当前jsp引入jstl标签库
include: 包含,将其他内容包含至当前页面 [了解]
指令语法
<%@指令名 属性名=属性值 %>
1.5.1 page
语法: <%@page 属性=“值” 属性=“值” %>
属性:
属性 | 描述 |
---|---|
contentType | 指定当前JSP页面的MIME类型和字符编码格式 |
errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 |
isErrorPage | 指定当前页面是否可以作为另一个JSP页面的错误处理页面 |
import | 导入要使用的Java类 |
language | 定义JSP页面所用的脚本语言,默认是Java |
session | 指定JSP页面是否使用session。默认为true立即创建,false为使用时创建 |
pageEncoding | 指定JSP页面的解码格式 |
- errorPage : 当前jsp中如果有异常,跳转至该页面
- import: 在当前jsp导入其他java包
- session: true|false,默认是true,设置当前页面是否可以直接使用session对象
false,就是没有session对象,使用时编译报错
1.5.2 taglib
语法: <%@ taglib uri=“” prefix=“” %>
用法: 引入jstl标签库
1.5.3 include
语法: <%@ include file=“路径”>
作用: 将file指定路径的文件加入到当前页面,已达到复用的效果
场景:页面的头尾重复部分的内容.
1.6 内置对象
内置对象,就是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 | javax.servlet.jsp.JspWriter |
pageContext | javax.servlet.jsp.PageContext | |
page | java.lang.Object当前对象this | 当前servlet实例 |
这九个对象可以在转译后的xxx_jsp.java中找到这些对象
通过pageContext获得其他八个对象
1.7 四大域(scope)[熟悉]
内置对象中有四个可以当做域对象,存取数据,分别是
域 | 解释 | 值的范围 |
---|---|---|
pageContext | 页面域 | 只有当前页面能使用 |
request | 请求域 | 在一次请求转发中有效 |
session | 会话域 | 在一次会话中有效 |
application | 应用域 | 在整个web应用中有效 |
四大域都有相同的取值赋值方法:
- 域对象.setAttribute("key",value);
- 域对象.getAttribute("key");
pageContext
二、 EL表达式
2.1 概念
EL表达式,主要用于简化取值操作.
2.2 作用
纯jsp取值: <%=request.getAttribute(“username”) %>
现在EL取值,${username}
作用: 简化取值操作
语法: ${域key}
2.3 取域中的值[重点]
四大域中的值都可以取
${key},如果四大域中key值一样,按照page–>request–>session–>application的顺序依次取值,取到值即停止.
如果四大域中key值一样,也可以指定取出某个域中的值
${域对象.key} --> ${sessionScope.el}
-----------------------------------
<h2>存入四大域值,key=el</h2>
<%
application.setAttribute("el","appValue");
pageContext.setAttribute("el","pageValue");
request.setAttribute("el","reqValue");
session.setAttribute("el","seValue");
%>
<h3>el取值结果:${el}</h3>
<h3>指定取某个域的值: ${sessionScope.el}</h3>
2.4 取值[重点]
(字符串,基本类型,对象,数组,集合)
<%@ page import="com.qf.model.User" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %><%--
+------------------+
天 道 酬 勤
+------------------+
Created by QiuShiju.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>取值</title>
</head>
<body>
<%
//先向域中存值
request.setAttribute("str","字符串");
request.setAttribute("num",100);
User user = new User( );
user.setUsername("牛彩云");
user.setPassword("123456");
request.setAttribute("user",user);
int[] array = {11,22,33};
request.setAttribute("array",array);
Map map = new HashMap();
map.put("aka","阿浩");
map.put("ak47","阿卡司机");
request.setAttribute("map",map);
%>
<h2>取字符串:${str}</h2>
<h2>取数字:${num}</h2>
<h2>取对象:${user}</h2>
<!-- 对象取值是重点 -->
<h2>取对象的属性:${user.username}</h2>
<h2>取出数组:${array[0]}</h2>
<h2>取出map:${map.get('aka')}</h2>
map取值${map['一']}<br>
map取值${map['二']}<br>
map取值${map['仨']}<br>
</body>
</html>
2.5 运算符
一样可以在el表达式是内部做运算: 算术,关系,逻辑,三目运算
<%--
+------------------+
天 道 酬 勤
+------------------+
Created by QiuShiju.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>运算</title>
</head>
<body>
<%
request.setAttribute("num",10);
request.setAttribute("num2",null);
request.setAttribute("sex",2);
%>
${num + 1}
${num - 1}
${num * 2}
${num / 2}
${num == 2}
${num != 2}
${num > 2}
${num < 2}
${num > 2 && num > 3}
${num < 2 || num > 3}
${empty num2}
${empty num}
${num > 2 ? '200':0}
<input type="radio" value="1" name="sex" ${sex == 1?'checked':''} >男
<input type="radio" value="2" name="sex" ${sex == 2?'checked':''}>女
</body>
</html>
2.6 隐式对象
EL表达式内部,可以直接使用的对象.
隐式对象 | 解释 |
---|---|
pageContext | page域 |
pageScope | page域 |
requestScope | 请求域 |
sessionScope | 会话域 |
applicationScope | 应用域 |
cookie | 获得cookie |
常用的有一个:
${pageContext.request.contextPath}了获得项目名
<a href="${pageContext.request.contextPath}/login">登录3</a><br>
三、JSTL
3.1 现有问题
- EL主要是用于作用域获取数据,虽然可以做运算判断,但是得到的都是一个结果,做展示。
- EL不存在流程控制。比如判断。
- EL对于集合只能做单点访问,不能实现遍历操作。比如循环。
3.2 什么是 JSTL?
JSTL:全称Java Server Pages Standard Tag Library JSP标准标签库(JSTL)是一个JSP标签集合。
3.3 JSTL的作用
可对EL获取到的数据进行逻辑操作。 与EL合作完成数据的展示。
3.4 JSTL的使用步骤
项目加入jstl和standard的jar包,或者引入pom依赖
<!-- jstl --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> <exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion> <exclusion> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jstl-impl</artifactId> <version>1.2</version> <exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion> <exclusion> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> </exclusion> <exclusion> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> </exclusion> </exclusions> </dependency>
在需要使用jstl标签的页面,中使用taglib引入库
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
在需要的地方写标签 <c:if >
3.5 核心标签的使用[重点]
3.5.1 判断标签
<body>
<%
request.setAttribute("num",0);
%>
<%
int num = (int)request.getAttribute("num");
if (num > 0) {
out.write("num > 0");
} else {
out.write("num < 0");
}
%>
<hr>
<c:if test="${num > 0}">
num > 0
</c:if>
<hr>
<c:choose>
<c:when test="${num > 0}">
num > 0
</c:when>
<c:when test="${num < 0}">
num < 0
</c:when>
<c:otherwise>
num = 0
</c:otherwise>
</c:choose>
</body>
3.5.2 循环标签[重点]
<%--
循环 var是变量
begin从哪里开始
end 到哪结束
step 步长默认为1
--%>
<c:forEach var="i" begin="1" end="10" step="2">
${i}<br>
</c:forEach>
<hr>
<%--
循环
items 就是域中的集合
var 每次循环得到的对象
--%>
<c:forEach var="user" items="${list}">
<div>${user}</div>
</c:forEach>
四、MVC框架(Model-View-Controller)
4.1 MVC概念
MVC又称为编程模式,是一种软件设计思想,将数据操作、页面展示、业务逻辑分为三个层级(模块),独立完成,相互调用
模型层(Model)
视图(View)
控制器(Controller)
4.2 MVC模式详解
MVC并不是Java独有的,现在几乎所有的B/S的架构都采用了MVC模式。
- 视图View:视图即是用户看到并与之交互的界面,比如HTML(静态资源),JSP(动态资源)等等。
- 控制器Controller:控制器即是控制请求的处理逻辑,对请求进行处理,负责流程跳转(转发和重定向)。
- 模型Model:对客观世界的一种代表和模拟(业务模拟、对象模拟)。
MVC流程 |
---|
4.3 优点
- 低耦合性:模块与模块之间的关联性不强,不与某一种具体实现产生密不可分的关联性
- 高维护性:基于低耦合性,可做到不同层级的功能模块灵活更换、插拔
- 高重用性:相同的数据库操作,可以服务于不同的业务处理。将数据作为独立模块,提高重用性
4.4 MVC在框架中应用
MVC模式被广泛用于Java的各种框架中,比如Struts2、SpringMVC等等都用到了这种思想。
4.5 三层架构与MVC
4.5.1 三层架构
View层(表示|界面层)、Service层(业务逻辑层)、DAO层(数据访问层)
三层架构流程 |
---|
4.5.2 MVC与三层架构的区别
- MVC强调的是视图和业务代码的分离。严格的说MVC其实关注的是Web层。View就是单独的页面,如JSP、HTML等,不负责业务处理,只负责数据的展示。而数据封装到Model里,由Controller负责在V和M之间传递。MVC强调业务和视图分离。
- 三层架构是“数据访问层”、“业务逻辑层”、“表示层”,指的是代码之间的解耦,方便维护和复用。
据作为独立模块,提高重用性
4.4 MVC在框架中应用
MVC模式被广泛用于Java的各种框架中,比如Struts2、SpringMVC等等都用到了这种思想。
4.5 三层架构与MVC
4.5.1 三层架构
View层(表示|界面层)、Service层(业务逻辑层)、DAO层(数据访问层)
三层架构流程 |
---|
4.5.2 MVC与三层架构的区别
- MVC强调的是视图和业务代码的分离。严格的说MVC其实关注的是Web层。View就是单独的页面,如JSP、HTML等,不负责业务处理,只负责数据的展示。而数据封装到Model里,由Controller负责在V和M之间传递。MVC强调业务和视图分离。
- 三层架构是“数据访问层”、“业务逻辑层”、“表示层”,指的是代码之间的解耦,方便维护和复用。