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下
root
root
com.mysql.jdbc.Driver
jdbc:mysql:///test
5
10
10
50
20
5
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 classJdbcUtils {/**
* 释放Connection链接
* @param connection*/
public static voidreleaseConnection(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 staticConnection getConnection() throws SQLException{returndataSource.getConnection();
}
}
View Code
com.cuit.mvc.model包:Customer.java实体类的封装
package com.cuit.mvc.model;public classCustomer {private intid;privateString name;privateString address;privateString phone;public intgetId() {returnid;
}publicCustomer() {
}publicCustomer(String name, String address, String phone) {this.name =name;this.address =address;this.phone =phone;
}public void setId(intid) {this.id =id;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicString getAddress() {returnaddress;
}public voidsetAddress(String address) {this.address =address;
}publicString getPhone() {returnphone;
}public voidsetPhone(String phone) {this.phone =phone;
}
@OverridepublicString 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 :当前DAO处理实体的类型是什么
* @author 白宁超http://www.cnblogs.com/baiboy/**/
public class DAO{//此步骤前需要/lib加入commons-dbutils-xx.jar
private QueryRunner queryRunner=newQueryRunner();private Classclazz;publicDAO(){//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)typeArgs[0];
}
}
}/**
* 返回某一个字段的值,或者返回数据表中有多少条记录等。
* @param sql:SQL语句
* @param args:填充SQL语句的占位符
* @return*/
public E getForValue(String sql,Object ... args) {
Connection connection=null;try{
connection=JdbcUtils.getConnection();return (E) queryRunner.query(connection,sql,new ScalarHandler(),args);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}return null;
}/**
* 返回T所对应的List
* @param sql:SQL语句
* @param args:填充SQL语句的占位符
* @return*/
public ListgetForList(String sql,Object ... args){
Connection connection=null;try{
connection&#61;JdbcUtils.getConnection();return queryRunner.query(connection,sql,new BeanListHandler<>(clazz),args);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}return null;
}/**
* 返回对应T的一个实体类对象
* &#64;param sql&#xff1a;SQL语句
* &#64;param args&#xff1a;填充SQL语句的占位符
* &#64;return*/
public T get(String sql,Object ... args){
Connection connection&#61;null;try{
connection&#61;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操作
* &#64;param sql&#xff1a;SQL语句
* &#64;param args&#xff1a;填充SQL语句的占位符*/
public voidupdate(String sql,Object ... args){
Connection connection&#61;null;try{
connection&#61;JdbcUtils.getConnection();
queryRunner.update(connection,sql,args);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}
}
}
View Code
CustomerDAO源码&#xff1a;
package com.cuit.mvc.dao;
import java.util.List;
import com.cuit.mvc.model.CriteriaCustomer;
import com.cuit.mvc.model.Customer;public interfaceCustomerDAO {public List getAll();//获取Customer列表信息
public void save(Customer customer);//对Customer的添加,通过CTRL&#43;T转到定义
public void update(Customer customer);//对Customer的更新,通过CTRL&#43;T转到定义
public Customer get(int id);//获取Customer实体
public void delete(int id);//根据id进行删除
public long getCountWithName(String name);//返回name相等的记录数//cc封装了查询条件&#xff0c;返回查询条件的list
public ListgetForListWithCriteriaCustomer(CriteriaCustomer cc);
}
View Code
com.cuit.mvc.dao.impl包&#xff1a;CustomerDAOJdbcImpl.java&#xff1a;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 DAOimplements CustomerDAO{public ListgetForListWithCriteriaCustomer(CriteriaCustomer cc) {
String sql&#61;"select * from customers where name like ? and address like ?"
&#43; "and phone like ?";//修改了CriteriaCustomer的getter方法:使其返回字符串中有%%//若返回值为null返回%%&#xff0c;若不返回null则返回&#xff1a;"%"&#43;字段本身的值&#43;"%"//如上效果如&#xff1a;cc.getName()&#61;&#61;null&#xff1f;%%:%&#43;name&#43;%
System.out.println(sql);returngetForList(sql,cc.getName(),cc.getAddress(),cc.getPhone());
}
&#64;Overridepublic ListgetAll() {
String sql&#61;"select * from customers";returngetForList(sql);
}
&#64;Overridepublic voidsave(Customer customer) {
String sql&#61;"insert customers(name,address,phone) values(?,?,?)";
update(sql, customer.getName(),customer.getAddress(),customer.getPhone());
}
&#64;Overridepublic Customer get(intid) {
String sql&#61;"select * from customers where id&#61;?";return get(sql,id);
}
&#64;Overridepublic void delete(intid) {
String sql&#61;"delete from customers where id&#61;?";
update(sql, id);
}
&#64;Overridepublic longgetCountWithName(String name) {
String sql&#61;"select count(id) from customers where name&#61;?";returngetForValue(sql, name);
}
&#64;Overridepublic voidupdate(Customer customer) {
String sql&#61;"update customers set name&#61;?,address&#61;?,phone&#61;? where id&#61;?";
update(sql,customer.getName(),customer.getAddress(),customer.getPhone(),customer.getId());
}
}
View Code
3 业务逻辑层
com.cuit.mvc.dao.servlet包&#xff1a;CustomerServlet.java对CustomerDAO公共方法具体实现&#xff0c;以及页面显示的控制
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 classCustomerServlet extends HttpServlet {//private CustomerDAO customerDAO&#61;new CustomerDAOJdbcImpl();//private CustomerDAO customerDAO&#61;new CustomerDAOXMLImpl();
private CustomerDAO customerDAO&#61;CustomerDAOFactory.getInstance().getCustomerDAO();public voiddoGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}/*public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method&#61;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;
}
}*/&#64;Overrideprotected voiddoPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {//1 获取servlet路径 诸如&#xff1a;/add.do
String servletPath&#61;req.getServletPath().substring(1);//去除/和.do得到类似于add这样字符串
String methodName&#61;servletPath.substring(0,servletPath.length()-3);//System.out.println(methodName);
try{//利用反射获取获取methodName对应的方法
Method method &#61; getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);//利用反射获取方法
method.invoke(this, req,resp);
}catch(Exception e) {//出错时候响应出来
resp.sendRedirect("error.jsp");
}
}private voidedit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String forwordPath&#61;"/error.jsp";//1 获取请求参数id
String idstr&#61;request.getParameter("id");//2 调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customer
try{
Customer customer&#61;customerDAO.get(Integer.parseInt(idstr));if(customer!&#61;null){
forwordPath&#61;"/updatecustomer.jsp";//3 将customer放在request中
request.setAttribute("customer", customer);
}
}catch(Exception e){}//4 响应updatecustomer.jsp页面&#xff1a;转发
request.getRequestDispatcher(forwordPath).forward(request, response);
}private voidupdate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//1 获取请求参数:id,name,address,phone,oldname
String id&#61;request.getParameter("id");
String name&#61;request.getParameter("name");
String oldname&#61;request.getParameter("oldname");
String address&#61;request.getParameter("address");
String phone&#61;request.getParameter("phone");//2 检验name是否被占用//2.1 比较name和oldname是否相同&#xff0c;若相同name可用&#xff0c;oldname.equals(name)不如equalsIgnoreCase&#xff0c;数据库默认大小写一致的&#xff0c;而equals忽略大小写
if(!oldname.equalsIgnoreCase(name)){//不相同&#xff0c;调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在
long count&#61;customerDAO.getCountWithName(name);//大于0&#xff0c; 响应updatecustomer.jsp页面&#xff1a;通过转发响应newcustomer.jsp
if(count>0){//通过request.getAttribute("message")显示信息&#xff0c;在页面上request.getAttribute("message")的方式显示//表单据回显。address,phone显示提交的新值&#xff0c; name显示oldname&#xff0c;而不是新值
request.setAttribute("message", "用户名["&#43;name&#43;"]已经被占用&#xff0c;请重新填写&#xff01;");//方法结束
request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response);return;
}
}//3 若验证通过&#xff0c;把表单参数封装为一个Customer对象customer
Customer customer&#61;newCustomer(name,address,phone);
customer.setId(Integer.parseInt(id));//4 调用CustomerDAO的update(Customer customer)执行更新操作
customerDAO.update(customer);//5 重定向到query.do
response.sendRedirect("query.do");
}//模糊查询
private voidquery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String name&#61;request.getParameter("name");
String address&#61;request.getParameter("address");
String phone&#61;request.getParameter("phone");
CriteriaCustomer cc&#61;newCriteriaCustomer(name,address,phone);//1 调用CustomerDAO的getALl方法得到Customer集合//List sustomers&#61;customerDAO.getAll();获取所有信息列表
List customers&#61;customerDAO.getForListWithCriteriaCustomer(cc);//2 把customer的集合放入request
request.setAttribute("customers", customers);//3 转发页面index.jsp(不能使用重定向)
request.getRequestDispatcher("/index.jsp").forward(request,response);
}private voiddelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String idstr&#61;request.getParameter("id").trim();int id&#61;0;try{
id&#61;Integer.parseInt(idstr);
customerDAO.delete(id);
}catch(Exception e){}
response.sendRedirect("query.do");
}//此方法名称跟页面add添加的action中add.do匹配
private voidadd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//1 获取表单参数&#xff1a;name&#xff0c;address&#xff0c;phone
String name&#61;request.getParameter("name");
String address&#61;request.getParameter("address");
String phone&#61;request.getParameter("phone");//2 检验name是否被占用//2.1 调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在
long count&#61;customerDAO.getCountWithName(name);if(count>0){//2.2 若返回值大于0&#xff0c;则相应newcustomer.jsp页面&#xff1a;①在此页面显示一个错误信息②此表单值可以回显//通过request.getAttribute("message")显示信息//通过value&#61;""回显
request.setAttribute("message", "用户名["&#43;name&#43;"]已经被占用&#xff0c;请重新填写&#xff01;");
request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);return;
}//3 若验证通过&#xff0c;把表单参数封装为一个Customer对象customer
Customer customer&#61;newCustomer(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包&#xff1a;JdbcUtilsTest.java对CustomerServlet.java各个方法单元测试
package com.cuit.mvc.test;
importstatic 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 classCustomerDAOJdbcImplTest {private CustomerDAO customerDAO&#61;newCustomerDAOJdbcImpl();
&#64;Testpublic voidgetForListWithCriteriaCustomer(){
CriteriaCustomer cc&#61;new CriteriaCustomer("Tom", null, null);
List customers&#61;customerDAO.getForListWithCriteriaCustomer(cc);
System.out.println(customers);
}
&#64;Testpublic voidtestGetAll() {
List customers&#61;customerDAO.getAll();
System.out.println(customers);
}
&#64;Testpublic voidtestSaveCustomer() {
Customer customer&#61;new Customer("Baijing","Shanghai","134-2345-9086");
customerDAO.save(customer);
}
&#64;Testpublic voidtestGetInt() {
Customer cust&#61;customerDAO.get(0);
System.out.println(cust);
}
&#64;Testpublic voidtestDelete() {
customerDAO.delete(2);
}
&#64;Testpublic voidtestGetCountWithName() {long count&#61;customerDAO.getCountWithName("Tom");
System.out.println(count);
}
}
View Code
5 视图显示页面层
index.jsp&#xff1a;显示顾客信息&#xff0c;并支持回显
String basePath&#61; request.getScheme()&#43;"://"&#43;request.getServerName()&#43;":"&#43;request.getServerPort()&#43;path&#43;"/";%>
My JSP &#39;index.jsp&#39; starting page$(&#39;.delete&#39;).click(function(){var content&#61;$(this).parent().parent().find("td:eq(1)").text();var flag&#61;confirm("确定要删除此"&#43;content&#43;"信息&#xff1f;");returnflag;
});
});
CustomerName: | |
CustomerAddress: | |
CustomerPhone: | |
Create New Customer |
customers&#61;(List)request.getAttribute("customers");if(customers!&#61;null && customers.size()>0){%>
ID | CustomerName | CustomerAddress | CustomerPhone | Update/Delete |
---|
for(Customer customer:customers){%>
Update
Delete
View Code
error.jsp&#xff1a;异常或者报错页面跳转
String basePath&#61; request.getScheme()&#43;"://"&#43;request.getServerName()&#43;":"&#43;request.getServerPort()&#43;path&#43;"/";%>
My JSP &#39;error.jsp&#39; starting page
对不起访问失败&#xff01;
View Code
newcustomer.jsp&#xff1a;添加顾客信息页面&#xff0c;支持回显&#xff0c;控制name不能重复
Insert title here");out.print(mes);out.print("
");out.print("
");
}%>
添加一条新的customer信息CustomerName: | "/> |
CustomerAddress: | "/> |
CustomerPhone: | "/> |
View Code
success.jsp&#xff1a;添加新信息成功跳转页面
Insert title hereView Code
updatecustomer.jsp&#xff1a;更新信息页面&#xff0c;支持回显&#xff0c;回显显示的是name旧值
Insert title here");out.print(mes);out.print("
");out.print("
");
}
String id&#61;null;
String name&#61;null;
String oldname&#61;null;
String address&#61;null;
String phone&#61;null;
Customer customer&#61;(Customer)request.getAttribute("customer");if(customer!&#61;null){
id&#61;customer.getId()&#43;"";
address&#61;customer.getAddress();
name&#61;customer.getName();
oldname&#61;customer.getName();
phone&#61;customer.getPhone();
}else{
id&#61;request.getParameter("id");
name&#61;request.getParameter("oldname");
oldname&#61;request.getParameter("oldname");
address&#61;request.getParameter("address");
phone&#61;request.getParameter("phone");
}%>
更新一条新的customer信息CustomerName: | |
CustomerAddress: | |
CustomerPhone: | |
View Code
3 顾客信息模糊查询设计与实现
1) 项目设计分析&#xff1a; 实现name&#xff0c;address&#xff0c;phone联合模糊查询
1、 调用CustomerDAO的getALl方法得到Customer集合
2、 把customer的集合放入request
3、 转发页面index.jsp(不能使用重定向)
4、 index.jsp页面循环遍历显示
2)项目源码实现
1 DAO数据操作
public List getForListWithCriteriaCustomer(CriteriaCustomer cc) {
String sql&#61;"select * from customers where name like ? and address like ? "
&#43; "and phone like ?";
//修改了CriteriaCustomer的getter方法:使其返回字符串中有%%
//若返回值为null返回%%&#xff0c;若不返回null则返回&#xff1a;"%"&#43;字段本身的值&#43;"%"
//如上效果如&#xff1a;cc.getName()&#61;&#61;null&#xff1f;%%:%&#43;name&#43;%
System.out.println(sql);
return getForList(sql,cc.getName(),cc.getAddress(),cc.getPhone());
}
2、servlet控制源码&#xff1a;
//模糊查询
private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String name&#61;request.getParameter("name");
String address&#61;request.getParameter("address");
String phone&#61;request.getParameter("phone");
CriteriaCustomer cc&#61;new CriteriaCustomer(name,address,phone);
//1 调用CustomerDAO的getALl方法得到Customer集合
//List sustomers&#61;customerDAO.getAll();获取所有信息列表
List customers&#61;customerDAO.getForListWithCriteriaCustomer(cc);
//2 把customer的集合放入request
request.setAttribute("customers", customers);
//3 转发页面index.jsp(不能使用重定向)
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
3、index页面显示
List customers&#61;(List)request.getAttribute("customers");
if(customers!&#61;null && customers.size()>0){
%>
ID | CustomerName | CustomerAddress | CustomerPhone | Update/Delete |
---|
for(Customer customer:customers){
%>
Update
Delete
}
%>
}
%>
3)项目单元测试
&#64;Test
public void getForListWithCriteriaCustomer(){
CriteriaCustomer cc&#61;new CriteriaCustomer("Tom", null, null);
List customers&#61;customerDAO.getForListWithCriteriaCustomer(cc);
System.out.println(customers);
}
4)项目运行效果
4 顾客信息添加设计与实现
1) 项目设计分析&#xff1a;name唯一&#xff0c;新添加信息需要验证错误提示
1、获取表单参数&#xff1a;name、address、phone
2、检验name是否被占用
3、若验证通过&#xff0c;把表单参数封装为一个Customer对象customer
4、调用CustomerDAO的save(Customer customer)执行保存操作
5、重定向到success.jsp页面
2)项目源码实现
1、DAO操作源码
&#64;Override
public void save(Customer customer) {
String sql&#61;"insert customers(name,address,phone) values(?,?,?)";
update(sql, customer.getName(),customer.getAddress(),customer.getPhone());
}
2、servlet操作源码
//1 获取表单参数&#xff1a;name&#xff0c;address&#xff0c;phone
String name&#61;request.getParameter("name");
String address&#61;request.getParameter("address");
String phone&#61;request.getParameter("phone");
//2 检验name是否被占用
//2.1 调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在
long count&#61;customerDAO.getCountWithName(name);
if(count>0){
//2.2 若返回值大于0&#xff0c;则相应newcustomer.jsp页面&#xff1a;①在此页面显示一个错误信息②此表单值可以回显
// 通过request.getAttribute("message")显示信息
// 通过value&#61;""回显
request.setAttribute("message", "用户名["&#43;name&#43;"]已经被占用&#xff0c;请重新填写&#xff01;");
request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);
return;
}
//3 若验证通过&#xff0c;把表单参数封装为一个Customer对象customer
Customer customer&#61;new Customer(name,address,phone);
//4 调用CustomerDAO的save(Customer customer)执行保存操作
customerDAO.save(customer);
//5 重定向到success.jsp页面
response.sendRedirect("success.jsp");
3、 视图页面显示源码
Object mes&#61;request.getAttribute("message");
if(mes!&#61;null){
out.print("
");
out.print(mes);
out.print("
");
out.print("
");
}
%>
添加一条新的customer信息CustomerName: | value&#61;""/> |
CustomerAddress: | value&#61;""/> |
CustomerPhone: | value&#61;""/> |
3)项目单元测试
&#64;Test
public void testSaveCustomer() {
Customer customer&#61;new Customer("Baijing","Shanghai","134-2345-9086");
customerDAO.save(customer);
}
4)项目运行效果
5 顾客信息更新设计与实现
1) 项目设计分析
1、 编辑操作&#xff1a;①获取请求参数id&#xff1b;②调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customer&#xff1b;③若验证通过&#xff0c;把表单参数封装为一个Customer对象customer&#xff1b;④ 调用CustomerDAO的update(Customer customer)执行更新操作&#xff1b;⑤重定向到query.do
2、更新操作&#xff1a;①获取请求参数:id,name,address,phone,oldname&#xff1b;②检验name是否被占用&#xff1b;③若验证通过&#xff0c;把表单参数封装为一个Customer对象customer&#xff1b;④调用CustomerDAO的update(Customer customer)执行更新操作&#xff1b;⑤重定向到query.do&#xff1b;
2)项目源码实现
1、DAO操作源码&#xff1a;
&#64;Override
public void save(Customer customer) {
String sql&#61;"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&#61;"/error.jsp";
//1 获取请求参数id
String idstr&#61;request.getParameter("id");
//2 调用CustomeDAO的customerDAO.get(id)获取和id对应的Customer对象customer
try{
Customer customer&#61;customerDAO.get(Integer.parseInt(idstr));
if(customer!&#61;null){
forwordPath&#61;"/updatecustomer.jsp";
//3 将customer放在request中
request.setAttribute("customer", customer);
}
}catch(Exception e){}
//4 响应updatecustomer.jsp页面&#xff1a;转发
request.getRequestDispatcher(forwordPath).forward(request, response);
}
private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//1 获取请求参数:id,name,address,phone,oldname
String id&#61;request.getParameter("id");
String name&#61;request.getParameter("name");
String oldname&#61;request.getParameter("oldname");
String address&#61;request.getParameter("address");
String phone&#61;request.getParameter("phone");
//2 检验name是否被占用
//2.1 比较name和oldname是否相同&#xff0c;若相同name可用&#xff0c;oldname.equals(name)不如equalsIgnoreCase&#xff0c;数据库默认大小写一致的&#xff0c;而equals忽略大小写
if(!oldname.equalsIgnoreCase(name)){
//不相同&#xff0c;调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在
long count&#61;customerDAO.getCountWithName(name);
//大于0&#xff0c; 响应updatecustomer.jsp页面&#xff1a;通过转发响应newcustomer.jsp
if(count>0){
// 通过request.getAttribute("message")显示信息&#xff0c;在页面上request.getAttribute("message")的方式显示
// 表单据回显。address,phone显示提交的新值&#xff0c; name显示oldname&#xff0c;而不是新值
request.setAttribute("message", "用户名["&#43;name&#43;"]已经被占用&#xff0c;请重新填写&#xff01;");
// 方法结束
request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response);
return;
}
}
//3 若验证通过&#xff0c;把表单参数封装为一个Customer对象customer
Customer customer&#61;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、视图显示操作源码
Object mes&#61;request.getAttribute("message");
if(mes!&#61;null){
out.print("
");
out.print(mes);
out.print("
");
out.print("
");
}
String id&#61;null;
String name&#61;null;
String oldname&#61;null;
String address&#61;null;
String phone&#61;null;
Customer customer&#61;(Customer)request.getAttribute("customer");
if(customer!&#61;null){
id&#61;customer.getId()&#43;"";
address&#61;customer.getAddress();
name&#61;customer.getName();
oldname&#61;customer.getName();
phone&#61;customer.getPhone();
}else{
id&#61;request.getParameter("id");
name&#61;request.getParameter("oldname");
oldname&#61;request.getParameter("oldname");
address&#61;request.getParameter("address");
phone&#61;request.getParameter("phone");
}
%>
更新一条新的customer信息CustomerName: | |
CustomerAddress: | |
CustomerPhone: | |
3)项目单元测试
&#64;Test
public void testSaveCustomer() {
Customer customer&#61;new Customer("Baijing","Shanghai","134-2345-9086");
customerDAO.save(customer);
}
4)项目运行效果
6 顾客信息删除设计与实现
1) 项目设计分析
1、获取id的值
2、调用DAO的删除方法
3、执行提示是否删除
4、删除成功跳转刷新
2)项目源码实现
1、DAO源码&#xff1a;
&#64;Override
public void delete(int id) {
String sql&#61;"delete from customers where id&#61;?";
update(sql, id);
}
2、servlet源码&#xff1a;
private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String idstr&#61;request.getParameter("id").trim();
int id&#61;0;
try{
id&#61;Integer.parseInt(idstr);
customerDAO.delete(id);
}catch(Exception e){}
response.sendRedirect("query.do");
}
3、页面显示源码&#xff1a;
$(function(){
$(&#39;.delete&#39;).click(function(){
var content&#61;$(this).parent().parent().find("td:eq(1)").text();
var flag&#61;confirm("确定要删除此"&#43;content&#43;"信息&#xff1f;");
return flag;
});
});
Update
Delete
3)项目单元测试
&#64;Test
public void testDelete() {
customerDAO.delete(2);
}
4)项目运行效果
7 面向接口开发的数据源配置
倘若需要操作其他数据库或者xml数据源进行存储&#xff0c;该如何操作呢&#xff1f;下面以jdbc和xml进行设计
1 、不修改DAO底层代码前提下&#xff0c;创建工厂模式&#xff0c;利用tyep类型进行选择实例创建连接模式&#xff0c;
//单例工厂
public class CustomerDAOFactory {
private Map daos&#61;new HashMap();
private static CustomerDAOFactory instance&#61;new CustomerDAOFactory();
public static CustomerDAOFactory getInstance(){
return instance;
}
private String type&#61;null;
public void setType(String type) {
this.type&#61;type;
}
private CustomerDAOFactory() {
daos.put("jdbc", new CustomerDAOJdbcImpl());
daos.put("xml", new CustomerDAOXMLImpl());
}
public CustomerDAO getCustomerDAO(){
return daos.get(type);
}
}
2、type值放在switch.properties用于切换&#xff0c;如下是该文件的内容
#type&#61;xml
type&#61;jdbc
3、初始化servlet&#xff0c;创建InitServlet.java文件&#xff0c;并控制type值传递CustomerDAOFactory工厂用来切换数据源
public class InitServlet extends HttpServlet {
&#64;Override
public void init() throws ServletException {
CustomerDAOFactory.getInstance().setType("jdbc");
//读取类路径switch.properties文件
InputStream in&#61;getServletContext().getResourceAsStream("/WEB-INF/classes/switch.properties");
Properties properties&#61;new Properties();
try {
properties.load(in);
//获取switch.properties的type值
String type&#61;properties.getProperty("type");
//赋给了CustomerDAOFactory的type属性
CustomerDAOFactory.getInstance().setType(type);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4、配置web.xml文件&#xff0c;使InitServlet.java在项目启动时即运行
CustomerServlet
com.cuit.mvc.servlet.CustomerServlet
InitServlet
com.cuit.mvc.servlet.InitServlet
1
五、顾客管理项目完整源码
六、顾客管理项目技术总结
1 Tomcat目录结构图
2 Tomcat配置&#xff0c;MyEclipse2015默认集成了&#xff0c;不需要配置
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发送请求控制&#xff1a;方法1
17 多页面向单个servlet发送请求控制&#xff1a;方法2
18 更新操作原理示意图
19 查询设计思路
20 MVC案例需求设计
21 jsp页面请求遍历数据
22 修改更新设计思路
23 面向接口编程
24 表单请求和回显图示