zoukankan      html  css  js  c++  java
  • 【JAVA】基于MVC架构Java技术荟萃案例演练

    基于JAVA-MVC技术的顾客管理项目案例总结

    作者 白宁超

    2016年6月9日22:47:08

    阅读前瞻:本文源于对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、监听、权限管理、文件上传与下载等后续文章继续完善优化。

    三、数据库创建阶段

    # 创建数据库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>
    View Code

    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();
        }
    
    }
    View Code

     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+"]";
        }
    }
    View Code

     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);
            }
        }
    }
    View Code

    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);
        
    }
    View Code

    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());
        }
    
    }
    View Code

    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");
        }
    
    }
    View Code

    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);
        }
    
    }
    View Code

    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>
    View Code

    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;  200; margin: 0 auto;" src="imgs/error.jpg"></img><br/><br>
        <p style="font-size: 25px; color: red;">对不起访问失败!</p>
        
      </body>
    </html>
    View Code

    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>
    View Code

    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>
    View Code

    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>
    View Code

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

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

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

    2、 把customer的集合放入request

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

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

    2)项目源码实现

    1 DAO数据操作

    	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控制源码:

    	//模糊查询
    	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页面显示

          <%
              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)项目单元测试

    	@Test
    	public void getForListWithCriteriaCustomer(){
    		CriteriaCustomer cc=new CriteriaCustomer("Tom", null, null);
    		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操作源码

    	@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 获取表单参数: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、 视图页面显示源码

    <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)项目单元测试

    	@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操作源码:

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

    2、servlet操作源码

    	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、视图显示操作源码

    <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)项目单元测试

    	@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源码:

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

    2、servlet源码:

    	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、页面显示源码:

      <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)项目单元测试

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

    4)项目运行效果

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

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

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

    //单例工厂
    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用于切换,如下是该文件的内容

    #type=xml
    type=jdbc
    

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

    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在项目启动时即运行

      <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 表单请求和回显图示

  • 相关阅读:
    java基础篇 之 非静态内部类
    java基础篇 之 super关键字的理解
    Spring Cloud学习 之 Spring Cloud Ribbon(负载均衡策略)
    java基础篇 之 接口
    java基础篇 之 构造器内部的多态行为
    Spring Cloud学习 之 Spring Cloud Ribbon(负载均衡器源码分析)
    Spring Cloud学习 之 Spring Cloud Ribbon(执行流程源码分析)
    Spring Cloud 学习 之 Spring Cloud Ribbon(基础知识铺垫)
    计算机网络基础
    Python异常处理
  • 原文地址:https://www.cnblogs.com/baiboy/p/javaweb.html
Copyright © 2011-2022 走看看