要求如下:
1、准备工作
1.搭建环境
1.1 导开发包
mysql驱动
beanUtils
log4j开发
jstl开发包
1.2 创建组织程序的包
cn.itcast.domain
cn.itcast.dao
cn.itcast.dao.impl
cn.itcast.service
cn.itcast.service.impl
cn.itcast.web.controller
cn.itcast.web.UI
cn.itcast.utils
cn.itcast.exception
junit.test
WEB-INF/jsp
1.3 为应用创建相应库和表
create database customer character set utf8 collate utf8_general_ci;
use day14_customer;
create table customer
(
id varchar(40) primary key,
name varchar(40) not null,
gender varchar(4) not null,
birthday date,
cellphone varchar(20),
email varchar(40),
preference varchar(255),
type varchar(100) not null,
description varchar(255)
);
2.建实体
3.写dao
4.写service
5.写web
两个配置文件 db.properties
和 dao.properties
,前者是连接mysql的信息,后者是通过读取本地的.properties文件来获取我们需要实例化的类,然后通过反射来生成对象
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/customer
username=root
password=root
dao.properties
CustomerDao=cn.itcast.dao.impl.CustomerDaoImpl
分层架构的代码是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→【业务逻辑层(service、service.impl)】→【表现层(web.controller、web.UI、web.filter、web.listener)】→【工具类(util)】→测试类的顺序进行编写的。
2、实体类 Customer
package cn.itcast.domain;
import java.util.Date;
public class Customer {
private String id;
private String name;
private String gender;
private Date birthday;
private String cellphone;
private String email;
private String preference;
private String type;
private String description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getCellphone() {
return cellphone;
}
public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPreference() {
return preference;
}
public void setPreference(String preference) {
this.preference = preference;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
2、写实体的dao的实现 CustomerDaoImpl
和接口 CustomerDao
(数据访问层)
在开发数据访问层时,由于要编写得到mysql数据库链接和释放资源这些性质的操作,所以应该把他们放在一个工具类JdbcUtils中。
JdbcUtils
package cn.itcast.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtils {
private static Properties prop = new Properties();
static {
try {
prop.load(JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"));
Class.forName(prop.getProperty("driver"));
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws Exception {
return DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("username"), prop.getProperty("password"));
}
public static void release(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close(); //throw new
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
st = null;
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
CustomerDaoImpl
package cn.itcast.dao.impl;
import cn.itcast.domain.Customer;
import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class CustomerDaoImpl implements cn.itcast.dao.CustomerDao {
@Override
public void add(Customer customer) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into customer(id,name,gender,birthday,cellphone,email,preference,type,description) values(?,?,?,?,?,?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, customer.getId());
ps.setString(2, customer.getName());
ps.setString(3, customer.getGender());
ps.setDate(4, new java.sql.Date(customer.getBirthday().getTime()));
ps.setString(5, customer.getCellphone());
ps.setString(6, customer.getEmail());
ps.setString(7, customer.getPreference());
ps.setString(8, customer.getType());
ps.setString(9, customer.getDescription());
ps.executeUpdate();
} catch (Exception e) {
throw new DaoException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
@Override
public void update(Customer customer) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "update customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=? where id=?";
ps = conn.prepareStatement(sql);
ps.setString(1, customer.getId());
ps.setString(2, customer.getName());
ps.setString(3, customer.getGender());
ps.setDate(4, new java.sql.Date(customer.getBirthday().getTime()));
ps.setString(5, customer.getCellphone());
ps.setString(6, customer.getEmail());
ps.setString(7, customer.getPreference());
ps.setString(8, customer.getType());
ps.setString(9, customer.getDescription());
ps.executeUpdate();
} catch (Exception e) {
throw new DaoException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
@Override
public void delete(String id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "delete from customer where id=?";
ps = conn.prepareStatement(sql);
ps.setString(1, id);
ps.executeUpdate();
} catch (Exception e) {
throw new DaoException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
@Override
public Customer find(String id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "select * from customer where id=?";
ps = conn.prepareStatement(sql);
ps.setString(1, id);
rs = ps.executeQuery();
if(rs.next()){
Customer customer = new Customer();
customer.setBirthday(rs.getDate("birthday"));
customer.setCellphone(rs.getString("cellphone"));
customer.setDescription(rs.getString("description"));
customer.setEmail(rs.getString("email"));
customer.setGender(rs.getString("gender"));
customer.setId(rs.getString("id"));
customer.setName(rs.getString("name"));
customer.setPreference(rs.getString("preference"));
customer.setType(rs.getString("type"));
return customer;
}
return null;
} catch (Exception e) {
throw new DaoException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
@Override
public List getAll() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "select * from customer";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
List list = new ArrayList();
while(rs.next()){
Customer customer = new Customer();
customer.setBirthday(rs.getDate("birthday"));
customer.setCellphone(rs.getString("cellphone"));
customer.setDescription(rs.getString("description"));
customer.setEmail(rs.getString("email"));
customer.setGender(rs.getString("gender"));
customer.setId(rs.getString("id"));
customer.setName(rs.getString("name"));
customer.setPreference(rs.getString("preference"));
customer.setType(rs.getString("type"));
list.add(customer);
}
return list;
} catch (Exception e) {
throw new DaoException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
}
CustomerDao
package cn.itcast.dao;
import cn.itcast.domain.Customer;
import java.util.List;
public interface CustomerDao {
void add(Customer customer);
void update(Customer customer);
void delete(String id);
Customer find(String id);
List getAll();
}
对于接口中的方法定义,这个只能是根据具体的业务来分析需要定义哪些方法了,但是无论是多么复杂的业务,都离不开基本的CRUD(增删改查)操作,Dao层是直接和数据库交互的,所以Dao层的接口一般都会有增删改查这四种操作的相关方法。
接着应该编写CustomerDao接口的实现类——CustomerDaoImpl,其里面一般都会有增删改查这四种操作的相关方法,增删改查时,难免会发生异常,所以在实际开发中,最好每一个层都编写一个自定义异常。
DaoException
package cn.itcast.exception;
public class DaoException extends RuntimeException {
public DaoException() {
}
public DaoException(String message) {
super(message);
}
public DaoException(String message, Throwable cause) {
super(message, cause);
}
public DaoException(Throwable cause) {
super(cause);
}
}
3、引进了工厂模式
DaoFactory
package cn.itcast.factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class DaoFactory {
private Properties prop = new Properties();
private DaoFactory() {
InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
try {
prop.load(in);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static DaoFactory instance = new DaoFactory();
public static DaoFactory getInstance() {
return instance;
}
/*如果将来产生多个dao,就不能写死(泛型)
*比如当调用createDao方法时,会传一个,CustomerDao的接口,
* 然后根据名称解读配置文件dao.properties加载CustomerDao的实现类,new出对象返回
*/
public T createDao(Class clazz) {
String name = clazz.getSimpleName();//得到接口名称
String className = prop.getProperty(name);
try {
T dao = (T) Class.forName(className).newInstance();
return dao;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/customer
username=root
password=root
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:orcl
#username=system
#password=itcast
4、开发service层(service层对web层提供所有的业务服务)
BusinessServiceImpl
package cn.itcast.service.impl;
import cn.itcast.dao.CustomerDao;
import cn.itcast.dao.impl.CustomerDaoImpl;
import cn.itcast.domain.Customer;
import cn.itcast.factory.DaoFactory;
import cn.itcast.service.BusinessService;
import java.util.List;
public class BusinessServiceImpl implements BusinessService {
private CustomerDao dao = DaoFactory.getInstance().createDao(CustomerDao.class);
@Override
public void addCustomer(Customer customer) {
dao.add(customer);
}
@Override
public void update(Customer customer) {
dao.update(customer);
}
@Override
public void delete(String id) {
dao.delete(id);
}
@Override
public Customer findCustomer(String id) {
return dao.find(id);
}
@Override
public List getAllCustomer() {
return dao.getAll();
}
}
BusinessService
package cn.itcast.service;
import cn.itcast.domain.Customer;
import java.util.List;
public interface BusinessService {
void addCustomer(Customer customer);
void update(Customer customer);
void delete(String id);
Customer findCustomer(String id);
List getAllCustomer();
}
5、开发web层
在一个项目中,开发Web层是最麻烦的。此客户关系管理系统的首页index.jsp,我们是采用分帧的方式来设计的,index.jsp代码如下:
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
首页
接着我们创建head.jsp页面,head.jsp代码如下:
head.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
首页
客户关系管理系统
添加客户
查看客户
开发添加客户的功能——创建一个WebUtils工具类,该工具类的功能就是封装客户端提交的表单数据到Customer对象中。
WebUtils
package cn.itcast.utils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
public class WebUtils {
public static T request2Bean(HttpServletRequest request, Class beanClass) {
try {
T bean = beanClass.newInstance();
//得到request里面所有数据
Map map = request.getParameterMap();
ConvertUtils.register(new Converter() {
public Object convert(Class Type, Object value) {
if (value == null) {
return null;
}
String str = (String) value;
if (str.trim().equals("")) {
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}, Date.class);
BeanUtils.populate(bean, map);//map里的数据填充到bean里去
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//产生唯一ID
public static String genarateID() {
return UUID.randomUUID().toString();
}
}
接下来写一个servlet,该servlet既用来给用户提供一个添加客户界面,又用来接收表单的添加客户请求,并处理用户的添加请求。
AddCustomerServlet
package cn.itcast.web.controller;
import cn.itcast.domain.Customer;
import cn.itcast.service.BusinessService;
import cn.itcast.service.impl.BusinessServiceImpl;
import cn.itcast.utils.Globals;
import cn.itcast.utils.WebUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "AddCustomerServlet", urlPatterns = "/servlet/AddCustomerServlet")
public class AddCustomerServlet extends HttpServlet {
//给用户提供一个添加界面
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("genders", Globals.genders);
request.setAttribute("preferences", Globals.preferences);
request.setAttribute("types", Globals.types);
request.getRequestDispatcher("/WEB-INF/jsp/addcustomer.jsp").forward(request, response);
}
//处理用户的添加请求
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
request.setCharacterEncoding("UTF-8");
//默认表单已经校验,把数据封装到Customer对象中
Customer customer = WebUtils.request2Bean(request, Customer.class);
customer.setId(WebUtils.genarateID());
BusinessService service = new BusinessServiceImpl();
service.addCustomer(customer);
request.setAttribute("message", "添加成功!");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "添加失败!");
}
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
在实际开发中,页面到底输出几个性别,不是在页面中显示的,而是由一个程序维护的,这个程序有几个性别,页面中就输出几个性别。也就是说客户性别、爱好、客户类型等输入选项在数据库里面都有各自对应的表,我们要从数据库里面读取出来并显示在页面中。我们也不必搞得这么麻烦,可编写一个java类来模拟。
Globals
package cn.itcast.utils;
public class Globals {
public static String genders[] = {"男", "女"};
public static String preferences[] = {"唱歌", "跳舞", "蹦极", "探险", "游泳", "篮球", "足球"};
public static String types[] = {"vip", "重点客户", "普通客户"};
}
添加客户界面addcustomer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
添加客户
创建全局消息显示页面message.jsp,代码如下:
message.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
全局消息显示界面
${message}
查看客户ListCustomerServlet
package cn.itcast.web.controller;
import cn.itcast.service.BusinessService;
import cn.itcast.service.impl.BusinessServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet(name = "ListCustomerServlet", urlPatterns = "/servlet/ListCustomerServlet")
public class ListCustomerServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
BusinessService service = new BusinessServiceImpl();
List list = service.getAllCustomer();
request.setAttribute("list", list);
request.getRequestDispatcher("/WEB-INF/jsp/listcustomer.jsp").forward(request,response);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "查看客户失败");
request.getRequestDispatcher("/message.jsp").forward(request,response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
列出所有客户显示listcustomer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
列出所有客户
客户姓名
性别
生日
手机
邮箱
爱好
类型
备注
操作
${c.name }
${c.gender }
${c.birthday }
${c.cellphone }
${c.email }
${c.preference }
${c.type }
${c.description }
修改
删除
至此,查看客户功能就完成了一小半,还有很多细节没实现。
源代码:https://github.com/yvettee36/Customer.git
连下篇:http://www.jianshu.com/p/3163ee51a120