java开发 mvc框架

来源:互联网 发布:瞬间流泪的话知乎 编辑:程序博客网 时间:2024/05/16 09:17

阅读前瞻:本文源于对javaweb相关技术和资料汇总,涉及大量javaweb基础技术诸如:Servlet运行原理、Get/Post请求的区别、jsp的基本原理和运行框架、jsp的9大隐含对象的使用、MVC开发模式的使用、构建封装自己dao代码库、以及基于MVC的增删改查操作等;小结最后还有面向接口编程的多数据源配置与存储,以及工厂模式的使用。除此之外,后续文章会对cookie、session、JavaBean、监听、权限管理、文件上传与下载、分页等诸多技术汇总。本文旨在java-web多技术贯穿于单项目中,逐渐深入的过程,使得大家既学习了java技术路线,也知道其怎么用。最后会附上源码,最后一节重点对所有实现技术小结与汇总,此过程会使用作者项目技术理解、网络资源资料、学习视频和文档截图文件等为参考,力求简单通俗易学。最后,作者文章布局采用:1、实验准备;2、需求分析;3、模块化实现;4、实验优化;5、技术梳理的写作思路。(本文原创,转载标明出处:基于JAVA-MVC技术的顾客管理项目案例总结)

一、实验准备阶段:

1  win*系统,一般配置笔记本或者台式机

2  安装MyEclipse开发平台,本实验使用MyEclipse2015(点击下载 访问密码 eafa)

3 Mysql数据库,本实验采用mysql-installer-community-5.6.14.0.msi(点击下载 访问密码 39bf)

4 关于数据库连接的3个JAR包

4.1 JDBC链接数据库的jar包,本实验采用mysql-connector-java-5.1.20.jar(点击下载 访问密码 8bb1)

4.2 dbUtils数据库JAR包,本实验采用commons-dbutils-1.6.jar(点击下载 访问密码 535d)

4.3 c3p0数据库配置JAR包,本实验采用c3p0-0.9.1.2.jar(点击下载 访问密码 9916)

5 两个公共文件

5.1 关于编写Jquery需要的js文件,本实验使用jquery.min.js(点击下载 访问密码 3357)

5.2 关于c3p0数据库配置xml源文件c3p0-config.xml(点击下载 访问密码 33a6)

二、需求分析阶段

1 对MyEclipse和MySql的正确安装,并对MyEclipse环境变量配置:(配置参考文档)

2 要求l使用mysql数据库去创建数据库test和表customers(id int 主键自增,name String 唯一约束,address String,phone String)

3 采用MVC技术开发,实现M/V/C很好的封装与解耦,在此基础完成对顾客表的增删改查,其中要求数据可以回显、模糊查询、容错等

4 servlet初始化启动控制多数据源配置

5 其他诸如分页、cookie、session、JavaBean、监听、权限管理、文件上传与下载等后续文章继续完善优化。

三、数据库创建阶段

1
2
3
4
5
6
7
8
9
10
# 创建数据库test
create database test;
use test;
#创建customer表id主键自增,name唯一
create table customers(
id varchar(11) primary key not null,
name varchar(70) not null unique,
address varchar(70),
phone varchar(70)
);

四、基于MVC技术开发阶段

1 顾客管理项目环境配置简介

MVC百度百科:MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。(注:详细MVC可以参照官方文档或者google

配置简介:

1 新建java web项目,默认基础下分别建立MVC对于的包,以及添加需要配置的jar包、js文件、xml文件、imgs等文件,打通整体开发框架。

2 创建需要完成jsp页面

2 MVC架构搭建

1、配置文件的引用

mysql-connector-java-5.1.20.jar:连接数据库的jar包,放于./WEB-INF/lib下

commons-dbutils-1.6.jar:dbutils的jar包,放于./WEB-INF/lib下

c3p0-0.9.1.2.jar:c3p0的jar包,放于./WEB-INF/lib下

jquery.min.js:用于编写js的文件,放于./WebRoot/scripts下

c3p0-config.xml:用于配置数据库,放于./src下

复制代码
<?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:///test</property>            <property name="acquireIncrement">5</property>    <property name="initialPoolSize">10</property>    <property name="minPoolSize">10</property>    <property name="maxPoolSize">50</property>    <!-- intergalactoApp adopts a different approach to configuring statement caching -->    <property name="maxStatements">20</property>     <property name="maxStatementsPerConnection">5</property>      </named-config></c3p0-config>
复制代码

2、 数据层配置

 com.cuit.mvc.db包:JdbcUtils.java数据库连接和释放方法的封装

复制代码
package com.cuit.mvc.db;import java.sql.Connection;import java.sql.SQLException;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;/** * JDBC操作工具 * @author 白宁超 http://www.cnblogs.com/baiboy/ */public class JdbcUtils {    /**     * 释放Connection链接     * @param connection     */    public static void releaseConnection(Connection connection){        try{            if(connection!=null) connection.close();        }catch(Exception e){            e.printStackTrace();        }    }    private static DataSource dataSource = null;        static{        dataSource=new ComboPooledDataSource("mvcapp");    }    /**     * 返回数据源的一个Connection对象     * @return     * @throws SQLException      */    public static Connection getConnection() throws SQLException{        return dataSource.getConnection();    }}
复制代码

 com.cuit.mvc.model包:Customer.java实体类的封装

复制代码
package com.cuit.mvc.model;public class Customer {        private int  id;    private String name;    private String address;    private String phone;    public int getId() {        return id;    }    public Customer() {            }    public Customer(String name, String address, String phone) {        this.name = name;        this.address = address;        this.phone = phone;    }    public void setId(int 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+"]";    }}
复制代码

 com.cuit.mvc.dao包:DAO.java最底层公共方法封装;CustomerDAO提供公共方法的接口;

DAO源码:

复制代码
package com.cuit.mvc.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.cuit.mvc.db.JdbcUtils;/** * 封装了基本的CRUD的方法,以供子类继承使用 * 当前DAO直接在方法中获取数据库连接 * @param <T> :当前DAO处理实体的类型是什么 * @author 白宁超 http://www.cnblogs.com/baiboy/ * */public class DAO<T> {    //此步骤前需要/lib加入commons-dbutils-xx.jar    private QueryRunner  queryRunner=new QueryRunner();    private Class<T> clazz;    public DAO(){        //Type通过Ctrl+Shift+O进行反射Type选择        Type superClass=getClass().getGenericSuperclass();        if(superClass instanceof ParameterizedType){            ParameterizedType parameterizedType=(ParameterizedType)superClass;            Type[] typeArgs=parameterizedType.getActualTypeArguments();            if(typeArgs!=null && typeArgs.length>0){                if(typeArgs[0] instanceof Class)    clazz=(Class<T>)typeArgs[0];            }        }    }        /**     * 返回某一个字段的值,或者返回数据表中有多少条记录等。     * @param sql:SQL语句     * @param args:填充SQL语句的占位符     * @return     */    public <E> E getForValue(String sql,Object ... args) {        Connection connection=null;        try{            connection=JdbcUtils.getConnection();            return (E) queryRunner.query(connection,sql,new ScalarHandler<T>(),args);        }catch(Exception e){            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(connection);        }        return null;    }    /**     * 返回T所对应的List     * @param sql:SQL语句     * @param args:填充SQL语句的占位符     * @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;    }    /**     * 返回对应T的一个实体类对象     * @param sql:SQL语句     * @param args:填充SQL语句的占位符     * @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;    }    /**     * 该方法封装了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);        }    }}
复制代码

CustomerDAO源码:

复制代码
package com.cuit.mvc.dao;import java.util.List;import com.cuit.mvc.model.CriteriaCustomer;import com.cuit.mvc.model.Customer;public interface CustomerDAO {    public List<Customer> getAll();//获取Customer列表信息    public void save(Customer customer);//对Customer的添加,通过CTRL+T转到定义    public void update(Customer customer);//对Customer的更新,通过CTRL+T转到定义    public Customer get(int id);//获取Customer实体    public void delete(int id);//根据id进行删除    public long getCountWithName(String name);//返回name相等的记录数    //cc封装了查询条件,返回查询条件的list    public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc);    }
复制代码

com.cuit.mvc.dao.impl包:CustomerDAOJdbcImpl.java:Customer对CustomerDAO具体方法的实现

复制代码
package com.cuit.mvc.dao.impl;import java.util.List;import com.cuit.mvc.dao.CustomerDAO;import com.cuit.mvc.dao.DAO;import com.cuit.mvc.model.CriteriaCustomer;import com.cuit.mvc.model.Customer;public class CustomerDAOJdbcImpl extends DAO<Customer> implements CustomerDAO{    public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) {        String sql="select * from customers where name like ? and address like ? "                + "and phone like ?";        //修改了CriteriaCustomer的getter方法:使其返回字符串中有%%        //若返回值为null返回%%,若不返回null则返回:"%"+字段本身的值+"%"        //如上效果如:cc.getName()==null?%%:%+name+%        System.out.println(sql);        return getForList(sql,cc.getName(),cc.getAddress(),cc.getPhone());            }    @Override    public List<Customer> getAll() {        String sql="select * from customers";        return getForList(sql);    }    @Override    public void save(Customer customer) {        String sql="insert customers(name,address,phone) values(?,?,?)";        update(sql, customer.getName(),customer.getAddress(),customer.getPhone());    }    @Override    public Customer get(int id) {        String sql="select * from customers where id=?";        return get(sql,id);    }    @Override    public void delete(int 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 void update(Customer customer) {        String sql="update customers set name=?,address=?,phone=? where id=?";        update(sql,customer.getName(),customer.getAddress(),customer.getPhone(),customer.getId());    }}
复制代码

3 业务逻辑层

 com.cuit.mvc.dao.servlet包:CustomerServlet.java对CustomerDAO公共方法具体实现,以及页面显示的控制

复制代码
package com.cuit.mvc.servlet;import java.io.IOException;import java.io.PrintWriter;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.cuit.mvc.dao.CustomerDAO;import com.cuit.mvc.dao.factory.CustomerDAOFactory;import com.cuit.mvc.dao.impl.CustomerDAOJdbcImpl;import com.cuit.mvc.dao.impl.CustomerDAOXMLImpl;import com.cuit.mvc.model.CriteriaCustomer;import com.cuit.mvc.model.Customer;public class CustomerServlet extends HttpServlet {    //private CustomerDAO customerDAO=new CustomerDAOJdbcImpl();    //private CustomerDAO customerDAO=new CustomerDAOXMLImpl();    private CustomerDAO customerDAO=CustomerDAOFactory.getInstance().getCustomerDAO();    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doPost(request, response);    }    /*public 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;        default: break;        }    }*/        @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp)            throws ServletException, IOException {        //1 获取servlet路径 诸如:/add.do        String servletPath=req.getServletPath().substring(1);        //去除/和.do得到类似于add这样字符串        String methodName=servletPath.substring(0,servletPath.length()-3);        //System.out.println(methodName);        try {            //利用反射获取获取methodName对应的方法            Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);            //利用反射获取方法            method.invoke(this, req,resp);        } catch (Exception e) {            //出错时候响应出来            resp.sendRedirect("error.jsp");        }    }    private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{        String forwordPath="/error.jsp";        //1 获取请求参数id        String idstr=request.getParameter("id");        //2 调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customer        try{            Customer customer=customerDAO.get(Integer.parseInt(idstr));            if(customer!=null){                forwordPath="/updatecustomer.jsp";                //3 将customer放在request中                request.setAttribute("customer", customer);            }        }catch(Exception e){}        //4 响应updatecustomer.jsp页面:转发        request.getRequestDispatcher(forwordPath).forward(request, response);    }    private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{        //1 获取请求参数:id,name,address,phone,oldname        String id=request.getParameter("id");        String name=request.getParameter("name");        String oldname=request.getParameter("oldname");        String address=request.getParameter("address");        String phone=request.getParameter("phone");        //2  检验name是否被占用        //2.1  比较name和oldname是否相同,若相同name可用,oldname.equals(name)不如equalsIgnoreCase,数据库默认大小写一致的,而equals忽略大小写        if(!oldname.equalsIgnoreCase(name)){            //不相同,调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在            long count=customerDAO.getCountWithName(name);            //大于0, 响应updatecustomer.jsp页面:通过转发响应newcustomer.jsp            if(count>0){                // 通过request.getAttribute("message")显示信息,在页面上request.getAttribute("message")的方式显示                // 表单据回显。address,phone显示提交的新值, name显示oldname,而不是新值                request.setAttribute("message", "用户名["+name+"]已经被占用,请重新填写!");                // 方法结束                request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response);                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");            }    //模糊查询    private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{        String name=request.getParameter("name");        String address=request.getParameter("address");        String phone=request.getParameter("phone");        CriteriaCustomer cc=new CriteriaCustomer(name,address,phone);        //1 调用CustomerDAO的getALl方法得到Customer集合        //List<Customer> sustomers=customerDAO.getAll();获取所有信息列表        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 delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{        String idstr=request.getParameter("id").trim();        int id=0;        try{            id=Integer.parseInt(idstr);            customerDAO.delete(id);        }catch(Exception e){}        response.sendRedirect("query.do");    }    //此方法名称跟页面add添加的action中add.do匹配    private void add(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(String name)获取name在数据库中是否存在        long count=customerDAO.getCountWithName(name);        if(count>0){        //2.2 若返回值大于0,则相应newcustomer.jsp页面:①在此页面显示一个错误信息②此表单值可以回显        //     通过request.getAttribute("message")显示信息        //     通过value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"回显            request.setAttribute("message", "用户名["+name+"]已经被占用,请重新填写!");            request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);            return;        }        //3 若验证通过,把表单参数封装为一个Customer对象customer        Customer customer=new Customer(name,address,phone);        //4 调用CustomerDAO的save(Customer customer)执行保存操作        customerDAO.save(customer);        //5 重定向到success.jsp页面        response.sendRedirect("success.jsp");    }}
复制代码

4 单元测试层

 com.cuit.mvc.dao.test包:JdbcUtilsTest.java对CustomerServlet.java各个方法单元测试

复制代码
package com.cuit.mvc.test;import static org.junit.Assert.*;import java.util.List;import org.junit.Test;import com.cuit.mvc.dao.CustomerDAO;import com.cuit.mvc.dao.impl.CustomerDAOJdbcImpl;import com.cuit.mvc.model.CriteriaCustomer;import com.cuit.mvc.model.Customer;public class CustomerDAOJdbcImplTest {    private  CustomerDAO customerDAO=new CustomerDAOJdbcImpl();    @Test    public void getForListWithCriteriaCustomer(){        CriteriaCustomer cc=new CriteriaCustomer("Tom", null, null);        List<Customer> customers=customerDAO.getForListWithCriteriaCustomer(cc);        System.out.println(customers);    }    @Test    public void testGetAll() {        List<Customer> customers=customerDAO.getAll();        System.out.println(customers);    }    @Test    public void testSaveCustomer() {        Customer customer=new Customer("Baijing","Shanghai","134-2345-9086");        customerDAO.save(customer);    }    @Test    public void testGetInt() {        Customer cust=customerDAO.get(0);        System.out.println(cust);    }    @Test    public void testDelete() {        customerDAO.delete(2);    }    @Test    public void testGetCountWithName() {        long count=customerDAO.getCountWithName("Tom");        System.out.println(count);    }}
复制代码

5 视图显示页面层 

index.jsp:显示顾客信息,并支持回显

复制代码
<%@page import="com.cuit.mvc.model.Customer"%><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>My JSP 'index.jsp' starting page</title>      <script type="text/javascript" src="scripts/jquery.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">         <table>             <tr>               <td>CustomerName:</td>               <td><input type="text" name="name"/></td>             </tr>                           <tr>               <td>CustomerAddress:</td>               <td><input type="text" name="address"/></td>             </tr>                           <tr>               <td>CustomerPhone:</td>               <td><input type="text" name="phone"/></td>             </tr>                           <tr>               <td><input type="submit" value="Query"/></td>               <td><a href="newcustomer.jsp">Create New Customer</a></td>             </tr>         </table>      </form>      <br/><br/>      <%          List<Customer> customers=(List<Customer>)request.getAttribute("customers");          if(customers!=null && customers.size()>0){       %>       <hr>       <br/><br/>       <table border="1" cellpadding="10" cellspacing="0">            <tr>               <th>ID</th>               <th>CustomerName</th>               <th>CustomerAddress</th>               <th>CustomerPhone</th>               <th>Update/Delete</th>            </tr>             <%               for(Customer customer:customers){            %>            <tr>               <td class="id"><%=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="delete.do?id=<%=customer.getId() %>" class="delete">Delete</a>               </td>                </tr>               <%                }                %>       </table>       <%          }        %>  </body></html>
复制代码

error.jsp:异常或者报错页面跳转

复制代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>My JSP 'error.jsp' starting page</title>        <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="styles.css">    -->  </head>    <body>    <h4>对不起没有您请求的页面</h4>    <img style=" height:200px; width: 200; margin: 0 auto;" src="imgs/error.jpg"></img><br/><br>    <p style="font-size: 25px; color: red;">对不起访问失败!</p>      </body></html>
复制代码

newcustomer.jsp:添加顾客信息页面,支持回显,控制name不能重复

复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <%        Object mes=request.getAttribute("message");        if(mes!=null){           out.print("<br>");           out.print(mes);           out.print("<br>");           out.print("<br>");        }     %>    <h1>添加一条新的customer信息</h1>     <!--此处add.do依赖于CustomerServlet中的add方法名  -->     <form action="add.do">         <table>             <tr>               <td>CustomerName:</td>               <td><input type="text" name="name"                    value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"/></td>             </tr>                           <tr>               <td>CustomerAddress:</td>               <td><input type="text" name="address"                   value="<%=request.getParameter("address")==null?"":request.getParameter("address")%>"/></td>             </tr>                           <tr>               <td>CustomerPhone:</td>               <td><input type="text" name="phone"                    value="<%=request.getParameter("phone")==null?"":request.getParameter("phone")%>"/></td>             </tr>                           <tr>               <td colspan="2"><input type="submit" value="Submit"/></td>             </tr>         </table>      </form></body></html>
复制代码

success.jsp:添加新信息成功跳转页面

复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <h2>成功添加,保存成功!</h2><br/><br/>    <h2><a href="index.jsp">Back Index</a></h2></body></html>
复制代码

updatecustomer.jsp:更新信息页面,支持回显,回显显示的是name旧值

复制代码
<%@page import="com.cuit.mvc.model.Customer"%><%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>   <%        Object mes=request.getAttribute("message");        if(mes!=null){           out.print("<br>");           out.print(mes);           out.print("<br>");           out.print("<br>");        }        String id=null;        String name=null;        String oldname=null;        String address=null;        String phone=null;        Customer customer=(Customer)request.getAttribute("customer");        if(customer!=null){           id=customer.getId()+"";           address=customer.getAddress();           name=customer.getName();           oldname=customer.getName();           phone=customer.getPhone();        }else{           id=request.getParameter("id");           name=request.getParameter("oldname");           oldname=request.getParameter("oldname");           address=request.getParameter("address");           phone=request.getParameter("phone");        }     %>    <h1>更新一条新的customer信息</h1>     <!--此处add.do依赖于CustomerServlet中的add方法名  -->     <form action="update.do">         <input type="hidden" name="id" value="<%=customer.getId()%>"/>         <input type="hidden" name="oldname" value="<%=oldname%>"/>         <table>             <tr>               <td>CustomerName:</td>               <td><input type="text" name="name" value="<%=name%>"/></td>             </tr>                           <tr>               <td>CustomerAddress:</td>               <td><input type="text" name="address"  value="<%=address %>"/></td>             </tr>                           <tr>               <td>CustomerPhone:</td>               <td><input type="text" name="phone" value="<%=phone%>"/></td>             </tr>                           <tr>               <td colspan="2"><input type="submit" value="Submit"/></td>             </tr>         </table>      </form></body></html>
复制代码

3 顾客信息模糊查询设计与实现

1) 项目设计分析: 实现name,address,phone联合模糊查询

1、 调用CustomerDAO的getALl方法得到Customer集合

2、 把customer的集合放入request

3、 转发页面index.jsp(不能使用重定向)

4、 index.jsp页面循环遍历显示

2)项目源码实现

1 DAO数据操作

1
2
3
4
5
6
7
8
9
public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) {
    String sql="select * from customers where name like ? and address like ? "
            "and phone like ?";
    //修改了CriteriaCustomer的getter方法:使其返回字符串中有%%
    //若返回值为null返回%%,若不返回null则返回:"%"+字段本身的值+"%"
    //如上效果如:cc.getName()==null?%%:%+name+%
    System.out.println(sql);
    return getForList(sql,cc.getName(),cc.getAddress(),cc.getPhone());
}

2、servlet控制源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//模糊查询
private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    String name=request.getParameter("name");
    String address=request.getParameter("address");
    String phone=request.getParameter("phone");
    CriteriaCustomer cc=new CriteriaCustomer(name,address,phone);
    //1 调用CustomerDAO的getALl方法得到Customer集合
    //List<Customer> sustomers=customerDAO.getAll();获取所有信息列表
    List<Customer> customers=customerDAO.getForListWithCriteriaCustomer(cc);
    //2 把customer的集合放入request
    request.setAttribute("customers", customers);
    //3 转发页面index.jsp(不能使用重定向)
    request.getRequestDispatcher("/index.jsp").forward(request,response);
}

3、index页面显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<%
    List<Customer> customers=(List<Customer>)request.getAttribute("customers");
    if(customers!=null && customers.size()>0){
 %>
 <hr>
 <br/><br/>
 <table border="1" cellpadding="10" cellspacing="0">
      <tr>
         <th>ID</th>
         <th>CustomerName</th>
         <th>CustomerAddress</th>
         <th>CustomerPhone</th>
         <th>Update/Delete</th>
      </tr>
      <%
        for(Customer customer:customers){
      %>
      <tr>
         <td class="id"><%=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="delete.do?id=<%=customer.getId() %>" class="delete">Delete</a>
         </td>
         </tr>
         <%
          }
          %>
 </table>
 <%
    }
  %>

3)项目单元测试

1
2
3
4
5
6
@Test
public void getForListWithCriteriaCustomer(){
    CriteriaCustomer cc=new CriteriaCustomer("Tom"nullnull);
    List<Customer> customers=customerDAO.getForListWithCriteriaCustomer(cc);
    System.out.println(customers);
}

4)项目运行效果

4 顾客信息添加设计与实现

1) 项目设计分析:name唯一,新添加信息需要验证错误提示

1、获取表单参数:name、address、phone

2、 检验name是否被占用

3、若验证通过,把表单参数封装为一个Customer对象customer

4、调用CustomerDAO的save(Customer customer)执行保存操作

5、重定向到success.jsp页面

2)项目源码实现

1、DAO操作源码

1
2
3
4
5
@Override
public void save(Customer customer) {
    String sql="insert customers(name,address,phone) values(?,?,?)";
    update(sql, customer.getName(),customer.getAddress(),customer.getPhone());
}

2、servlet操作源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//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(String name)获取name在数据库中是否存在
long count=customerDAO.getCountWithName(name);
if(count>0){
//2.2 若返回值大于0,则相应newcustomer.jsp页面:①在此页面显示一个错误信息②此表单值可以回显
//     通过request.getAttribute("message")显示信息
//     通过value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"回显
    request.setAttribute("message""用户名["+name+"]已经被占用,请重新填写!");
    request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);
    return;
}
//3 若验证通过,把表单参数封装为一个Customer对象customer
Customer customer=new Customer(name,address,phone);
//4 调用CustomerDAO的save(Customer customer)执行保存操作
customerDAO.save(customer);
//5 重定向到success.jsp页面
response.sendRedirect("success.jsp");

3、 视图页面显示源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<body>
    <%
        Object mes=request.getAttribute("message");
        if(mes!=null){
           out.print("<br>");
           out.print(mes);
           out.print("<br>");
           out.print("<br>");
        }
     %>
    <h1>添加一条新的customer信息</h1>
     <!--此处add.do依赖于CustomerServlet中的add方法名  -->
     <form action="add.do">
         <table>
             <tr>
               <td>CustomerName:</td>
               <td><input type="text" name="name"
                    value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"/></td>
             </tr>
              
              <tr>
               <td>CustomerAddress:</td>
               <td><input type="text" name="address"
                   value="<%=request.getParameter("address")==null?"":request.getParameter("address")%>"/></td>
             </tr>
              
              <tr>
               <td>CustomerPhone:</td>
               <td><input type="text" name="phone"
                    value="<%=request.getParameter("phone")==null?"":request.getParameter("phone")%>"/></td>
             </tr>
              
              <tr>
               <td colspan="2"><input type="submit" value="Submit"/></td>
             </tr>
         </table>
      </form>
</body>

3)项目单元测试

1
2
3
4
5
@Test
public void testSaveCustomer() {
    Customer customer=new Customer("Baijing","Shanghai","134-2345-9086");
    customerDAO.save(customer);
}

4)项目运行效果

5 顾客信息更新设计与实现

1) 项目设计分析

1、 编辑操作:①获取请求参数id;②调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customer;③若验证通过,把表单参数封装为一个Customer对象customer;④ 调用CustomerDAO的update(Customer customer)执行更新操作;⑤重定向到query.do

2、更新操作:①获取请求参数:id,name,address,phone,oldname;②检验name是否被占用;③若验证通过,把表单参数封装为一个Customer对象customer;④调用CustomerDAO的update(Customer customer)执行更新操作;⑤重定向到query.do;

2)项目源码实现

1、DAO操作源码:

1
2
3
4
5
@Override
public void save(Customer customer) {
    String sql="insert customers(name,address,phone) values(?,?,?)";
    update(sql, customer.getName(),customer.getAddress(),customer.getPhone());
}

2、servlet操作源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    String forwordPath="/error.jsp";
    //1 获取请求参数id
    String idstr=request.getParameter("id");
    //2 调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customer
    try{
        Customer customer=customerDAO.get(Integer.parseInt(idstr));
        if(customer!=null){
            forwordPath="/updatecustomer.jsp";
            //3 将customer放在request中
            request.setAttribute("customer", customer);
        }
    }catch(Exception e){}
    //4 响应updatecustomer.jsp页面:转发
    request.getRequestDispatcher(forwordPath).forward(request, response);
}
private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    //1 获取请求参数:id,name,address,phone,oldname
    String id=request.getParameter("id");
    String name=request.getParameter("name");
    String oldname=request.getParameter("oldname");
    String address=request.getParameter("address");
    String phone=request.getParameter("phone");
    //2  检验name是否被占用
    //2.1  比较name和oldname是否相同,若相同name可用,oldname.equals(name)不如equalsIgnoreCase,数据库默认大小写一致的,而equals忽略大小写
    if(!oldname.equalsIgnoreCase(name)){
        //不相同,调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在
        long count=customerDAO.getCountWithName(name);
        //大于0, 响应updatecustomer.jsp页面:通过转发响应newcustomer.jsp
        if(count>0){
            // 通过request.getAttribute("message")显示信息,在页面上request.getAttribute("message")的方式显示
            // 表单据回显。address,phone显示提交的新值, name显示oldname,而不是新值
            request.setAttribute("message""用户名["+name+"]已经被占用,请重新填写!");
            // 方法结束
            request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response);
            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");
     
}

3、视图显示操作源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<body>
   <%
        Object mes=request.getAttribute("message");
        if(mes!=null){
           out.print("<br>");
           out.print(mes);
           out.print("<br>");
           out.print("<br>");
        }
        String id=null;
        String name=null;
        String oldname=null;
        String address=null;
        String phone=null;
        Customer customer=(Customer)request.getAttribute("customer");
        if(customer!=null){
           id=customer.getId()+"";
           address=customer.getAddress();
           name=customer.getName();
           oldname=customer.getName();
           phone=customer.getPhone();
        }else{
           id=request.getParameter("id");
           name=request.getParameter("oldname");
           oldname=request.getParameter("oldname");
           address=request.getParameter("address");
           phone=request.getParameter("phone");
        }
     %>
    <h1>更新一条新的customer信息</h1>
     <!--此处add.do依赖于CustomerServlet中的add方法名  -->
     <form action="update.do">
         <input type="hidden" name="id" value="<%=customer.getId()%>"/>
         <input type="hidden" name="oldname" value="<%=oldname%>"/>
         <table>
             <tr>
               <td>CustomerName:</td>
               <td><input type="text" name="name" value="<%=name%>"/></td>
             </tr>
              
              <tr>
               <td>CustomerAddress:</td>
               <td><input type="text" name="address"  value="<%=address %>"/></td>
             </tr>
              
              <tr>
               <td>CustomerPhone:</td>
               <td><input type="text" name="phone" value="<%=phone%>"/></td>
             </tr>
              
              <tr>
               <td colspan="2"><input type="submit" value="Submit"/></td>
             </tr>
         </table>
      </form>
</body>

3)项目单元测试

1
2
3
4
5
@Test
public void testSaveCustomer() {
    Customer customer=new Customer("Baijing","Shanghai","134-2345-9086");
    customerDAO.save(customer);
}

4)项目运行效果

6 顾客信息删除设计与实现

1) 项目设计分析

1、获取id的值

2、调用DAO的删除方法

3、执行提示是否删除

4、删除成功跳转刷新

2)项目源码实现

1、DAO源码:

1
2
3
4
5
@Override
public void delete(int id) {
    String sql="delete  from customers where id=?";
    update(sql, id);
}

2、servlet源码:

1
2
3
4
5
6
7
8
9
private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    String idstr=request.getParameter("id").trim();
    int id=0;
    try{
        id=Integer.parseInt(idstr);
        customerDAO.delete(id);
    }catch(Exception e){}
    response.sendRedirect("query.do");
}

3、页面显示源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script type="text/javascript" src="scripts/jquery.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>
<td>
      <a  href="edit.do?id=<%=customer.getId() %>">Update</a>
      <a href="delete.do?id=<%=customer.getId() %>" class="delete">Delete</a>
</td>

3)项目单元测试

1
2
3
4
@Test
public void testDelete() {
    customerDAO.delete(2);
}

4)项目运行效果

7 面向接口开发的数据源配置

倘若需要操作其他数据库或者xml数据源进行存储,该如何操作呢?下面以jdbc和xml进行设计

1 、不修改DAO底层代码前提下,创建工厂模式,利用tyep类型进行选择实例创建连接模式,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//单例工厂
public class CustomerDAOFactory {
     
    private Map<String,CustomerDAO> daos=new HashMap<String,CustomerDAO>();
 
    private static CustomerDAOFactory instance=new CustomerDAOFactory();
    public static CustomerDAOFactory getInstance(){
        return instance;
    }
    private  String type=null;
    public  void setType(String type) {
        this.type=type;
    }
    private CustomerDAOFactory() {
        daos.put("jdbc"new CustomerDAOJdbcImpl());
        daos.put("xml"new CustomerDAOXMLImpl());
    }
    public CustomerDAO getCustomerDAO(){
        return daos.get(type);
    }
}

2、type值放在switch.properties用于切换,如下是该文件的内容

1
2
#type=xml
type=jdbc

3、初始化servlet,创建InitServlet.java文件,并控制type值传递CustomerDAOFactory工厂用来切换数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class InitServlet extends HttpServlet {
     
    @Override
    public void init() throws ServletException {
        CustomerDAOFactory.getInstance().setType("jdbc");
        //读取类路径switch.properties文件
        InputStream in=getServletContext().getResourceAsStream("/WEB-INF/classes/switch.properties");
        Properties properties=new Properties();
        try {
            properties.load(in);
            //获取switch.properties的type值
            String type=properties.getProperty("type");
            //赋给了CustomerDAOFactory的type属性
            CustomerDAOFactory.getInstance().setType(type);
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4、配置web.xml文件,使InitServlet.java在项目启动时即运行

1
2
3
4
5
6
7
8
9
<servlet>
  <servlet-name>CustomerServlet</servlet-name>
  <servlet-class>com.cuit.mvc.servlet.CustomerServlet</servlet-class>
</servlet>
<servlet>
  <servlet-name>InitServlet</servlet-name>
  <servlet-class>com.cuit.mvc.servlet.InitServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

五、顾客管理项目完整源码

 本项目完整源码:(点击下载  访问密码 16cf)

六、顾客管理项目技术总结

1 Tomcat目录结构图

2 Tomcat配置,MyEclipse2015默认集成了,不需要配置

3 web程序结构图

4 Servlet简介

5 servlet运行交互图

6 servlet运行原理

7 jsp运行原理

8 jsp的9大隐含对象

9 jsp注释与声明

10 jsp和属性相关的方法

11 页面请求重定向与请求转发

12 page指令

12 errorPage和isErrorPage

13 关于中文乱码的解决方案

 14 MVC简介

15 MVC原理图

16 多页面向单个servlet发送请求控制:方法1

17 多页面向单个servlet发送请求控制:方法2

18 更新操作原理示意图

19 查询设计思路

20 MVC案例需求设计

21 jsp页面请求遍历数据

22 修改更新设计思路

23 面向接口编程

24 表单请求和回显图示

0 0
原创粉丝点击