zoukankan      html  css  js  c++  java
  • JavaWeb(五):MVC案例

    MVC是Model-View-Controller的简称,即模型-视图-控制器。
    MVC是一种设计模式,它把应用程序分成三个核心模块:模型、视图、控制器,它们各自处理自己的任务。模型是应用程序的主体部分,模型表示业务数据和业务逻辑。一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以提高了代码的可重用性。视图是用户看到并与之交互的界面,作用如下:视图向用户显示相关的数据,接受用户的输入,不进行任何实际的业务处理。控制器接受用户的输入并调用模型和视图去完成用户的需求。控制器接收请求并决定调用哪个模型组件去处理请求,然后决定调用哪个视图来显示模型处理返回的数据。

    把逻辑部分、访问数据库的部分放在Servlet,显示部分放在JSP页面。
    发请求到服务器,服务器调用Servlet,Servlet做一个控制器,根据请求的情况取去调用Java类,Java类完成业务逻辑和访问数据库的操作,根据POJO的返回结果转向JSP,JSP进行显示,显示的时候可以使用一些标准标签库。
    POJO里包含处理逻辑、业务逻辑,并去访问数据库。
    Servlet根据不同的返回结果转向不同的JSP页面,转向的方式包括重定向和转发。

    model:

    controller:Servlet

    view:JSP

    一、查询和删除

    1.1 查询

    需求

    点击超链接后在页面显示所有学生考试信息

    数据库

    字段

    • flowId
    • type
    • idCard
    • examCard
    • studentName
    • location
    • grade

    数据表截图

    Bean

    public class Student {
    
        private Integer flowId;
        private int type;
        private String idCard;
        private String examCard;
        private String studentName;
        private String location;
        private int grade;
    
    
        public Integer getFlowId() {
            return flowId;
        }
    
        public void setFlowId(Integer flowId) {
            this.flowId = flowId;
        }
    
        public int getType() {
            return type;
        }
    
        public void setType(int type) {
            this.type = type;
        }
    
        public String getIdCard() {
            return idCard;
        }
    
        public void setIdCard(String idCard) {
            this.idCard = idCard;
        }
    
        public String getExamCard() {
            return examCard;
        }
    
        public void setExamCard(String examCard) {
            this.examCard = examCard;
        }
    
        public String getStudentName() {
            return studentName;
        }
    
        public void setStudentName(String studentName) {
            this.studentName = studentName;
        }
    
        public String getLocation() {
            return location;
        }
    
        public void setLocation(String location) {
            this.location = location;
        }
    
        public int getGrade() {
            return grade;
        }
    
        public void setGrade(int grade) {
            this.grade = grade;
        }
    
        public Student(Integer flowId, int type, String idCard, String examCard, String studentName, String location, int grade) {
            this.flowId = flowId;
            this.type = type;
            this.idCard = idCard;
            this.examCard = examCard;
            this.studentName = studentName;
            this.location = location;
            this.grade = grade;
        }
    
        // 反射需要一个无参的构造器
        public Student(){
    
        }
    }

    流程

    页面

    超链接的页面 c.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="listAllStudent">List All Student</a>
    </body>
    </html>

    c.jsp截图

    转发的页面 students.jsp

    <%@ page import="java.util.List" %>
    <%@ page import="com.satguigu.mvc.Student" %><%--
      Created by IntelliJ IDEA.
      User: JieZhao
      Date: 2019/8/13
      Time: 13:38
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
    <%= request.getAttribute("students") %>
    <br>
    <%
        List<Student> stus = (List<Student>)request.getAttribute("students");
    %>
    
    
    <table>
        <tr>
            <th>FlowId</th>
            <th>Type</th>
            <th>IdCard</th>
            <th>ExamCard</th>
            <th>StudentName</th>
            <th>Location</th>
            <th>Grade</th>
        </tr>
        <%
        for (Student student: stus){
        %>
            <tr>
                <td><%= student.getFlowId() %>  </td>
                <td><%= student.getType() %>  </td>
                <td><%= student.getIdCard() %>  </td>
                <td><%= student.getExamCard() %>  </td>
                <td><%= student.getStudentName() %>  </td>
                <td><%= student.getLocation() %>  </td>
                <td><%= student.getGrade() %>  </td>
            </tr>
    
       <% }%>
    
    
    </table>
    
    </body>
    </html>

    代码

    Dao

    public class StudentDao {
    
        public List<Student> getAll(){
            List<Student> students = new ArrayList<>();
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            try{
                String driverClass = "com.mysql.jdbc.Driver";
                String url = "jdbc:mysql:///aidata";
                String user = "root";
                String passward = "root";
                Class.forName(driverClass);
                connection = DriverManager.getConnection(url, user, passward);
                String sql = "SELECT flow_id, type, id_card, exam_card, sutdent_name, Location, Grade FROM examstudent";
                preparedStatement = connection.prepareStatement(sql);
                resultSet = preparedStatement.executeQuery();
                while (resultSet.next()){
                    int flowId = resultSet.getInt(1);
                    int type = resultSet.getInt(2);
                    String idCard = resultSet.getString(3);
                    String examCard = resultSet.getString(4);
                    String studentName = resultSet.getString(5);
                    String location = resultSet.getString(6);
                    int grade = resultSet.getInt(7);
                    Student student = new Student(flowId, type, idCard, examCard, studentName, location, grade);
                    students.add(student);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try{
                    if(resultSet != null){
                    resultSet.close();
                    }
                }catch (SQLException e){
                    e.printStackTrace();
                }
                try{
                    if(preparedStatement != null){
                        preparedStatement.close();
                    }
                }catch (SQLException e){
                    e.printStackTrace();
                }
                try{
                    if(connection != null){
                        connection.close();
                    }
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }
            return students;
        }
    }

    Servlet

    public class ListAllStudentsServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,  ServletException {
    
            StudentDao studentDao = new StudentDao();
            List<Student> students = studentDao.getAll();
    
            request.setAttribute("students", students); //结果添加到students属性里,存到request里
            request.getRequestDispatcher("/students.jsp").forward(request, response);
           // 将request转发到students.jsp页面
         }
    }

    配置web.xml

    <servlet>
        <servlet-name>listAllStudent</servlet-name>
        <servlet-class>com.aidata.mvc.ListAllStudentsServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>listAllStudent</servlet-name>
        <url-pattern>/listAllStudent</url-pattern>
    </servlet-mapping>

    1.2 删除

    students.jsp里添加删除按钮 

    Dao里添加删除方法

    public void deleteByFlowId(Integer flowId){
            List<Student> students = new ArrayList<>();
            Connection connection = null;
            PreparedStatement preparedStatement = null;
    
            try {
                String driverClass = "com.mysql.jdbc.Driver";
                String url = "jdbc:mysql:///aidata";
                String user = "root";
                String password = "root";
                Class.forName(driverClass);
                connection = DriverManager.getConnection(url, user, password);
                String sql = "DELETE FROM examstudent WHERE flow_id = ?";
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setInt(1, flowId);
                preparedStatement.executeUpdate();
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
    
                try{
                    if(preparedStatement != null){
                        preparedStatement.close();
                    }
                }catch (SQLException e){
                    e.printStackTrace();
                }
                try{
                    if(connection != null){
                        connection.close();
                    }
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }
    
        }

    Servlet添加删除的Servlet

    public class DeleteStudentServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws IOException, ServletException {
    
            String flowId = request.getParameter("flowId");
            StudentDao studentDao = new StudentDao();
            studentDao.deleteByFlowId(Integer.parseInt(flowId));
            List<Student> students = studentDao.getAll();
            request.setAttribute("students", students);
            request.getRequestDispatcher("/listAllStudent").forward(request, response); // 重定向到servlet
    
        }
    }

    配置web.xml

    <servlet>
        <servlet-name>deleteStudent</servlet-name>
        <servlet-class>com.aidata.mvc.DeleteStudentServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>deleteStudent</servlet-name>
        <url-pattern>/deleteStudent</url-pattern>
    </servlet-mapping>

    二、案例

    2.1 架构分析

    下面开始做一个小案例:利用MVC模式对数据进行增删改查

    没有业务层,直接由Servlet调用DAO,所以也没有事务操作,可以在DAO中直接获取Connection对象

    采取MVC设计模式

    使用到的技术:

    • MVC设计模式:JSP、Servlet
    • 数据库使用MySQL
    • 连接数据库使用C3P0数据库连接池
    • JDBC工具采用DBUtils
    • 页面的提示操作采用jQuery

    技术难点:

    • 多个请求如何使用一个Servlet
    • 模糊查询
    • 在创建或修改的情况下,验证用户名已经被使用,并给出提示信息

    2.2 DAO层

    DAO 模式

    DAO (DataAccessobjects 数据存取对象)是指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作都封装起来。

    对外提供相应的接口

    在面向对象设计过程中,有一些"套路”用于解决特定问题称为模式。

    DAO 模式提供了访问关系型数据库系统所需操作的接口,将数据访问和业务逻辑分离对上层提供面向对象的数据访问接口。

    从以上 DAO 模式使用可以看出,DAO 模式的优势就在于它实现了两次隔离。

    • 1、隔离了数据访问代码和业务逻辑代码。业务逻辑代码直接调用DAO方法即可,完全感觉不到数据库表的存在。分工明确,数据访问层代码变化不影响业务逻辑代码,这符合单一职能原则,降低了藕合性,提高了可复用性。
    • 2、隔离了不同数据库实现。采用面向接口编程,如果底层数据库变化,如由 MySQL 变成 Oracle 只要增加 DAO 接口的新实现类即可,原有 MySQ 实现不用修改。这符合 "开-闭" 原则。该原则降低了代码的藕合性,提高了代码扩展性和系统的可移植性。

    一个典型的DAO 模式主要由以下几部分组成。

    • 1、DAO接口: 把对数据库的所有操作定义成抽象方法,可以提供多种实现。
    • 2、DAO 实现类: 针对不同数据库给出DAO接口定义方法的具体实现。
    • 3、实体类:用于存放与传输对象数据。
    • 4、数据库连接和关闭工具类: 避免了数据库连接和关闭代码的重复使用,方便修改。

    数据库

     建立数据表

    Create table customers(
        id int primary key auto_increment,
        name varchar(30) not null unique,
        address varchar(30),
        phone varchar(30)
    );
    # 为 name 字段添加唯一约束
    alter table customers add constraint name_uk unique(name);

    数据表截图

    C3P0数据源

    论数据库连接池的必要性及c3p0的详解

    使用eclipse

    添加c3p0的jar包和mysql驱动的jar包到根目录的lib目录中

    添加commons-dbutils-1.3.jar到根目录的lib目录中

    添加c3p0的配置文件到src目录

    c3p0-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    
        <named-config name="mvcapp">
            
            <!-- 指定连接数据源的基本属性 -->
            <property name="user">root</property>
            <property name="password">root</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql:///aidata</property>
            
            <!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
            <property name="acquireIncrement">5</property>
            <!-- 初始化数据库连接池时连接的数量 -->
            <property name="initialPoolSize">5</property>
            <!-- 数据库连接池中的最小的数据库连接数 -->
            <property name="minPoolSize">5</property>
            <!-- 数据库连接池中的最大的数据库连接数 -->
            <property name="maxPoolSize">10</property>
    
            <!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
            <property name="maxStatements">20</property>
            <!-- 每个连接同时可以使用的 Statement 对象的个数 -->
            <property name="maxStatementsPerConnection">5</property>
        
        </named-config>
            
    </c3p0-config>

    实体类

    Customer.java

    package com.aidata.mvcapp.domain;
    
    public class Customer {
    
        private Integer id;
        private String name;
        private String address;
        private String phone;
    
        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 String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    
        @Override
        public String toString() {
            return "Customer [id=" + id + ", name=" + name + ", address=" + address + ", phone=" + phone + "]";
        }
    
    }

    数据库连接和关闭工具类

    JdbcUtils.java

    package com.aidata.mvcapp.db;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    /**
     * @ClassName JdbcUtils
     * @Description JDBC操作的工具类
     * @author JZ
     * @Date
     * @version 1.0.0
     */
    public class JdbcUtils {
    
        /**
         * @Description 释放连接
         * @param connection
         */
        public static void releaseConnection(Connection connection) {
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    
        private static DataSource dataSource = null;
    
        // 数据源只能创建一次,所以用static
        static {
            dataSource = new ComboPooledDataSource("mvcapp");
        }
    
        /**
         * @Description 返回数据源的一个Connection对象
         * @return
         * @throws SQLException
         */
        public static Connection getConnection() throws SQLException {
            return dataSource.getConnection();
        }
    }

    DAO接口

    CustomerDAO.java

    该接口定义了和业务相关的功能,操作customer

    package com.aidata.mvcapp.dao;
    
    import java.util.List;
    
    import com.aidata.mvcapp.domain.Customer;
    
    public interface CustomerDAO {
        
        public List<Customer> getAll();
        
        public void save(Customer customer);
        
        public Customer get(Integer id);
        
        public void delete(Integer id);
        
        /**
         * 
         * @Description 返回和name相等的记录数
         * @param name
         * @return
         */
        public long getCountWithName(String name);
    
    }

    DAO 实现类

    DAO.java

    该类不和业务相关,即和customer不相关,而是关注增删改查的功能

    增删改都是update,查

    package com.aidata.mvcapp.dao;
    
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.sql.Connection;
    import java.util.List;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.apache.commons.dbutils.handlers.ScalarHandler;
    
    import com.aidata.mvcapp.db.JdbcUtils;
    
    /**
     * @ClassName DAO
     * @Description 封装了CRUD的方法,以供子类继承使用 当前DAO没有事务,直接在方法中获取数据库连接 整个DAO采取DBUtils解决方案
     * @author JZ
     * @Date
     * @version 1.0.0
     * @param <T>
     *            所处理的实体类的类型
     */
    public class DAO<T> {
    
        private QueryRunner queryRunner = new QueryRunner();
    
        private Class<T> clazz;
    
        public DAO() {
            Type superClass = getClass().getGenericSuperclass();
            if (superClass instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) superClass;
                Type[] typeArgs = parameterizedType.getActualTypeArguments();
                if (typeArgs != null && typeArgs.length > 0) {
                    clazz = (Class<T>) typeArgs[0];
                }
            }
        }
    
        /**
         * @Description 返回某一个字段的值,例如某一天记录的customerName或 返回数据表中由多少条记录等
         * @param sql
         * @param args
         * @return
         */
        public <E> E getForValue(String sql, Object... args) {
            Connection connection = null;
            try {
                connection = JdbcUtils.getConnection();
                return (E) queryRunner.query(connection, sql, new ScalarHandler(), args);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JdbcUtils.releaseConnection(connection);
            }
            return null;
        }
    
        /**
         * @Description 返回 T 所对应的List
         * @param sql
         * @param args
         * @return
         */
        public List<T> getForList(String sql, Object... args) {
            Connection connection = null;
            try {
                connection = JdbcUtils.getConnection();
                return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), args);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JdbcUtils.releaseConnection(connection);
            }
            return null;
        }
    
        /**
         * @Description 返回对应T的一个实例类对象
         * @param sql
         * @param args
         * @return
         */
        public T get(String sql, Object... args) {
            Connection connection = null;
            try {
                connection = JdbcUtils.getConnection();
                return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JdbcUtils.releaseConnection(connection);
            }
            return null;
        }
    
        /**
         * @Description 封装了INSERT、DELETE、UPDATE操作
         * @param sql
         *            SQL语句
         * @param args
         *            填充SQL语句的占位符
         */
        public void update(String sql, Object... args) {
            Connection connection = null;
            try {
                connection = JdbcUtils.getConnection();
                queryRunner.update(connection, sql, args);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JdbcUtils.releaseConnection(connection);
            }
        }
    
    }

    CustomerDAOJdbcImpl.java

    将业务和功能结合起来,实现了业务操作

    package com.aidata.mvcapp.dao.impl;
    
    import java.util.List;
    
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.DAO;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerDAOJdbcImpl extends DAO<Customer> implements CustomerDAO {
    
        @Override
        public List<Customer> getAll() {
            String sql = "SELECT id, name, address, phone From customers";
            return getForList(sql);
        }
    
        @Override
        public void save(Customer customer) {
            String sql = "INSERT INTO customers(name, address, phone) VALUES(?,?,?)";
            update(sql, customer.getName(), customer.getAddress(), customer.getPhone());
        }
    
        @Override
        public Customer get(Integer id) {
            String sql = "SELECT id, name, address, phone FROM customers WHERE id = ?";
            return get(sql, id);
        }
    
        @Override
        public void delete(Integer id) {
            String sql = "DELETE FROM customers WHERE id = ?";
            update(sql, id);
        }
    
        @Override
        public long getCountWithName(String name) {
            String sql = "SELECT count(id) FROM customers WHERE name = ?";
            return getForValue(sql, name);
        }
    
    }

    2.3 多个请求对应一个Servlet

    第一种方式:url添加参数

    jsp

    <body>
    
        <a href="customerServlet?method=add">Add</a>
        <br><br>
        
        <a href="customerServlet?method=query">Query</a>
        <br><br>
        
        <a href="customerServlet?method=delete">Delete</a>
        <br><br>
        
    </body>

    定义Servlet

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String method = request.getParameter("method");
    
            switch (method) {
            case "add":
                add(request, response);
                break;
            case "query":
                query(request, response);
                break;
            case "delete":
                delete(request, response);
                break;
            }
        }
    
        private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("add");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("query");
        }
    
        private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("delete");
        }
    
    }

    web.xml

      <servlet>
        <servlet-name>customerServlet</servlet-name>
        <servlet-class>com.aidata.mvcapp.servlet.CustomerServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>customerServlet</servlet-name>
        <url-pattern>/customerServlet</url-pattern>
      </servlet-mapping>

    缺点:当添加一个请求时,需要在 Servlet 中修改两处代码:switch、添加方法;url 中使用 method=xxx 暴漏了要调用的方法,不私密,有安全隐患。

    第二种方式:反射

    jsp

    <body>
    
        <a href="addCustomer.do">Add</a>
        <br><br>
        
        <a href="query.do">Query</a>
        <br><br>
        
        <a href="deleteCustomer.do">Delete</a>
        <br><br>
        
    </body>

    web.xml

      <servlet>
        <servlet-name>customerServlet</servlet-name>
        <servlet-class>com.aidata.mvcapp.servlet.CustomerServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>customerServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
      </servlet-mapping>

    Servlet

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String servletPath = request.getServletPath();
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
            System.out.println(methodName);
            Method method;
            try {
                method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, request, response);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("add");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("query");
        }
    
        private void deleteCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("delete");
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("edit");
        }
    
    }

    流程:

    2.4 模糊查询

     非模糊查询

    JSP

    <%@page import="java.util.List"%>
    <%@page import="com.aidata.mvcapp.domain.Customer"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="query.do" method="post">
        <table>
            <tr>
                <td>CustomerName:</td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td>Address:</td>
                <td><input type="text" name="address"></td>
            </tr>        
            <tr>
                <td>Phone:</td>
                <td><input type="text" name="phone"></td>
            </tr>
            <tr>
                <td><input type="submit" name="Query"></td>
                <td><a href="">Add New Customer</a></td>
            </tr>
        </table>
    </form>
        <br><br>
        <%
           List<Customer> customers = (List)request.getAttribute("customers");
           if(customers != null && customers.size() > 0){
        %>
        <hr>
        <br><br>
        
            <table border="1" cellpadding="0" cellspacing="10">
              <tr>
                <th>ID</th>
                <th>CustomerName</th>
                <th>Address</th>
                <th>Phone</th>
                <th>UPDATEDELETE</th>
               </tr>
            <%
                for(Customer customer: customers){
            %>
            
            <tr>
                <td><%= customer.getId() %></td>
                <td><%= customer.getName() %></td>
                <td><%= customer.getAddress() %></td>
                <td><%= customer.getPhone() %></td>     
                <td>
                    <a href="">UPDATE</a>
                    <a href="">DELETE</a>
                </td>      
            </tr>
           
            <%      
           }
            %>
         </table>
        <%      
           }
        %>
        
    </body>
    </html>

    Servlet

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        private CustomerDAO customerDAO = new CustomerDAOJdbcImpl();
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String servletPath = request.getServletPath();
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
            System.out.println(methodName);
            Method method;
            try {
                method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, request, response);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("add");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.调用CustomerDAO的getAll()方法,得到Customer的集合
            List<Customer> customers = customerDAO.getAll();
            // 2.把customer集合放入request中
            request.setAttribute("customers", customers);
            // 3.转发页面到index.jsp,不能用重定向
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    
        private void deleteCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("delete");
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("edit");
        }
    
    }

    模糊查询

    接口添加方法,定义用于查询的类

    需要在 CustomerDAO 接口中定义一个 getForListWithCriteriaCustomer(CriteriaCustomer cc)。 其中 CriteriaCustomer 用于封装查询条件:name, address, phone。因为查询条件很多时候和 domain 类并不相同,所以要做成一个单独的类

    package com.aidata.mvcapp.dao;
    
    import java.util.List;
    
    import com.aidata.mvcapp.domain.Customer;
    
    public interface CustomerDAO {
    
        public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc);
    
        public List<Customer> getAll();
    
        public void save(Customer customer);
    
        public Customer get(Integer id);
    
        public void delete(Integer id);
    
        /**
         * @Description 返回和name相等的记录数
         * @param name
         * @return
         */
        public long getCountWithName(String name);
    
    }

    CriteriaCustomer

    package com.aidata.mvcapp.dao;
    
    public class CriteriaCustomer {
    
        private String name;
        private String address;
        private String phone;
    
        public CriteriaCustomer(String name, String address, String phone) {
            super();
            this.name = name;
            this.address = address;
            this.phone = phone;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    
    }

    拼 SQL
    SQL: "SELECT id, name, address, phone FROM customers WHERE " +
    "name LIKE ? AND address LIKE ? ANDphone LIKE ?";

    package com.aidata.mvcapp.dao.impl;
    
    import java.util.List;
    
    import com.aidata.mvcapp.dao.CriteriaCustomer;
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.DAO;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerDAOJdbcImpl extends DAO<Customer> implements CustomerDAO {
    
        @Override
        public List<Customer> getAll() {
            String sql = "SELECT id, name, address, phone From customers";
            return getForList(sql);
        }
    
        @Override
        public void save(Customer customer) {
            String sql = "INSERT INTO customers(name, address, phone) VALUES(?,?,?)";
            update(sql, customer.getName(), customer.getAddress(), customer.getPhone());
        }
    
        @Override
        public Customer get(Integer id) {
            String sql = "SELECT id, name, address, phone FROM customers WHERE id = ?";
            return get(sql, id);
        }
    
        @Override
        public void delete(Integer id) {
            String sql = "DELETE FROM customers WHERE id = ?";
            update(sql, id);
        }
    
        @Override
        public long getCountWithName(String name) {
            String sql = "SELECT count(id) FROM customers WHERE name = ?";
            return getForValue(sql, name);
        }
    
        @Override
        public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) {
            String sql = "SELECT id, name, address, phone FROM customers WHERE "
                    + "name LIKE ? AND address LIKE ? AND phone LIKE ?";
    
            return getForList(sql, cc.getName(), cc.getAddress(), cc.getPhone());
        }
    
    }

    为了正确的填充占位符时,重写了 CriteriaCustomer 的 getter:

    package com.aidata.mvcapp.dao;
    
    public class CriteriaCustomer {
    
        private String name;
        private String address;
        private String phone;
    
        public CriteriaCustomer(String name, String address, String phone) {
            super();
            this.name = name;
            this.address = address;
            this.phone = phone;
        }
    
        public String getName() {
            if (name == null) {
                name = "%%";
            } else {
                name = "%" + name + "%";
            }
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            if (address == null) {
                address = "%%";
            } else {
                address = "%" + address + "%";
            }
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getPhone() {
            if (phone == null) {
                phone = "%%";
            } else {
                phone = "%" + phone + "%";
            }
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    
    }

    修改 Servlet

    获取请求参数,把请求参数封装为CriteriaCustomer 对象,再调用 getForListWithCriteriaCustomer(CriteriaCustomer cc) 方法

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.aidata.mvcapp.dao.CriteriaCustomer;
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        private CustomerDAO customerDAO = new CustomerDAOJdbcImpl();
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String servletPath = request.getServletPath();
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
            System.out.println(methodName);
            Method method;
            try {
                method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, request, response);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("add");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String name = request.getParameter("name");
            String phone = request.getParameter("phone");
            String address = request.getParameter("address");
    
            CriteriaCustomer cc = new CriteriaCustomer(name, address, phone);
    
            // 1.调用CustomerDAO的getAll()方法,得到Customer的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);
            // 2.把customer集合放入request中
            request.setAttribute("customers", customers);
            // 3.转发页面到index.jsp,不能用重定向
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    
        private void deleteCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("delete");
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("edit");
        }
    
    }

    2.5 删除操作

    Servlet 

    超链接:delete.do?id=<%=customer.getId()%>
    Servlet 的 delete 方法
    获取 id
    调用 DAO 执行删除
    重定向到 query.do(若目标页面不需要读取当前请求的 request 属性,就可以使用重定向),将显示删除后的 Customer 的 List

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.aidata.mvcapp.dao.CriteriaCustomer;
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        private CustomerDAO customerDAO = new CustomerDAOJdbcImpl();
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String servletPath = request.getServletPath();
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
            System.out.println(methodName);
            Method method;
            try {
                method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, request, response);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("add");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String name = request.getParameter("name");
            String phone = request.getParameter("phone");
            String address = request.getParameter("address");
    
            CriteriaCustomer cc = new CriteriaCustomer(name, address, phone);
    
            // 1.调用CustomerDAO的getAll()方法,得到Customer的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);
            // 2.把customer集合放入request中
            request.setAttribute("customers", customers);
            // 3.转发页面到index.jsp,不能用重定向
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    
        private void deleteCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String idStri = request.getParameter("id");
            int id = 0;
            // try...catch... 防止idStri不能转为int类型,若不能转,id=0,不进行任何删除操作
            try {
                id = Integer.parseInt(idStri);
                customerDAO.delete(id);
            } catch (Exception e) {
            }
            response.sendRedirect("query.do");
            System.out.println("delete");
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("edit");
        }
    
    }

    JSP

    jQuery 提示:
    确定要删除 xx 的信息吗?

     

    <%@page import="java.util.List"%>
    <%@page import="com.aidata.mvcapp.domain.Customer"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript" src="scripts/jquery-1.11.3.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $(".delete").click(function() {
                var content = $(this).parent().parent().find("td:eq(1)").text();
                var flag = confirm("确定要删除"+content+"的信息吗?");
                return flag;
            });
        });
    </script>
    </head>
    <body>
    <form action="query.do" method="post">
        <table>
            <tr>
                <td>CustomerName:</td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td>Address:</td>
                <td><input type="text" name="address"></td>
            </tr>        
            <tr>
                <td>Phone:</td>
                <td><input type="text" name="phone"></td>
            </tr>
            <tr>
                <td><input type="submit" name="Query"></td>
                <td><a href="">Add New Customer</a></td>
            </tr>
        </table>
    </form>
        <br><br>
        <%
           List<Customer> customers = (List)request.getAttribute("customers");
           if(customers != null && customers.size() > 0){
        %>
        <hr>
        <br><br>
        
            <table border="1" cellpadding="0" cellspacing="10">
              <tr>
                <th>ID</th>
                <th>CustomerName</th>
                <th>Address</th>
                <th>Phone</th>
                <th>UPDATEDELETE</th>
               </tr>
            <%
                for(Customer customer: customers){
            %>
            
            <tr>
                <td><%= customer.getId() %></td>
                <td><%= customer.getName() %></td>
                <td><%= customer.getAddress() %></td>
                <td><%= customer.getPhone() %></td>     
                <td>
                    <a href="">UPDATE</a>
                    <a href="deleteCustomer.do?id=<%= customer.getId() %>" class="delete">DELETE</a>
                </td>      
            </tr>
           
            <%      
           }
            %>
         </table>
        <%      
           }
        %>
        
    </body>
    </html>

     request的getParameter(String name)方法获取表单里面的name信息

    只有设置了 name 属性的表单元素才能在提交表单时传递它们的值,因为服务端获取表单提交的数据是通过表单元素的 name 属性的值而得到的,没有 name 属性就无法得到表单元素提交给服务端的值

     2.6 新增

    流程

    效果:点击Add New Customer 超链接,连接到 newcustomer.jsp

    创建newcustomer.jsp

     

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="addCustomer.do" method="post">
        <table>
            <tr>
                <td>CustomerName:</td>
                <td><input type="text" name="name" value="<%= request.getParameter("name") == null?"": request.getParameter("name") %>"></td>
            </tr>
            <tr>
                <td>Address:</td>
                <td><input type="text" name="address"></td>
            </tr>        
            <tr>
                <td>Phone:</td>
                <td><input type="text" name="phone"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" name="Submit"></td>
            </tr>
        </table>
    </form>
    </body>
    </html>

    success.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <h4>操作成功!</h4>
        <h4><a href="index.jsp">Return...</a></h4>
    </body>
    </html>

    修改addCustomer 方法
    CustomerServlet 的 addCustomer 方法

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.aidata.mvcapp.dao.CriteriaCustomer;
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        private CustomerDAO customerDAO = new CustomerDAOJdbcImpl();
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String servletPath = request.getServletPath();
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
            System.out.println(methodName);
            Method method;
            try {
                method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, request, response);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 1. 获取表单参数:name,address,phone
            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
            // 2. 检验name是否已经被占用
    
            // 2.1 调用customerDAO的getCountWithName方法获取name是否在数据库中存在
            long count = customerDAO.getCountWithName(name);
            // 2.2 若返回值大于0,则响应newcustomer.jsp页面:
            // 通过转发的方式响应newcustomer.jsp
            if (count > 0) {
                // 2.2.1 要求在newcustomer.jsp页面显示一个错误消息:用户名name已经被占用,请重新选择!
                // 在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,
                // 在页面上通过request.getAttribute("message")的方式显示
                request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");
                // 2.2.2 newcustomer.jsp的表单值可以回显
                // jsp中,value="<%= request.getParameter("name") == null?"": request.getParameter("name") %>
    
                // 2.2.3 结束方法:return
                request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);
                return;
            }
            // 3. 若验证通过,则把表单参数封装为一个Customer对象customer
            Customer customer = new Customer(name, address, phone);
            // 4. 调用CustomerDAO的save方法,执行保存操作
            customerDAO.save(customer);
            // 5. 重定向到success.jsp页面
            response.sendRedirect("success.jsp");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String name = request.getParameter("name");
            String phone = request.getParameter("phone");
            String address = request.getParameter("address");
    
            CriteriaCustomer cc = new CriteriaCustomer(name, address, phone);
    
            // 1.调用CustomerDAO的getAll()方法,得到Customer的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);
            // 2.把customer集合放入request中
            request.setAttribute("customers", customers);
            // 3.转发页面到index.jsp,不能用重定向
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    
        private void deleteCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String idStri = request.getParameter("id");
            int id = 0;
            // try...catch... 防止idStri不能转为int类型,若不能转,id=0,不进行任何删除操作
            try {
                id = Integer.parseInt(idStri);
                customerDAO.delete(id);
            } catch (Exception e) {
            }
            response.sendRedirect("query.do");
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("edit");
        }
    
    }

    执行流程图

    2.7 修改

    先显示(SELECT 操作)修改的页面,再进行修改(update)
    显示修改页面
    Update 的超链接:<a href="edit.do?id=<%= customer.getId() %>">UPDATE</a>

    index.jsp

    <%@page import="java.util.List"%>
    <%@page import="com.aidata.mvcapp.domain.Customer"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript" src="scripts/jquery-1.11.3.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $(".delete").click(function() {
                var content = $(this).parent().parent().find("td:eq(1)").text();
                var flag = confirm("确定要删除"+content+"的信息吗?");
                return flag;
            });
        });
    </script>
    </head>
    <body>
    <form action="query.do" method="post">
        <table>
            <tr>
                <td>CustomerName:</td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td>Address:</td>
                <td><input type="text" name="address"></td>
            </tr>        
            <tr>
                <td>Phone:</td>
                <td><input type="text" name="phone"></td>
            </tr>
            <tr>
                <td><input type="submit" name="Query"></td>
                <td><a href="newcustomer.jsp">Add New Customer</a></td>
            </tr>
        </table>
    </form>
        <br><br>
        <%
           List<Customer> customers = (List)request.getAttribute("customers");
           if(customers != null && customers.size() > 0){
        %>
        <hr>
        <br><br>
        
            <table border="1" cellpadding="0" cellspacing="10">
              <tr>
                <th>ID</th>
                <th>CustomerName</th>
                <th>Address</th>
                <th>Phone</th>
                <th>UPDATEDELETE</th>
               </tr>
            <%
                for(Customer customer: customers){
            %>
            
            <tr>
                <td><%= customer.getId() %></td>
                <td><%= customer.getName() %></td>
                <td><%= customer.getAddress() %></td>
                <td><%= customer.getPhone() %></td>     
                <td>
                    <a href="edit.do?id=<%= customer.getId() %>">UPDATE</a>
                    <a href="deleteCustomer.do?id=<%= customer.getId() %>" class="delete">DELETE</a>
                </td>      
            </tr>
           
            <%      
           }
            %>
         </table>
        <%      
           }
        %>
        
    </body>
    </html>

    edit 方法: 

    private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            String forwardPath = "/error.jsp";
            // 1. 获取请求参数id
            String idStr = request.getParameter("id");
            // 2.调用customerDAO的customerDAO.get(id)获取和id对应的Customer对象
            try {
                Customer customer = customerDAO.get(Integer.parseInt(idStr));
                if (customer != null) {
                    forwardPath = "updatecustomer.jsp";
                    // 3.将customer放入request中
                    request.setAttribute("customer", customer);
                }
            } catch (Exception e) {
            }
            // 4.响应updatecustomer.jsp页面:转发
            request.getRequestDispatcher(forwardPath).forward(request, response);
        }

    JSP 页面
    获取请求域中的 Customer 对象,调用对应的字段的 get 方法来显示值。
    使用隐藏域来保存要修改的 Customer 对象的 id:<input type="hidden" name="id" value=“<%= customer.getId() %>"/>。虽然没有修改id,当然也不能改,但依然少不了,id用来判断到底是哪个customer。 

    使用隐藏域来保存 oldName:<input type="hidden" name=“oldName" value=“<%= customer.getName() %>"/>,oldName保存修改前的名字,name会更新为提交的名字。

    关于隐藏域:和其他的表单域一样可以被提交到服务器,只不过在页面上不显示
    提交到 update.do

    updatecustomer.jsp:

    <%@page import="com.aidata.mvcapp.domain.Customer"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%
        Object msg = request.getAttribute("message");
        if(msg != null){
            
    %>        
        <br>
        <font color="red"><%= msg %></font>
        <br>
        <br>
    <%
    }
        String id = null;
        String oldName = null;
        String name = null;
        String address = null;
        String phone = null;
        
        Customer customer = (Customer)request.getAttribute("customer");
        if(customer != null){
            // 如果没有出错,从edit方法过来的,customer不为空
            id = customer.getId() + "";
            // 这里name和oldName一样,但是后面提交的时候,name会提交,即更新,而oldName保持不变,从而可以比较
            oldName = customer.getName();
            name = customer.getName();
            address = customer.getAddress();
            phone = customer.getPhone();
        }else{
            // 如果出错,即提交了重复的名字,会出现提示信息,会停留在本页面,没有edit方法了,也就没有customer属性了
            // 只能从之前提交的request中得到id等
            id = request.getParameter("id");
            oldName = request.getParameter("oldName");
            //
            name = request.getParameter("oldname");
            address = request.getParameter("address");
            phone = request.getParameter("phone");
        }
    %>
    <form action="update.do" method="post">
        
        <input type="hidden" name="id" value="<%= id %>" />
        <input type="hidden" name="oldName" value="<%= oldName %>" />
    
        <table>
            <tr>
                <td>CustomerName:</td>
                <td><input type="text" name="name" value="<%= name %>" /></td>
            </tr>
            <tr>
                <td>Address:</td>
                <td><input type="text" name="address" value="<%= address %>" /></td>
            </tr>        
            <tr>
                <td>Phone:</td>
                <td><input type="text" name="phone"value="<%= phone %>" /></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" name="Submit"></td>
            </tr>
        </table>
    </form>
    
    </body>
    </html>

    隐藏域的问题
    回显的问题
    Newcustomer.jsp 和 updateCustomer.jsp 能汇总到一个页面吗 ?

    修改操作
    Update 方法:

     private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1. 获取表单参数:name,address,phone
            String id = request.getParameter("id");
            String name = request.getParameter("name");
            String phone = request.getParameter("phone");
            String address = request.getParameter("address");
            String oldName = request.getParameter("oldName");
            // 2. 检验name是否已经被占用
            // 2.1 比较name和oldName是否相同,若相同说明name可用
            // 2.1 若不相同,调用customerDAO的getCountWithName方法获取name是否在数据库中存在
            if (!oldName.equalsIgnoreCase(name)) {
                // 如你输入了A,以前已经有了a,java的equals会认为两者不同,于是进入该if
                // 但是mysql认为A和a相同,于是返回了1,即已经存在了,从而引发message
                // 忽略大小写,不进入if,直接进行后面的update
                long count = customerDAO.getCountWithName(name);
                // 2.2 若返回值大于0,则响应updatecustomer.jsp
                if (count > 0) {
                    // 2.2.1 在updatecustomer.jsp页面显示一个错误信息:用户名name已经被占用,请重新选择!
                    // 在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,
                    // 在页面上通过request.getAttribute("message")的方式显示
                    request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");
                    // 2.2.2 updatecustomer.jsp的表单值可以回显
                    // address,phone显示提交表单的新的值,而name显示oldName,而不是新提交的name
                    // 2.2.3 结束方法:return
                    return;
                }
            }
            // 3. 若验证通过,则把表单参数封装为一个Customer对象customer
            Customer customer = new Customer(name, address, phone);
            customer.setId(Integer.parseInt(id));
            // 4. 调用CustomerDAO的update(Customer customer)执行更新操作
            customerDAO.update(customer);
            // 5. 重定向到query.do
            response.sendRedirect("query.do");
        }
    
    }

     完整Servlet

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.aidata.mvcapp.dao.CriteriaCustomer;
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;
    import com.aidata.mvcapp.domain.Customer;
    
    public class CustomerServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        private CustomerDAO customerDAO = new CustomerDAOJdbcImpl();
    
        public CustomerServlet() {
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String servletPath = request.getServletPath();
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
            System.out.println(methodName);
            Method method;
            try {
                method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this, request, response);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 1. 获取表单参数:name,address,phone
            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
            // 2. 检验name是否已经被占用
    
            // 2.1 调用customerDAO的getCountWithName方法获取name是否在数据库中存在
            long count = customerDAO.getCountWithName(name);
            // 2.2 若返回值大于0,则响应newcustomer.jsp页面:
            // 通过转发的方式响应newcustomer.jsp
            if (count > 0) {
                // 2.2.1 要求在newcustomer.jsp页面显示一个错误消息:用户名name已经被占用,请重新选择!
                // 在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,
                // 在页面上通过request.getAttribute("message")的方式显示
                request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");
                // 2.2.2 newcustomer.jsp的表单值可以回显
                // jsp中,value="<%= request.getParameter("name") == null?"": request.getParameter("name") %>
    
                // 2.2.3 结束方法:return
                request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);
                return;
            }
            // 3. 若验证通过,则把表单参数封装为一个Customer对象customer
            Customer customer = new Customer(name, address, phone);
            // 4. 调用CustomerDAO的save方法,执行保存操作
            customerDAO.save(customer);
            // 5. 重定向到success.jsp页面
            response.sendRedirect("success.jsp");
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String name = request.getParameter("name");
            String phone = request.getParameter("phone");
            String address = request.getParameter("address");
    
            CriteriaCustomer cc = new CriteriaCustomer(name, address, phone);
    
            // 1.调用CustomerDAO的getAll()方法,得到Customer的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);
            // 2.把customer集合放入request中
            request.setAttribute("customers", customers);
            // 3.转发页面到index.jsp,不能用重定向
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    
        private void deleteCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String idStri = request.getParameter("id");
            int id = 0;
            // try...catch... 防止idStri不能转为int类型,若不能转,id=0,不进行任何删除操作
            try {
                id = Integer.parseInt(idStri);
                customerDAO.delete(id);
            } catch (Exception e) {
            }
            response.sendRedirect("query.do");
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            String forwardPath = "/error.jsp";
            // 1. 获取请求参数id
            String idStr = request.getParameter("id");
            // 2.调用customerDAO的customerDAO.get(id)获取和id对应的Customer对象
            try {
                Customer customer = customerDAO.get(Integer.parseInt(idStr));
                if (customer != null) {
                    forwardPath = "updatecustomer.jsp";
                    // 3.将customer放入request中
                    request.setAttribute("customer", customer);
                }
            } catch (Exception e) {
            }
            // 4.响应updatecustomer.jsp页面:转发
            request.getRequestDispatcher(forwardPath).forward(request, response);
        }
    
        private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1. 获取表单参数:name,address,phone
            String id = request.getParameter("id");
            String name = request.getParameter("name");
            String phone = request.getParameter("phone");
            String address = request.getParameter("address");
            String oldName = request.getParameter("oldName");
            // 2. 检验name是否已经被占用
            // 2.1 比较name和oldName是否相同,若相同说明name可用
            // 2.1 若不相同,调用customerDAO的getCountWithName方法获取name是否在数据库中存在
            if (!oldName.equalsIgnoreCase(name)) {
                // 如你输入了A,以前已经有了a,java的equals会认为两者不同,于是进入该if
                // 但是mysql认为A和a相同,于是返回了1,即已经存在了,从而引发message
                // 忽略大小写,不进入if,直接进行后面的update
                long count = customerDAO.getCountWithName(name);
                // 2.2 若返回值大于0,则响应updatecustomer.jsp
                if (count > 0) {
                    // 2.2.1 在updatecustomer.jsp页面显示一个错误信息:用户名name已经被占用,请重新选择!
                    // 在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,
                    // 在页面上通过request.getAttribute("message")的方式显示
                    request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");
                    // 2.2.2 updatecustomer.jsp的表单值可以回显
                    // address,phone显示提交表单的新的值,而name显示oldName,而不是新提交的name
    

                      request.getRequestDispatcher("update.jsp").forward(request, response);
                      // 2.2.3 结束方法:return
                      return; // 重定向跳转后必须加上return,要不然页面虽然跳转了,但是还会执行跳转后面的语句

    
                }
            }
            // 3. 若验证通过,则把表单参数封装为一个Customer对象customer
            Customer customer = new Customer(name, address, phone);
            customer.setId(Integer.parseInt(id));
            // 4. 调用CustomerDAO的update(Customer customer)执行更新操作
            customerDAO.update(customer);
            // 5. 重定向到query.do
            response.sendRedirect("query.do");
        }
    
    }

    2.8 更换底层存储源

    深入理解面向接口编程:在类中调用接口的方法,而不必关心具体的实现。这将有利于代码的解耦,使程序有更好的可移植性和可扩展性。

    需要修改源码 

    src下新建customes.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <customers>
        <customer id="1001">
            <name>Tom</name>
            <address>Beijing</address>
            <phone>123</phone>
        </customer>
    </customers>

    新建实现类,功能暂时省略

    package com.aidata.mvcapp.dao.impl;
    
    import java.util.List;
    
    import com.aidata.mvcapp.dao.CriteriaCustomer;
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.domain.Customer;
    
    
    public class CustomerDAOXMLImpl implements CustomerDAO {
    
        @Override
        public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public List<Customer> getAll() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void save(Customer customer) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public Customer get(Integer id) {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void delete(Integer id) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void update(Customer customer) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public long getCountWithName(String name) {
            // TODO Auto-generated method stub
            return 0;
        }
    
    }

    只需要在CustomerServlet中修改一行语句

    private CustomerDAO customerDAO = new CustomerDAOXMLImpl();

    使用工厂模式,不修改源码

    如果一行语句也不用修改怎么做?

    使用属性文件

    动态修改 Customer 的存储方式:通过修改类路径下的 switch.properties 文件的方式来实现

    src下创建switch.properties

    #type=xml
    type=jdbc

    创建Servlet读取配置文件

    当Web 应用在启动的时候,InitServlet 被创建,并由 Servlet 容器调用其 init() 方法:

      <servlet>
        <servlet-name>InitServlet</servlet-name>
        <servlet-class>com.aidata.mvcapp.servlet.InitServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>

    读取类路径下的 switch.properties 文件,获取 switch.properties 的 type 属性值,赋给了 CustomerDAOFactory 的 type 属性值

    package com.aidata.mvcapp.servlet;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.aidata.mvcapp.dao.factory.CustomerDAOFactory;
    
    public class InitServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        @Override
        public void init() throws ServletException {
            CustomerDAOFactory.getInstance().setType("jdbc");
            InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/switch.properties");
            Properties properties = new Properties();
            try {
                properties.load(in);
                String type = properties.getProperty("type");
                CustomerDAOFactory.getInstance().setType(type);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }

     需要通过一个类的一个方法来获取具体的实现类的对象:

    package com.aidata.mvcapp.dao.factory;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import com.aidata.mvcapp.dao.CustomerDAO;
    import com.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;
    import com.aidata.mvcapp.dao.impl.CustomerDAOXMLImpl;
    
    public class CustomerDAOFactory {
    
        private Map<String, CustomerDAO> daos = new HashMap<String, CustomerDAO>();
    
        private CustomerDAOFactory() {
            daos.put("jdbc", new CustomerDAOJdbcImpl());
            daos.put("xml", new CustomerDAOXMLImpl());
        }
    
        private static CustomerDAOFactory instance = new CustomerDAOFactory();
    
        public static CustomerDAOFactory getInstance() {
            return instance;
        }
    
        private static String type = null;
    
        public void setType(String type) {
            this.type = type;
        }
    
        public CustomerDAO getCustomerDAO() {
            return daos.get(type);
        }
    }

    创建 CustomerServlet 时,为 customerDAO 属性赋值是通过 CustomerDAOFactory  的 getCustomerDAO() 方法完成的 。此时的 type 已经在 InitServlet 中被赋值了。

    private CustomerDAO customerDAO = CustomerDAOFactory.getInstance().getCustomerDAO();
  • 相关阅读:
    谈谈入职新公司1月的体会
    来点高逼格的,使用前端Sendmessage实现SSO
    2019做的第一个艰难决定
    Golang中设置函数默认参数的优雅实现
    linux系统shell基础知识入门二
    在AWS中自定义Credential Provider实现Client连接
    linux系统shell基础知识入门
    初学者学习golang可能遇到的坑
    【Menu】 目录索引
    rsync 服务介绍及相关实验
  • 原文地址:https://www.cnblogs.com/aidata/p/11986345.html
Copyright © 2011-2022 走看看