基于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;}@Overridepublic 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.jarprivate 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封装了查询条件,返回查询条件的listpublic 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());}@Overridepublic List<Customer> getAll() {String sql="select * from customers";return getForList(sql);}@Overridepublic void save(Customer customer) {String sql="insert customers(name,address,phone) values(?,?,?)";update(sql, customer.getName(),customer.getAddress(),customer.getPhone());}@Overridepublic Customer get(int id) {String sql="select * from customers where id=?";return get(sql,id);}@Overridepublic void delete(int id) {String sql="delete  from customers where id=?";update(sql, id);}@Overridepublic long getCountWithName(String name) {String sql="select count(id) from customers where name=?";return getForValue(sql, name);}@Overridepublic 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;}}*/@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//1 获取servlet路径 诸如:/add.doString 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 获取请求参数idString idstr=request.getParameter("id");//2 调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customertry{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,oldnameString 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.jspif(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对象customerCustomer customer=new Customer(name,address,phone);customer.setId(Integer.parseInt(id));//4 调用CustomerDAO的update(Customer customer)执行更新操作
        customerDAO.update(customer);//5 重定向到query.doresponse.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的集合放入requestrequest.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,phoneString 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对象customerCustomer 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();@Testpublic void getForListWithCriteriaCustomer(){CriteriaCustomer cc=new CriteriaCustomer("Tom", null, null);List<Customer> customers=customerDAO.getForListWithCriteriaCustomer(cc);System.out.println(customers);}@Testpublic void testGetAll() {List<Customer> customers=customerDAO.getAll();System.out.println(customers);}@Testpublic void testSaveCustomer() {Customer customer=new Customer("Baijing","Shanghai","134-2345-9086");customerDAO.save(customer);}@Testpublic void testGetInt() {Customer cust=customerDAO.get(0);System.out.println(cust);}@Testpublic void testDelete() {customerDAO.delete(2);}@Testpublic 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; width: 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的集合放入requestrequest.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)项目单元测试

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

@Overridepublic 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,phoneString 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对象customerCustomer 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)项目单元测试

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

@Overridepublic 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 获取请求参数idString idstr=request.getParameter("id");//2 调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customertry{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,oldnameString 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.jspif(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对象customerCustomer customer=new Customer(name,address,phone);customer.setId(Integer.parseInt(id));//4 调用CustomerDAO的update(Customer customer)执行更新操作customerDAO.update(customer);//5 重定向到query.doresponse.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)项目单元测试

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

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

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

转载于:https://my.oschina.net/u/3579120/blog/1539213

【JAVA】基于MVC架构Java技术荟萃案例演练相关推荐

  1. 视频教程-Java微服务架构-Java

    Java微服务架构 十余年计算机技术领域从业经验,在中国电信.盛大游戏等多家五百强企业任职技术开发指导顾问,国内IT技术发展奠基人之一. 杨千锋 ¥208.00 立即订阅 扫码下载「CSDN程序员学院 ...

  2. H5智能内核-基于MVC架构的全新Zoomla!逐浪CMS2 x3.8发布

    点此进入下载https://www.z01.com/down/3067.shtml [高速免费下载通道↓] 详细介绍: 北京时间2016年11月16日,国内领先的WEB与移动内核软件研发厂商-Zoom ...

  3. 基于MVC设计(Java Web程序)----图书馆系统

    文章目录 基于MVC设计----图书馆系统 整体项目运行截图 登录设计(MVC设计模式) 登录功能源代码 总结 基于MVC设计----图书馆系统 这一学期学习了JavaWeb开发, 课程结束时老师给的 ...

  4. Java学习-MVC架构模式

    目录 1 传统方式处理业务的缺点 2 MVC架构模式理论基础 4 MVC架构模式如何设计 4.1 设计JDBC工具类的封装 4.2 创建封装数据的对象 4.3 设计Dao模式 4.4 业务逻辑编写 4 ...

  5. 基于MVC架构的百姓物流管理系统

    目 录 摘要 Ⅰ ABSTRACT III 1 绪 论 1 1.1研究背景 1 1.2国内外现状 1 1.3研究意义 1 2 系统相关技术 3 2.1系统开发平台 3 2.2 MVC体系结构 3 2. ...

  6. HEVC新技术(一):基于MVC的AMVP技术

    基于MVC(Motion Vector Competition)的AMVP(Advanced Motion Vector Prediction) 技术是HEVC采用的新技术之一. 所谓AMVP,就是通 ...

  7. qt基于MVC架构的设计

    什么是MVC架构? MVC是模型(Model).视图(View).控制器(Controller)的简写, 是一种架构设计模式, 是一种设计理念.是为了达到分层设计的目的,从而使代码解耦,便于维护和代码 ...

  8. 赵聪慧 java,基于Instrumentation的JAVA代码暖替换

    基于Instrumentation的JAVA代码热替换 理类用来获取 Instrumentation 实例package com.codeconch.util; import java.lang.in ...

  9. java 基于口令加密算法,Java安全编程:基于口令加密(PBE)

    安全 PBE 在之前的文章中曾讲到过DES加密算法,类似这种加密算法都有一个密钥,密钥的长度决定了加密的安全性,但是这种密钥比较难记忆,是需要存储的. PBE算法是一种基于口令的加密算法,它并不是构建 ...

最新文章

  1. Response.Redirect:无法在发送 HTTP 标头之后进行重定向
  2. [导入]XML for Analysis(XMLA)开发详解-(3)各版本的SQL Server及Windows下配置XMLA over HTTP访问SASS(OLAP)的文档合集...
  3. JavaScript中getter/setter的实现
  4. 吴恩达深度学习课程deeplearning.ai课程作业:Class 4 Week 4 Face Recognition for the Happy House
  5. [云炬创业学笔记]第一章创业是什么测试12
  6. php 模板制作教程,Destoon模板制作简明教程_PHP教程
  7. 管理处理器的亲和性(affinity)
  8. 背景提取算法——帧间差分法、背景差分法、ViBe算法、ViBe+算法
  9. Java技术——你真的了解String类的intern()方法吗
  10. java中的final关键字(2013-10-11-163 写的日志迁移
  11. matlab 遗传算法 等式约束,关于MATLAB遗传算法工具箱不等式约束
  12. MyBatis #{ } ${ }
  13. 浅析bin,lib,src的区别
  14. IP种子——网络安全的重要组成部分
  15. 第四方支付跟第三方支付的区别,支付源码有什么用
  16. tcpdump进行IP抓包
  17. 属于程序员的“高考”考题,我估计没准还有很多人没有看过(建议不要收藏)
  18. 知乎高赞:电气工程专业学生的最好归宿在哪里?
  19. Intel无线网卡linux,Deepin 15.8/Ubuntu 18.04用intel无线网卡9260ac速度跑不满的解决
  20. 0成本截流的三种方法,挣钱从引流开始

热门文章

  1. 网络面试100问(八)
  2. android模拟器网络配置
  3. 代理模式--为别人做嫁衣
  4. #基于ROS的编队控制
  5. origin软件画流程图_Origin十大绘图技巧 轻松提高作图效率
  6. 云呐|动环监控网管软件有哪些
  7. Vue2【尚硅谷--天禹老师】:Vue核心
  8. POJ 1149 PIGS 最大流建模
  9. Linux集群间免密登录
  10. 无中生有之突击NOIP(4)--搜索