基于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"></property>
<property name="initialPoolSize"></property>
<property name="minPoolSize"></property>
<property name="maxPoolSize"></property> <!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements"></property>
<property name="maxStatementsPerConnection"></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>){
if(typeArgs[] instanceof Class) clazz=(Class<T>)typeArgs[];
}
}
}
/**
* 返回某一个字段的值,或者返回数据表中有多少条记录等。
* @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();
//去除/和.do得到类似于add这样字符串
String methodName=servletPath.substring(,servletPath.length()-);
//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>){
// 通过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=;
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>){
//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();
System.out.println(cust);
} @Test
public void testDelete() {
customerDAO.delete();
} @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()>){
%>
<hr>
<br/><br/>
<table border="" cellpadding="" cellspacing="">
<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="">
<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=""><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=""><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数据操作

	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】基于MVC架构Java技术荟萃案例演练的更多相关文章

  1. Java ---理解MVC架构

    之间的文章,我们主要是介绍了jsp的相关语法操作,我们可以通过请求某个jsp页面,然后由相对应的servlet实例给我们返回html页面.但是在实际的项目中,我们很少会直接的请求某个页面,一般都是请求 ...

  2. JavaWeb:基于MVC设计模式的一个小案例(一)

    (未经允许,请勿转载,谢谢.) 本案例的处理过程: 客户端发送一个请求给服务器,服务器把这个请求给Servlet,Servlet 获取请求信息,根据请求信息的情况去调用 model (在这里是一个普通 ...

  3. MVC架构模式详细说明

    一.简介: 架构模式是一个通用的.可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题.架构模式与软件设计模式类似,但具有更广泛的范围. 模型-视图-控制器模式,也称为MVC模式(Mod ...

  4. 【深入Cocos2d-x】使用MVC架构搭建游戏Four

    喜欢Four这个项目,就赶快在GitHub上Star这个项目吧! 喜欢我的文章,来微博关注我吧:王选易在学C艹 点我下载 项目起源 项目Logo: 下面是该游戏的项目地址,各位想参考源代码的同学可以到 ...

  5. SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

    熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...

  6. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  7. JAVA 架构和技术框架百科

    YApi 是高效.易用.功能强大的 api 管理平台,旨在为开发.产品.测试人员提供更优雅的接口管理服务.可以帮助开发者轻松创建.发布.维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只 ...

  8. java 学习写架构必会几大技术点

    java 学习写架构必会几大技术点 关于学习架构,必须会的几点技术 1. java反射技术 2. xml文件处理 3. properties属性文件处理 4. 线程安全机制 5. annocation ...

  9. java MVC架构-spring mvc,struct2(理解)

    MVC架构实现基础: 基于filter或者servlet实现请求地址分析,如果需要控制类处理请求,则调用相应的控制类.调用控制类时,根据配置文件初始化控制类相关的参数.数据库连接可持久化存在.控制类处 ...

随机推荐

  1. https://oj.leetcode.com/problems/majority-element/

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  2. CharSequence cannot be resolved. It is indirectly referenced from required .class files

    最近在写项目的时候发现会莫名其妙的出现这个编译错误,网上查了下发现自己安装的是JDK1.8造成的 原因:JDK1.8版本现在还不稳定 解决方法:卸载JDK1.8,安装JDK1.7 扩展:发现安装JDK ...

  3. pagination 分页

    <!DOCTYPE html> <html> <head> <title>pagination</title> <style type ...

  4. java基本类型的默认值及其取值范围

  5. LINUX 下时间转换为秒数

    linux下时间是从1970.1.1开始算的秒数 //转来自网址 http://blog.csdn.net/wind19/article/details/6579495 $ dateTue Feb 3 ...

  6. .NET程序反汇编JustDecompile 开源

    JustDecompile是Telerik公司推出一个免费的.net反编译工具,支持插件,与Visual Studio 集成,能够创建Visual Studio project文件.JustDecom ...

  7. 【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件

    目录 概述 功能 如何使用 参考帮助 概述 源代码主要包含三个项目,BMap.NET.BMap.NET.WindowsForm以及BMap.NET.WinformDemo. BMap.NET 对百度地 ...

  8. MySQL 半同步复制+MMM架构

    200 ? "200px" : this.width)!important;} --> 介绍 上篇文章介绍了MMM架构的实现方法,但是上篇文章的MMM方案的复制是异步复制,异 ...

  9. Win8 Metro动态加载内容框架

    制作背景 为了参加ImagineCup 2013 世界公民类比赛,我们设计制作了一个可动态扩展的幼教类App.这个App需要能动态加载内容,内容包括带动画可交互的电子书,动画,视频,游戏. 技术支持 ...

  10. 自动化安装SQL Server+SP就那么简单

    随着业务.企业规模的日益壮大,DB的数量也在不断增多,配置一台新增DB,从服务器的参数配置,磁盘阵列规划,DB安装部署,DB参数调优等等一列步骤下来,手工操作的效率变得越来越低,因为我负责的数据库近些 ...