黑马就业班(02.JavaWeb+项目实战\09.JSP EL表达式 JSTL)part2——三层架构、EL/JSTL用户信息列表展示案例

1、三层架构:软件设计架构
  软件设计的三层架构如下(参考视频20解析):注意三层架构与MVC开发模式的关系。

1. 界面层(表示层):用户看到的界面。用户可以通过界面上的组件和服务器进行交互
2. 业务逻辑层:处理业务逻辑的。
3. 数据访问层:操作数据存储文件(数据库、xml、properties等)。
1. M:Model,模型。JavaBean
	* 完成具体的业务操作,如:查询数据库,封装对象
2. V:View,视图。JSP
	* 展示数据。
3. C:Controller,控制器。Servlet(控制器就是一个中转)
	* 获取用户的输入;
	* 调用模型,使用模型封装的业务进行数据的查询与获取;
	* 将模型查询出来的数据交给视图进行展示。

  如下图,我们之前说的MVC的控制器(Servlet)以及视图(JSP)都在界面层。用户通过浏览器访问界面层,然后通过界面层向控制器(Servlet)发送请求,控制器(Servlet)接收用户的请求,并且获取用户提交的参数信息,将参数信息封装,接下来去调用业务逻辑层(service),业务逻辑层再去调用数据访问层(DAO),数据访问层查询数据库并将相应的数据返回给业务逻辑层,业务逻辑层再将数据返回给MVC的控制器(Servlet),控制器(Servlet)将数据发送给视图(JSP),用于展示数据,由这个JSP页面最终给客户端作出响应。
  我们以前写代码的时候没有业务逻辑层,以前MVC模型中的model(JavaBean)就是在数据访问层,我们以前直接通过界面层的控制器(Servlet)直接调用数据访问层的模型中的业务逻辑(比如之前案例中的UserDao中的login()方法,我们直接使用Servlet调用login方法进行登录,login()方法会查询数据库有没有我们输入的参数并验证)。也就是说我们之前是没有编写中间的业务逻辑层的。
  那为什么要定义业务逻辑层,这样反而更加复杂?我们在数据访问层中定义了对数据库最基本的CRUD操作,也就是说这些功能是十分单一的,但是这些单一功能的方法是无法完成一件具体的事情。业务逻辑层中将DAO中的简单方法组合成为复杂的功能(业务逻辑的操作),这样使得数据访问层的方法的复用性大大增强,我们的业务逻辑层要使用到哪一些功能,就将数据访问层中的功能取出来使用即可。我们在业务逻辑层(service)中会编写大量的代码来处理这些复杂的业务操作。而界面层(web)的功能是接收用户参数,封装数据,调用业务逻辑层完成数据的处理,最后将处理的数据转发给JSP页面,并将JSP页面返回给浏览器显示。
  以后放置各部分代码的包起名:界面层(公司域名.项目名.web)、业务逻辑层(公司域名.项目名.service)、数据访问层(公司域名.项目名.dao)。以后项目也会这样分类代码,我们写代码的时候也需要按照规范来写代码。
  我们将来会使用SSM三大框架对三层进行封装和简化,界面层(SpringMVC)、业务逻辑层(Spring)、数据访问层(MyBatis)

黑马就业班(02.JavaWeb+项目实战\09.JSP EL表达式 JSTL)part2——三层架构、EL/JSTL用户信息列表展示案例_第1张图片

案例:用户信息列表展示

(这个案例结合自己文章看——Request案例:用户登录)

  • 1、需求:用户信息的增删改查操作
  • 2、设计
1. 技术选型:tomcat(服务器)+Servlet(控制器)+JSP(视图)+MySQL(数据库)+JDBCTemplate(JDBCTemplate对象简化JDBC的开发)+Duird(数据库连接池)+BeanUtilS(简化JavaBean的数据封装)
2. 数据库设计:
	create database day17; -- 创建数据库
	use day17; 			   -- 使用数据库
	create table user(   -- 创建表
		id int primary key auto_increment,
		name varchar(20) not null,
		gender varchar(5),
		age int,
		address varchar(32),
		qq	varchar(20),
		email varchar(50)
	);
  • 3、开发
1. 环境搭建
	1) 创建数据库环境
	2) 创建项目,导入需要的jar包

2. 编码
  • 4、 测试
  • 5、 部署运维

具体步骤

准备

  资料里面已经提供了各种页面的html文件,包括index.html(查询所有用户信息),提供index.html可以跳转到list.html(展示用户信息),在list.html可以对用户信息进行修改,跳转到update.html,可以添加用户信息,跳转到add.html。另外还有login.html的登录页面。其他文件就是对这些页面进行美化的js、css以及fonts文件。
黑马就业班(02.JavaWeb+项目实战\09.JSP EL表达式 JSTL)part2——三层架构、EL/JSTL用户信息列表展示案例_第2张图片

step1:进行项目设计,这个项目主要是技术选型以及数据库的设计

  确定当前需要的技术:tomcat(服务器)+Servlet(控制器)+JSP(视图,需要使用到EL表达式以及JSTL标签替代java代码)+MySQL(数据库)+JDBCTemplate(JDBCTemplate对象简化JDBC的开发)+Duird(数据库连接池)+BeanUtilS(简化JavaBean的数据封装)
  设计数据库day09case(相关数据库在:MySQL数据目录:datadir=“C:\ProgramData\MySQL\MySQL Server 5.5\data” 下查看),注意,这里只是数据库的设计,并没有真正将数据库放在SQL的环境下运行。代码如下:

CREATE DATABASE day09case; -- 创建数据库day09case
SHOW DATABASES; -- 查看所有的数据库
USE day09case; -- 使用数据库,进入我们创建的数据库
SELECT DATABASE(); -- 确认当前正在使用的数据库

-- 在数据库中创建user表
CREATE TABLE USER(
	id INT PRIMARY KEY AUTO_INCREMENT, -- id设置为主键,自动增长
	NAME VARCHAR(20) NOT NULL, -- 姓名非空,字符类型
	gender VARCHAR(5) NOT NULL, -- 性别非空,字符类型
	age INT ,
	address VARCHAR(32),
	qq VARCHAR(20), -- qq设置为字符类型,否则数字太大可能超过int(32)位的范围,int最大也就是4294967296‬,qq号码很容易比这个大
	email VARCHAR(50) -- email包括各种字符串,我们也使用字符串类型
);

step2:搭建开发环境

  首先,创建数据库环境。打开SQLyog软件,将之前设计的sql语句放到这个软件里面运行。可以在SQLyog里面右键打开表,查看当前表的内容,当前表没有任何数据。我们可以插入一些数据。
黑马就业班(02.JavaWeb+项目实战\09.JSP EL表达式 JSTL)part2——三层架构、EL/JSTL用户信息列表展示案例_第3张图片
  接下来,创建项目day09Case,将虚拟目录改为:/day09case,并将端口改为80,并根据之前的技术选型导入相应的jar包(放到web——WEB-INF——lib下),记得add as library。

数据库驱动jar包: mysql-connector-java-5.1.37-bin.jar
Druid jar包: druid-1.0.9.jar
c3p0(方便我们切换连接池) :c3p0-0.9.1.2.jar
JDBC Template jar包
commons-logging-1.2.jar、spring-beans-5.0.0.RELEASE.jar、spring-core-5.0.0.RELEASE.jar、spring-jdbc-5.0.0.RELEASE.jar、spring-tx-5.0.0.RELEASE.jar
JSTL标签:javax.servlet.jsp.jstl.jar、jstl-impl.jar
BeanUtils:commons-beanutils-1.8.0.jar、commons-logging-1.1.1.jar(这个是BeanUtils的依赖包)

  随后,我们将资料提供的静态页面全部复制到web目录下(静态资源全部放到web目录),将来前端人员会将各类UI、UE效果图(流程跳转图),并将对应的静态页面编写好。我们拿到静态页面后,可以根据自己的需求,改造成为自己需要的文件(比如这里改造为jsp),然后将静态页面里面的假数据换成真实的动态的数据即可(通过Servlet控制器调用业务逻辑层获取数据,并将数据返回视图JSP替换假数据),页面是不需要我们编写的。
  随后我们先不要编写代码,先启动服务器,看看静态页面之间的跳转能不能完成。访问:http://localhost/day09case/index.html,正常跳转,接下来我们就可以进行代码的编写。

step3:编码分析

  案例有5个功能:列表查询展示、修改,删除、添加、登录。今天只做列表查询的功能。
  分析参考视频23。
  首先,在界面层,我们在浏览器访问index.jsp页面,点击“查询所有用户信息”按钮,跳转到list.jsp页面,这个页面展示所有用户的信息。目前静态页面里面的数据是假的,现在我们要将这些数据转变成为真是的数据库里面存储的数据。那么我们就不能跳转直接展示的页面list.jsp,而是跳转到一个Servlet(控制器):UserListServlet.java,通过这个Servlet去查询数据库,返回数据并将这些数据动态地展示回list.jsp。(我们后期会将html页面全部改为jsp)
  这个UserListServlet.java不会从index.jsp接收数据,因此我们不需要设置request的编码。下面的步骤如下:

  1. 我们在UserListServlet.java里面调用service层的findAll()方法,返回List集合List,这个集合里面包含了查询出来的数据库里面的User对象。我们在这里调用service层的findAll方法的时候,会UserService service = new UserServiceImpl();
  2. 我们将获取到的List集合传入request域中,以便于将index.jsp的请求跳转到展示页面list.jsp;
  3. 将request域中的数据转发到list.jsp页面进行展示

  list.jsp接收到UserListServlet后,会使用el+jstl将数据展示到页面上。使用jstl的foreach标签遍历List集合,生成表格table展示数据。

  在service层,我们会创建一个UserService.java接口以及该接口的实现类UserServiceImpl.java。这样设置的好处是,在界面层UserListServlet.java创建实现类的对象,如果我们实现类的功能有缺陷,我们只需要替换实现类就可以,不需要改变接口的功能,提高了程序的可扩展性与可维护性,这是面向接口的编程方式。在接口UserService.java里面有:public List findAll()方法,在实现类UserServiceImpl.java里面也会有:public List findAll()方法,这个方法调用dao.fianAll()完成查询,并将查询出来的数据返回给Servlet(UserListServlet)

  在DAO层,我们也会创建接口UserDao.java以及实现类UserDaoImpl.java。在接口UserDao里面,有:public List findAll()方法,实现类UserDaoImpl.java里面也会有:public List findAll()方法,这个方法使用jdbc操作数据库。

  用户访问index.jsp。跳转到UserListServlet.java,这个类调用UserServiceImpl.java的findAll()查询数据库,返回用户信息的List集合,同时UserServiceImpl.java也会调用UserDaoImpl.java的方法查询数据库。然后UserListServlet.java将list集合插入request域,并转发到list.jsp页面,这个页面遍历list集合并展示数据,这样用户在浏览器上就看到了list.jsp页面展示的数据。

黑马就业班(02.JavaWeb+项目实战\09.JSP EL表达式 JSTL)part2——三层架构、EL/JSTL用户信息列表展示案例_第4张图片

step4:代码编写

  我们先创建各类包:domain(数据库表对应的实现类)、web(界面层)、service(业务逻辑层)、dao(数据访问层)、util(工具类)。
  首先,编写domain下的类User.java,这个类对应数据库的user表。代码如下

package lkj.domain;

public class User
{
     
    private int id;
    private String name;
    private String gender;
    private int age;
    private String address;
    private String qq;
    private String email;

    //空构造器
    public User()
    {
         }
    
    //带参构造器

    public User(int id, String name, String gender, int age, String address, String qq, String email)
    {
     
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.address = address;
        this.qq = qq;
        this.email = email;
    }
    
    //getter与setter方法

    public int getId()
    {
     
        return id;
    }

    public String getName()
    {
     
        return name;
    }

    public String getGender()
    {
     
        return gender;
    }

    public int getAge()
    {
     
        return age;
    }

    public String getAddress()
    {
     
        return address;
    }

    public String getQq()
    {
     
        return qq;
    }

    public String getEmail()
    {
     
        return email;
    }

    public void setId(int id)
    {
     
        this.id = id;
    }

    public void setName(String name)
    {
     
        this.name = name;
    }

    public void setGender(String gender)
    {
     
        this.gender = gender;
    }

    public void setAge(int age)
    {
     
        this.age = age;
    }

    public void setAddress(String address)
    {
     
        this.address = address;
    }

    public void setQq(String qq)
    {
     
        this.qq = qq;
    }

    public void setEmail(String email)
    {
     
        this.email = email;
    }
    
    //toString方法

    @Override
    public String toString()
    {
     
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", qq='" + qq + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

  接下来,我们先编写客户访问的首页:index.jsp。创建一个新的index.jsp,并将前面提供的index.html的内容复制到index.jsp,index.jsp只留下配置的第一行。index.jsp只需要修改超链接跳转的路径即可,我们跳转到UserListServlet.java。index.jsp的代码如下

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

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

    
    <link href="css/bootstrap.min.css" rel="stylesheet">
    
    <script src="js/jquery-2.1.0.min.js">script>
    
    <script src="js/bootstrap.min.js">script>
    <script type="text/javascript">
    script>
  head>
  <body>
    <%--可以看出我们的页面的样式设计使用了BootStrap来设计--%>
    <div align="center">
      <%--
      我们只需要修改超链接的href属性即可,将其跳转到UserListServlet。
      注意这里的请求是浏览器发出的,因此需要加虚拟目录。
      我们的虚拟目录通过EL表达式的隐式对象pageContext(用来获取JSP的内置对象)获取JSP的request对象,
      再通过JSP对象request对应的java类Request,里面有getContextPath方法,request.contextPath的形式的获取虚拟目录。

       EL表达式的pageContext对象,对应JSP的pageContext对象的获取JSP其他8个内置对象的功能,用来获取JSP其他8个内置对象;
      EL表达式的pageScope对象,对应JSP的pageContext对象的共享数据功能,用来在当前的JSP页面进行数据共享。
      既JSP的pageContext对象对应EL表达式内置对象pageScope与pageContext对象,但是对应的功能不一样。
      --%>
      <a
              href="${pageContext.request.contextPath}/userListServlet" style="text-decoration:none;font-size:33px">查询所有用户信息
      a>
    div>
  body>
html>

  然后我们编写UserListServlet类,在web下面new一个Servlet包,下面放UserListServlet类(web包括Servlet与JSP,需要区分)。UserListServlet的代码如下:

package lkj.web.servlet;

import lkj.domain.User;
import lkj.service.impl.UserServiceImpl;

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;

//注意,只有界面层需要创建Servlet,而service层与dao层都只是创建java
@WebServlet("/userListServlet")
public class UserListServlet extends HttpServlet
{
     
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
     
        //首先,我们创建service中的的UserServiceImpl类的对象,并调用其中的findAll()方法,返回一个包含User对象的List集合
        UserServiceImpl service = new UserServiceImpl();//以这种多态的形式创建对象
        List<User> user = service.findAll();//返回一个List集合
        //将获取到的List集合存储到JSP的request对象,便于在request域中进行数据共享
        request.setAttribute("user" , user);
        //将请求转发到list.jsp页面进行展示,请求转发是由服务器发出的,不需要加虚拟目录
        request.getRequestDispatcher("/list.jsp").forward(request , response);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
     
        this.doPost(request, response);
    }
}

  接下来需要编写service包中的UserService接口与UserServiceImpl类,在service下放一个impl的包,下面放UserServiceImpl类。代码如下

//UserServiceImpl
package lkj.service;

import lkj.domain.User;

import java.util.List;

/**
 * 用户管理的业务接口
 */
public interface UserService
{
     
    /**
     * 查询所有用户信息
     * @return
     */
    //创建一个抽象的finaALL()方法,注意加文档注释。注意加返回值为List
    public abstract List<User> findAll();
}
//UserService
package lkj.service.impl;

import lkj.dao.UserDao;
import lkj.dao.impl.UserDaoImpl;
import lkj.domain.User;
import lkj.service.UserService;

import java.util.List;

//这个类实现UserService接口,并重写findAll()方法
public class UserServiceImpl implements UserService
{
     
    //这个方法调用dao中的UserDaoImpl方法的findAll()方法。这个引用只被这个类使用,私有化
    private UserDao dao = new UserDaoImpl();//以这种多态的方式创建对象!!!
    @Override
    public List<User> findAll()
    {
     
        return dao.findAll();//返回dao的findAll()方法返回的List
    }
}

  接下来需要编写dao包中的UserDao接口与UserDaoImpl类,在dao下放一个impl的包,下面放UserDaoImpl类。代码如下

//UserDaoImpl
package lkj.dao;

import lkj.domain.User;

import java.util.List;

/**
 * 用户操作的DAO
 */
public interface UserDao
{
     
    //创建一个抽象的findAll方法,同样返回一个List
    public abstract List<User> findAll();
}
//UserDao
package lkj.dao.impl;

import lkj.dao.UserDao;
import lkj.domain.User;
import lkj.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class UserDaoImpl implements UserDao
{
     
    private JdbcTemplate jt = new JdbcTemplate(JDBCUtils.getDataSource());
    @Override
    public List<User> findAll()
    {
     
        //使用JDBC操作数据库...
        //1.定义sql
        String sql = "select * from user";
        //2、这里我们不需要传入查询参数,直接使用JDBCTemplate的query方法即可.
        //这个方法查询数据库,查询出来的数据每一行构造成为一个User对象并将这些User对象放入List集合
        List<User> user = jt.query(sql, new BeanPropertyRowMapper<User>(User.class));

        //我们这里不需要接收用户提交的参数,既不需要使用到BeanUtils来封装用户提交的JavaBean类User的参数

        return user;//将查询出来的List集合返回
    }
}

  接下来创建Util包中的JDBCUtils工具类,先将Druid连接池的配置文件放到src文件夹下。注意将druid.properties中的数据库与端口修改为我们当前的设定值。druid.properties的代码如下:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day09case
username=root
password=root
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000

  接下来创建JDBCUtils类,这个脸进行数据库的连接配置,并初始化连接池对象。提供连接池对象与数据库连接对象。之前写过,直接将代码放在util包下:

package lkj.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * JDBC工具类 使用Durid连接池
 */
public class JDBCUtils
{
     

    private static DataSource ds ;

    static {
     

        try {
     
            //1.加载配置文件
            Properties pro = new Properties();
            //使用ClassLoader加载配置文件,获取字节输入流
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            pro.load(is);

            //2.初始化连接池对象
            ds = DruidDataSourceFactory.createDataSource(pro);

        } catch (IOException e) {
     
            e.printStackTrace();
        } catch (Exception e) {
     
            e.printStackTrace();
        }
    }

    /**
     * 获取连接池对象
     */
    public static DataSource getDataSource(){
     
        return ds;
    }

    /**
     * 获取连接Connection对象
     */
    public static Connection getConnection() throws SQLException {
     
        return  ds.getConnection();
    }
}

  最后,编写界面层UserListServlet跳转到的list.jsp页面。同样创建一个新的list.jsp,然后将list.html的内容复制到list.jsp上,list.jsp保留第一行配置。代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



<html lang="zh-CN">
    <head>
        
        <meta charset="utf-8">
        
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        
        <meta name="viewport" content="width=device-width, initial-scale=1">
        
        <title>用户信息管理系统title>

        
        <link href="css/bootstrap.min.css" rel="stylesheet">
        
        <script src="js/jquery-2.1.0.min.js">script>
        
        <script src="js/bootstrap.min.js">script>
        <style type="text/css">
            td, th {
      
                text-align: center;
            }
        style>
    head>
    <body>
        <div class="container">
            <h3 style="text-align: center">用户信息列表h3>
            <table border="1" class="table table-bordered table-hover">
                <tr class="success">
                    <th>编号th>
                    <th>姓名th>
                    <th>性别th>
                    <th>年龄th>
                    <th>籍贯th>
                    <th>QQth>
                    <th>邮箱th>
                    <th>操作th>
                tr>

                <%--
                我们将静态页面的虚假信息静态删除,使用JSTL标签遍历request域转发过来的List<User>集合。
                request域存储的user键值对如下:
                request.setAttribute("user" , user);
                --%>
                <c:forEach items="${requestScope.user}" var="user" varStatus="s">
                    <tr>
                        <td>${s.count}td>     <%--用循环次数代表编号--%>
                        <td>${user.name}td>     <%--用逻辑视图的方法,在EL表达式中使用User的getter取出属性的值--%>
                        <td>${user.gender}td>
                        <td>${user.age}td>
                        <td>${user.address}td>
                        <td>${user.qq}td>
                        <td>${user.email}td>
                        <td><a class="btn btn-default btn-sm" href="update.html">修改a> <a class="btn btn-default btn-sm" href="">删除a>td>
                    tr>
                c:forEach>

                <tr>
                    <td colspan="8" align="center"><a class="btn btn-primary" href="add.html">添加联系人a>td>
                tr>
            table>
        div>
    body>
html>

  所有代码写为之后,我们启动服务器,访问:http://localhost/day09case/index.jsp。(我将WEB-INF文件夹写为WEB_INF,导致出错。注意不要犯这种低级错误),页面成功查询数据库展示:
黑马就业班(02.JavaWeb+项目实战\09.JSP EL表达式 JSTL)part2——三层架构、EL/JSTL用户信息列表展示案例_第5张图片

你可能感兴趣的:(Java资料,JSTL,EL,三层架构)