一、EL 表达式
1. 什么是 EL 表达式
- EL 表达式的全称是:Expression Language,是表达式语言
- EL 表达式的作用是:主要是代替了 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出
- 使用 EL 表达式进行输出数据,要比 jsp 的表达式脚本简洁很多
- 案例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- jsp 代码脚本 -->
<%
request.setAttribute("name", "1111");
%>
<h3>使用 jsp 表达式脚本输出:<%=request.getAttribute("name")%></h3>
<h3>使用 EL 表达式输出:${name}</h3>
<!-- 如果是取不到数据的情况呢? -->
<h3>使用 jsp 表达式脚本输出:<%=request.getAttribute("age")%></h3>
<h3>使用 EL 表达式输出:${age}</h3>
</body>
</html>
效果:
- EL 表达式的格式是:${表达式}
- EL 表达式在输出 null 值的时候,输出的是空串;jsp 表达式脚本在输出 null 值的时候,输出的是 null 字符串
2. EL表达式搜索四个域的顺序
回顾:域对象是什么意思?
域对象就类似于 Java 中的 Map,也就是说域对象中可以放很多的键值对的数据。但是域对象是有一定的范围的。
servlet 中域对象有几个?
有4个:
pageContext:只在当前页面中有效
request:只在同一个请求中有效
session:只在同一个会话中有效
application:在整个项目都有效
- EL 表达式主要是在 jsp 页面中输出数据,主要是输出域对象中的数据。
- 当四个域中都有相同的 key 的数据的时候,EL 表达式会按照四个域的从小到大的顺序去搜索,找到后就输出。
- 案例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
${key}
</body>
</html>
3. EL 表达式输出对象内容
我们可以通过 EL 表达式去输出对象中属性的内容。
案例:
Student 实体类:
package com.xszx.bean;
public class Student {
private String name;
private Integer age;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
jsp 页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- jsp 脚本 -->
<%
Student student = new Student();
student.setName("张三");
student.setAge(18);
// 往 page 域对象中设置属性值
pageContext.setAttribute("student", student);
%>
<h3>姓名:${student.name}</h3>
<h3>年龄:${student.age}</h3>
</body>
</html>
4. EL 表达式进行关系运算
关系运算符 | 说明 | 范例 | 结果 |
== 或 eq | 等于 | ${5 == 5} 或 ${5 eq 5} | true |
!= 或 ne | 不等于 | ${5 != 5} 或 ${5 ne 5} | false |
< 或 lt | 小于 | ${3 < 5} 或 ${3 lt 5} | true |
> 或 gt | 大于 | ${2 > 10} 或 ${2 gt 10} | false |
<= 或 le | 小于等于 | ${5 <= 12} 或 ${5 le 12} | true |
>= 或 ge | 大于等于 | ${3 >= 5} 或 ${3 ge 5} | false |
5. EL 表达式进行三元运算
格式:${条件表达式 ? 结果1 : 结果2}
案例:
<%
pageContext.setAttribute("status", 1);
%>
${status == 1 ? '上架' : '下架'}
二、JSTL 标签库
1. JSTL 标签库的介绍
- JSTL 标签库的全称是 JSP Standard Tag Library,JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标签库
- EL 表达式主要是为了替换 jsp 中的表达式脚本,而 JSTL 标签库主要是为了替换代码脚本。这样使得整个 jsp页面变的更加简洁
- JSTL 标签库的组成部分
功能 | URI | 前缀 |
核心标签库(重点) | c | |
格式化(了解) | fmt | |
函数(不使用) | fn | |
数据库(不使用) | sql | |
xml(不使用) | x |
2. JSTL 标签库的使用步骤
- 导入 jstl 标签库的两个 jar 包(导入两个 jar 包后记得需要右击,然后 add library...)
- 使用 taglib 指令引入标签库
3. if 标签的使用
- 格式:
<c:if/>
- 作用:if 标签用来做条件判断,类似于 Java 中的 if
- 案例:
<%
int age = 15;
pageContext.setAttribute("age", age);
%>
<c:if test="${age >= 18}">
<h3>成年人</h3>
</c:if>
<c:if test="${age < 18}">
<h3>未成年人</h3>
</c:if>
4. forEach 标签的使用
- 作用:遍历集合、数组,类似于 Java 中的 for 循环
- 案例:遍历 List 集合
<%
List<Student> list = new ArrayList<>();
list.add(new Student("张三", 18));
list.add(new Student("李四", 21));
list.add(new Student("王五", 25));
pageContext.setAttribute("list", list);
%>
<table border="1" cellspacing="0">
<tr>
<th>姓名</th>
<th>年龄</th>
</tr>
<!--
items 属性:表示要遍历的集合
var 属性:表示给每个遍历到的数据起的变量名
-->
<c:forEach items="${list}" var="stu">
<tr>
<td>${stu.name}</td>
<td>${stu.age}</td>
</tr>
</c:forEach>
</table>
三、MVC 概念的介绍
- MVC 全称是:Model 模型、View 视图、Controller 控制器
- MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 web 层的代码如何有效分离,单独工作
- View 视图:只负责数据和界面的展示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作(JSP/HTML)
- Controller 控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色(Servlet,转发到某个页面或者重定向到某个页面)
- Model 模型:将与业务员逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码(JavaBean/domain/entity/pojo)
- MVC 是一种思想,它的理念是将软件代码拆分成为组件,单独开发,组合使用。(目的还是为了降低耦合)
- 具体落地的话,我们一般需要使用到这些包:
-
- bean(pojo、entity):编写实体类的包
- dao(mapper):编写操作数据库相关代码的包
- service:编写业务相关代码的包
- controller:编写接收请求、响应请求相关代码的包
- util:编写工具类代码的包
- test:编写测试类代码的包
- 分层之后,各个层之间是怎样的调用流程?
四、综合案例
1. 需求
实现员工管理的列表展示 + 条件查询功能。
涉及到的表:员工表、部门表。
效果图:
2. 创建数据库及表
3. 创建项目导入相关 jar 包
3. 创建项目导入相关 jar 包
4. 编写数据库工具类
package com.xszx.util;
import java.sql.*;
public class JDBCUtil {
static{
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
String url = "jdbc:mysql:///xszx2?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "root";
Connection connection = null;
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(ResultSet rs, Statement st, Connection connection){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
5. 编写实体类
部门实体类:
package com.xszx.bean;
public class Dept {
private Integer id;
private String dname;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
员工实体类:
package com.xszx.bean;
import java.util.Date;
public class Emp {
private Integer id;
private String name;
private Integer sex;
private Integer age;
private Date birthday;
private String hobby;
private Dept dept;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
6. 实现员工列表展示+条件查询功能
6.1 编写 dao 层代码
dao 层接口
package com.xszx.dao;
import com.xszx.bean.Emp;
import java.util.List;
public interface EmpDao {
List<Emp> findAll(String name);
}
dao 层实现类
package com.xszx.dao.impl;
import com.xszx.bean.Dept;
import com.xszx.bean.Emp;
import com.xszx.dao.EmpDao;
import com.xszx.util.JDBCUtil;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class EmpDaoImpl implements EmpDao {
@Override
public List<Emp> findAll(String name) {
Connection connection = JDBCUtil.getConnection();
String sql = "";
if(name != null && !name.equals("")){
sql = "select e.*, d.dname from emp e, dept d where e.did = d.id and e.name like '%"+name+"%'";
}else{
sql = "select e.*, d.dname from emp e, dept d where e.did = d.id";
}
List<Emp> list = new ArrayList<>();
Statement st = null;
ResultSet rs = null;
try {
st = connection.createStatement();
rs = st.executeQuery(sql);
while(rs.next()){
Emp emp = new Emp();
emp.setId(rs.getInt("id"));
emp.setName(rs.getString("name"));
emp.setSex(rs.getInt("sex"));
emp.setAge(rs.getInt("age"));
emp.setBirthday(rs.getDate("birthday"));
emp.setHobby(rs.getString("hobby"));
Dept dept = new Dept();
dept.setDname(rs.getString("dname"));
emp.setDept(dept);
list.add(emp);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.close(rs, st, connection);
}
return list;
}
}
6.2 编写 service 层代码
service 接口
package com.xszx.service;
import com.xszx.bean.Emp;
import java.util.List;
public interface EmpService {
List<Emp> findAll(String name);
}
service 实现类
package com.xszx.service.impl;
import com.xszx.bean.Emp;
import com.xszx.dao.EmpDao;
import com.xszx.dao.impl.EmpDaoImpl;
import com.xszx.service.EmpService;
import java.util.List;
public class EmpServiceImpl implements EmpService {
private EmpDao empDao = new EmpDaoImpl();
@Override
public List<Emp> findAll(String name) {
return empDao.findAll(name);
}
}
6.3 编写 controller 层代码
package com.xszx.controller;
import com.xszx.bean.Emp;
import com.xszx.service.EmpService;
import com.xszx.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("/empFindAll")
public class EmpFindAllServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
EmpService empService = new EmpServiceImpl();
List<Emp> list = empService.findAll(name);
req.setAttribute("list", list);
req.setAttribute("name", name); // 条件回显使用
req.getRequestDispatcher("list.jsp").forward(req, resp);
}
}
6.4 编写列表展示页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="empFindAll">
姓名:<input type="text" name="name" value="${name}">
<input type="submit" value="查询">
</form>
<table border="1" cellspacing="0">
<tr>
<td>编号</td>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>生日</td>
<td>爱好</td>
<td>部门</td>
</tr>
<c:forEach items="${list}" var="e">
<tr>
<td>${e.id}</td>
<td>${e.name}</td>
<td>${e.sex == 1 ? "男" : "女"}</td>
<td>${e.age}</td>
<td>${e.birthday}</td>
<td>${e.hobby}</td>
<td>${e.dept.dname}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
6.5 效果展示
6.6 问题
问题1:启动报错:
解决:
一般是在配置 servlet 访问路径时,没有以 / 开头。
问题2:条件查询没效果
解决:查看后端是否能够接收到查询条件、是否乱码以及 sql 编写是否正确,如果都没问题,那是数据库版本的原因,需要将数据库 url 地址写为:jdbc:mysql:///xszx2?useUnicode=true&characterEncoding=utf-8
五、作业
A类作业:将今天讲解的综合案例写一遍。
B类作业:在今天讲解的综合案例基础上加上分页功能。