(MVC — — Demo)客户管理系统的开发日志
目录
第一步:搭建开发环境
将一众需要的jar
包导入开发环境中 ;
在 WEB
项目中,WEB-INF
目录下面创建一个 lib
目录,将需要的 jar
包放到这里,并添加到库中;
第二步:层次包(按照三层架构
思想写)
主要把握住 MVC
思想,按照层次写开发包;
再加一些自己需要的包,包括但不限于:工具包(utils
)、自定义异常包(exception
)、工厂包(factory
)、实体包(domain
)、bean包(bean)。。。
第四步:开发(utils
)工具包
这个包,必须开发出来;
里面封装着项目中,需要经常用到的操作;
例如:JDBC
操作数据库,每次都要获取连接、关闭连接;我们不可能每次都手动写一遍获取、关闭连接的代码;最好的做法,就是在工具包里面写一个 JdbcUtils 工具类,在里面写上获取与关闭连接的代码;在项目中需要用到JDBC
操作数库,就直接调用工具类的方法 ;
JDBC工具类部分代码
:
/**
* 利用jdbc操控数据库
*
* @author An
*/
@SuppressWarnings("unused")
public class JdbcUtils {
private static Properties config = new Properties();
static {
try {
// 读取配置文件
config.load(JdbcUtils.class.getResourceAsStream("/ijava/xin/utils/db.properties"));
// 加载数据库驱动类
Class.forName(config.getProperty("driver"));
} catch (IOException e) {
e.printStackTrace();
throw new JdbcException("读取配置文件出错");
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new JdbcException("配置文件路径有问题");
}
}
/**
* @return 返回数据库的连接
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(config.getProperty("url"), config.getProperty("username"), config.getProperty("password"));
}
public static void closedConnection(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
第四步:开发 Dao
层
先写 daoImpl
类,在里面实现对数据库的操作方法,最后提取出 dao
接口 ;
第五步:开发 services
层
先写 servicesImpl
类,在里面 实现 项目对外提供的服务,最后提取出 services
接口 ;
第六步:开发 factory(工厂)
包
工厂包,是为了解耦;
当services
层需要dao
层的方法时候,不能直接在services
层里面直接 new
dao
层对象,这样就是硬编码了;将 services
层 和 dao
层 紧紧的绑定在一起 ; 以后改动dao
层,会牵扯到services
层;
因此,我们需要让他们之间出现一个桥梁,让他们不直接通信,让这个桥梁起个媒介的作用;
我们就用工厂来解耦,就是在工厂包里面,为dao层做一个 daoFactory 工厂类,里面提供静态方法;
示例代码:
/**
* 静态工厂解耦
*
* @author An
*/
@SuppressWarnings("unused")
public class CustomerDaoFactory {
private static CustomerDao customerDao = new CustomerDaoImpl();
public static CustomerDao getCustomerDao() {
return customerDao;
}
}
我们在services
层,就直接问工厂来要 dao
层的实例;这样即使dao
层改变了,甚至推倒重来了,我们也只需要在工厂中对其进行修改,根本不影响services
层 ;
这里我用的是 静态工厂
,是工厂中最简单的一种了。缺点也很明显,要为每一层增加一个新的实现,我都要为其写一个工厂类;懒得写简单工厂,我写的这个demo的业务逻辑很简单。
当然也可以 写一个 泛型工厂
一劳永逸 ;
备注:我web
是从 servlet+JSP + tomcat
学起的;现在学到了JDBC
的事物,对那些 spring
等框架,我都没学到;
但是从对群里的群友对话,他说用了sprig
的框架以后,没考虑过工厂,说spring
会解耦,services
层如果需要dao
层对象,spring
会根据字段给它一个;
霎时,吾觉 spring
莫不是一个工厂吧;后百度之,果不其然,乃一大工厂也 ;
从上面的经历,可以看出,从最初的学起,还是很有好处的;
第七步:开发web
层
用
<iframe>
标签实现分帧页面
// 写上target属性,属性值是我们的画中画标签名
<a href="${pageContext.request.contextPath}/Demo.jsp" target="showForm">添加客户</a>
<a href="${pageContext.request.contextPath}/Demo2.jsp" target="showForm">查看客户</a>
<hr> <iframe src="" name="showForm" style="text-align: center" scrolling="auto" frameborder="0" height="85%" width="100%"></iframe>用全局类来管理
伪静态数据
在程序开发过程中,我们在表单中有一项性别要用户填写;常规操作是用
<radio>
标签给出两个性别,供选择;这样,其实也就是性别,被我们写死了;假如,系统以后卖到泰国,性别就会不只有男、女,两个选项;我们就需要去更改当初的表单的性别设置,可能表单的性别设置也会关联到其他。
这样一下,就需要改动许多东西;因此,我们最开始开发的时候,就应该考虑到数据以后会改变的情况;写一个程序来控制这些数据显示;
表单中的爱好一栏,也是同样的操作,由程序控制显示,因为,每年都会有新的爱好出来;
我把这种在一段时间内是静态的,但是长久看,确实动态的数据,称为
伪静态数据
;
常用try catch
对我们的代码,要常用 try catch
包起来,因为我们在服务器端可能会出现一些错误,我们不能将这些错误直接显示在网页上,我们就要捕捉它们,跳准到全局页面(500),在后台打印log;
从请求中获取请求参数,封装进bean
中
现在学过的有2种方法:
第一种,就是将它们读取进一个枚举中,然后迭代枚举,然后使用
beanUtils
的方法,将它们封装进bean
里面;
// 获取请求的参数的名字
Enumeration<String> enumeration = request.getParameterNames();
// 循环获取参数名字,对应的值
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement();
// 根据名字从域中拿值
String value = request.getParameter(name);
// 将数据封装到对象中,使用BeanUtils,或者直接使用反射
BeanUtils.setProperty(classbean, name, value);
第二种,就是将请求参数封装进Map里面,再封装进bean里面 ;假如Map里面的关键字在
bean
里面没有,则不进行赋值 ;Map<String, String[]> map = request.getParameterMap(); BeanUtils.populate(t, map);
分帧显示页面
比如,我们想实现这样一个页面,上下分帧,各自显示自己的画面,点击上半部分页面的超链接,在下半部分页面显示超链接指向的窗口页面;
我们只需要在上半部分的页面中加入一个画中画标签<iframe>
即可;然后在超链接上指明超链接打开的窗口地址;这样设置以后,打开超链接,就会在我们指定的下面的页面显示;
示例代码
:
<h1 style="color: darkcyan">客户管理系统</h1>
<audio autoplay="autoplay" loop="loop" src="${pageContext.request.contextPath}/Music/cuoguo.mp3"></audio>
<a href="${pageContext.request.contextPath}/addcustomer.html" target="showForm">添加客户</a>
<a href="${pageContext.request.contextPath}/showAll.html" target="showForm">查看客户</a>
<hr>
<iframe name="showForm" style="text-align: center" scrolling="auto" frameborder="0" height="85%" width="100%"></iframe>
这样做以后,还有一个好处,点击超链接,上半部分的页面是不会刷新的,它们相当于一个全局页面了,我们可以在里面设置背景音乐,这样背景音乐就成了全局音乐,下部分页面切换。不会影响音乐的播放 ;
制作分页
我们这个小项目中,需要对数据库的用户进行展示;这就需要用分页技术了 ;
- 分页逻辑
---------------------------------分页实现逻辑:--------------------------
1、对于页面上的 页码,上一页、下一页 等都是超链接,它们对应着一个个的 servlet
;
2、servlet
接受到请求以后,将请求信息封装为一个对象(QueryInfo
)
3、QueryInfo
对象字段设计
int currentPage ; // 查询页
int pageSize ; // 每页显示数据的条数
int startIndex ; // 查询页的数据开始的下标 ,根据查询页和每页显示数据,可以算出来
4、web层的servlet将请求信息封装为 QueryInfo
对象以后,然后将请求跳准services
层,将 QueryInfo
对象作为services
层方法的参数 ;
5、services
层,根据QueryInfo
对象的信息,调用dao
层,查询出需要的数据,数据的总数、;
6、dao
层将查询到的信息,封装为一个对象(QueryResult
对象),存进域里面;
7、QueryResult
对象设计
List list ; // 保存页面显示的数据
int totalRecord ; // 数据库中的数据总数
8、services
层封装一个PageBean
对象 ;这个对象字段设计,根据JSP
页面中显示的数据,来设计,这个对象,其实也就是页面;
9、PageBean
对象设计
List list ; // 保存页面显示的数据
int totalRecord ; // 数据库中数据的总数
int pagaSize ; // 每页显示多少条数据
int currentPage ; // 当前显示的页码
int previousPage ; // 前一页
int nextPage ; // 下一页
int[] pageBar = new int[] ; // 页码条,根据信息算出来的
10、services
层将 pageBean
对象,保存进域里面,然后交给最初的 servlet
处理;
11、最初的 servlet
跳准到自己,页面用 el表达式
取值 ;
分页的逻辑就是这么一回事;还是比较简单的;
开发分页对象的实体
设计出三个java类,很简单,没啥讲的;
但是有一些字段,明明是自己根据信息算出来的,而不是从外界获取到的,那么这样的字段就不要有set
方法 ;
页码条
根据实际情况生成页码条;
示例代码:
public int[] getPageBar() {
int startIndex = 0;
int endIndex = 0;
// 先判断当前一共多少页,默认最多显示5个页码条
if (getTotalPage() < 5) {
// 根据实际情况生成数组长度
pageBar = new int[getTotalPage()];
startIndex = 1;
endIndex = getTotalPage() ;
} else {
pageBar = new int[5];
startIndex = currentPage - 2;
endIndex = currentPage + 2;
if (startIndex < 1) {
startIndex = 1;
endIndex = 5;
}
if (endIndex > getTotalPage()) {
endIndex = getTotalPage();
startIndex = getTotalPage() - 4;
}
}
// 为数组填充值
int index = 0;
for (int i = startIndex; i <= endIndex; i++) {
pageBar[index++] = i;
}
return pageBar;
}
坑点
拼接浏览器url地址的时候,不能在里面随便写上空格;例如:'&pageSize='
不能写成 '&pageSize = '
;
class
属性是可以el
表达式的:class="${status.count%2 == 0}"
;el表达式可以写在JSP
页面中的任何地方,
更新客户信息
// 开发修改用户信息模块。难点在于将数据库中的信息,复原到表格里面;
可以使用了body
上的onload
监听方法,调用JS
函数,在JS
里面通过DOM
操作,取值赋值,这是我首先想出来的方法;不会jQuery
,就只能这么做了;
后来发现,其实对一般的输入项使用 value和el表达式就可以完成;
对于选项(<radio> <checkbox>
)使用三元表达式,和el表达式,也可以完成;
对于<textarea>
对他设置value
属性,value
的值是不会显示在页面中,只能在标签体上用el表达式取值,或者DOM
操作,用innertHtml
进行赋值 ;
其实是 value
与 innetHTML
的区别value
是属性值,而innerHtml
则是赋人眼可见的值 ,也就是标签体的值,只不过一些标签,没有标签体,它们的值就是 value
的值;
JS的一些坑
JS比较值是否相等的时候,如果是字符串,则应该用单引号括起来,不论它是字面值还是变量值,但是变量做参数的时候,不需要括号括起来;
JS 中非0 都是真,跟C一样,用IF的时候要注意
// 这里必须判断是否等于 -1 否则表达式永真
if ('${customer.preference}'.indexOf(pre[i].value)!=-1) {
pre[i].checked = 'true';
}
JS中字符串的contain
方法,不好用,不是所有浏览器都支持 ;
JS 函数,有时候获取不到传进去的参数,可以试着在参数上加上单引号;
乱码问题!
再次说一下乱码的问题 ;
response
没设置编码的原因是,servlet
里面没做输出,都是跳准到JSP
里面输出
而JSP
页面的pageEncoding='UTF-8'
,就已经改变了JSP翻译为servlet的response
的码表;
所以JSP
输出中文不会出现乱码;但是你要是在servlet
做输出,就必须改变其response
的码表了 ;
(MVC — — Demo)客户管理系统的开发日志的更多相关文章
- 基于.net mvc 的供应链管理系统(YB-SCM)开发随笔1-开篇
作为开篇之作,先把这个项目的介绍和一些技术点给各位. 1.项目所用到的技术 (1)前台展示:ASP.NET MVC 3.0+Jquery+Sea+Bootstrap等 (2)开发环境:VS2012/V ...
- 基于.net mvc 的供应链管理系统(YB-SCM)开发随笔
作为园子里的伪新人,经常拜读众位大牛的帖子,一直有写点东西的想法. 今天终于下定决心去写这个系统的开发过程,由于本人文笔有限,不足之处多多海涵.
- Taurus.MVC 微服务框架 入门开发教程:项目集成:5、统一的日志管理。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- 20160410javaweb 开发小案例 --客户管理系统
客户管理系统---体验基于数据库javaweb的增删改查 添加客户 查询客户列表 修改客户信息 删除客户 条件查询客户信息 分页查询客户 javaee的经典三层架构--工厂类实现解耦 jsp+serv ...
- 黑马客户管理系统(SSM)
黑马客户管理系统 1系统概述 1.1系统功能介绍 本系统后台使用SSM框架编写,前台页面使用当前主流的Bootstrap和jQuery框架完成页面信息展示功能(关于Bootstrap的知识,有兴趣的读 ...
- SpringMVC Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现
SpringMVC学习系列(12) 完结篇 之 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现 到这里已经写到第12篇了,前11篇基本上把Spring M ...
- mongodb入门级的视频教程-简易客户管理系统制作
本套教程作为mongodb入门级的视频教程,首先讲解了mongodb的下载.安装,环境变量的设置.启动mongodb和将mongodb安装成为windows服务.然后进一步讲解了mongodb里面集合 ...
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:2、客户端:ASP.NET Core(C#)项目集成:应用中心。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
随机推荐
- 2018年 第43届ACM-ICPC亚洲区域赛(青岛)现场赛 赛后总结
下了动车后,又颠颠簸簸的在公交车上过了接近一个小时,本来就晕车,于是,到的时候脑子晕死了,而且想吐.可能是没吃早饭的缘故,午饭好好次QWQ. 开幕式 还是第一次在这种环境下参赛,记得以前是看老师发的学 ...
- docker容器中查看容器linux版本
root@dae5aecea3dd:~# cat /etc/issue Ubuntu LTS \n \l
- spring相关知识点易错
1.spring不支持静态变量注入,即不能再static变量上面加@Resoure 要是想注入的话就用set方法注入 private static ComboPooledDataSource pool ...
- NOI2019 游记——一切都是最好的安排
有幸运有遗憾 一切都是最好的安排. Day-3 临近NOI了,机房都在狂奶某某同学进队稳了 HE省队垫底,THUSC面试都没进 作为一个有自知之明的人 也就指望着能拼进前100,至少也拿个银牌. 心态 ...
- TCP/IP协议入门
TCP/IP协议入门 1. 简介 Transmission Control Protocol/Internet Protocol的简写,即传输控制协议/因特网互联协议.它是网络通信的一套协议集合. 先 ...
- Python 自学笔记(二)
3-1.条件判断 3-1.条件判断 3-1-1.单项判断 if 3-1-2.双向判断 if...else... 3-1-3.多向判断 if...elif...else 3-2.if嵌套 4.输入 4- ...
- Flutter移动电商实战 --(27)列表页_现有Bug修复和完善
小解决小bug 默认右侧的小类没有被加载 数据加载完成后,就list的第一个子对象传递给provide进行赋值,这样右侧的小类就刷新了数据 默认加载了第一个类别 调整颜色 对比图片调整下颜色 这里的参 ...
- PHP学习之工厂方法模式
<?php //工厂方法模式 interface Doing { function eat(); function sleep(); } class Cat implements Doing { ...
- linux rtc中废弃的接口和新的接口
1. 废弃的接口 rtc_tm_to_time 2. 替换废弃接口的新接口 rtc_tm_sub
- 【NetDevops】网络自动化运维--1获取用户基本信息
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 之前博客的云主机到期了没续费,被删啦最重要的是没有备份!此处省略几个字..... ...