Java实现CRM项目过程中的细节记录(二)
文章目录
上一篇:Java实现CRM项目过程中的细节记录(一)
一、线索模块
1. 服务器缓存
-
什么是服务器缓存?
缓存:内存中的数据
浏览器缓存:浏览器内存中保存的以前的服务器做出的响应
服务器缓存:保存在服务器内存中的数据 -
服务器缓存通常都保存些什么?
一般来讲,服务器缓存就是用来保存数据字典的,因为数据字典数据量大,而且值不是很容易发生变化。 -
处理服务器缓存的最佳时机?
web开发三大组件:(Servlet
(controller
)、Filter
、Listener
),这3个组件对象,是由Tomcat
服务器帮我们维护的,一般把这些类写在web包中,如监听器在包中的位置:com.company.crm.web.listener.Listener.java
。通过监听器,监听上下文(全局域)对象的创建,当
application
对象创建完毕后,监听器中的contextInitialized()
方法就执行了,我们就可以在这个contextInitialized()
方法中将所有的数据字典值取出,将他们保存到application
域对象中。所谓的服务器缓存其实就是往application
域对象中存值。将数据字典值保存到
application
域对象中的过程,就是将数据字典保存到服务器内存中,产生缓存的过程。
2. 监听器
- 在监听器中,我们需要使用到数据字典的业务层对象,而使用spring配置监听器,再注入service是不行的
以下写法是错误的:
public class SysInitListener implements ServletContextListener {
//这种写法是错误的,因为监听器对象是由Tomcat管理的,而Autowired是Spring才能实现自动注入
@Autowired
private DicService dicService;//null
@Override
public void contextInitialized(ServletContextEvent sce) {
//虽然new出来的service不是null,但是这个service中的dao也使用了自动注入,所以为null
DicServiceImpl dicService = new DicServiceImpl();
}
}
- 我们需要使用
WebApplicationContextUtils
工具类,该工具类的作用是获取到spring
容器的引用,进而获取到我们需要的bean
实例WebApplicationContextUtils.getWebApplicationContext(application).getBean(DicService.class);
- 注意:配置监听器时的上下顺序:
- Spring提供监听器(
ContextLoaderListener
)配置在上方,先由spring
容器创建好service
- 因为我们自定义的监听器(
SysInitListener
)要用到Spring,所以要配置在Spring监听器的下方,再由tomcat
容器引用service
对象 - 扩展:
web.xml
中三大web组件的一般配置顺序:先Filter
,然后是Listener
,最后是Servlet
。特殊:字符集过滤器(CharacterEncodingFilter
)要放在最后
- Spring提供监听器(
2. Spring管理JUnit
关于命名(要遵守驼峰命名法):
- 测试类的命名:模块名(domain)+Test
- 方法的命名:test+功能
模块:
- 一般都是对业务层进行测试,我们应该每完成一个业务功能,就应该对这个业务功能编写一份单元测试方法,在测试方法上加
@Test
断言(Assert
):
- 表示测试的结果取得之后,要和我们提供的一个预期的结果进行比较,如果比较二者的值是相同的,测试成功,否则测试失败
Assert.assertEquals(期望值, 真实值);
由Spring去管理JUnit,来进行单元测试:
- 在测试类上加上下面两个注解,就可以在测试类中加入自动注入
Service
@RunWith(SpringJUnit4ClassRunner.class)//表示由spring去管理JUnit,来进行单元测试 @ContextConfiguration("classpath:spring/applicationContext.xml")
3. 当其它模块已经有该功能的时候
功能(方法)一致,也不能在这个模块引用别的模块,无形中增加了耦合度,
4. 模态窗口中敲回车
模态窗口中敲回车时,会强制刷新页面,通过return false;
阻止页面刷新
$("#e").keydown(function (event) {
if (event.keyCode == 13) {
//do something
return false;
}
});
二、交易模块
1. 细节
(1)web组件不往service层传递
session是web层的组件,使用在控制层,别往service层传递
(2)native2ascii.exe工具
java JDK bin 目录下的工具native2ascii.exe
可以将汉字转为ascii
码(/uxxxx)
(3)当从后台跳到前台页面时
正常流程:服务器访问toIndex.do
(没有处理任何数据,单纯返回了一个地址)--------------->index.jsp
当另一个请求save.do
保存完毕后要跳到index.jsp
,这个时候有两个选择,为了之后的可维护性,要请求转发到toIndex.do
,再跳到index.jsp
。
解释:虽然现在toIndex.do
中没有做任何处理,只是返回了一个页面,但日后可能会添加处理,那么save.do
就可以不用管了
(4)及时break
在循环查找时,如果找到了,就即时break
(5)实体类中添加字段
当某个字段在数据库中不存在,但是又经常跟该实体类一起使用时,可以在实体类中添加该字段,一般多添加(与数据库表字段不同)的字段不超过三个
2. 封装工具类
当出现我们自己明明知道传进来的是什么类,但是却不能调用其方法的时候,可以用反射
//这个工具类的作用是设置实体类的id、创建时间和创建人
public class SetUtil {
//形参分别是创建人名字,实体类对象,实体类简单类名(因为实现类的位置相对固定,就在工具类中指定了实体类的包名)
public static void setWorkbench(String name, Object obj, String className) {
className = "com.bjpowernode.crm.workbench.domain." + className;
same(name, obj, className);
}
public static void setSettings(String name, Object obj, String className) {
className = "com.bjpowernode.crm.settings.domain." + className;
same(name, obj, className);
}
private static void same(String name, Object obj, String className) {
String id = UUIDUtil.getUUID();
String time = DateTimeUtil.getSysTime();
try {
Class c = Class.forName(className);
Method setId = c.getMethod("setId", String.class);
Method setCreateBy = c.getMethod("setCreateBy", String.class);
Method setCreateTime = c.getMethod("setCreateTime", String.class);
setId.invoke(obj, id);
setCreateBy.invoke(obj, name);
setCreateTime.invoke(obj, time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 自动补全插件(typeahead)
query
代表输入框中你的输入值(即查询值),process
回调函数。
$("#create-customerName").typeahead({
source: function (query, process) {
$.get(
"workbench/tran/getCustomerNames.do",
{"name": query},
function (data) {
//alert(data);
process(data);
},
"json"
);
},
delay: 500
});
后台要返回一个String
的集合,注意这个集合中的元素是String
@RequestMapping("/getCustomerNames.do")
@ResponseBody
public List<String> getCustomerNames(String name) {
return customerService.getCustomerNames(name);
}
更详细的说明见:Bootstrap3-typeahead 文本自动补全填充
3. ECharts可视化图表插件
官方网址https://www.echartsjs.com/zh/index.html
官方网站上有文档,实例,可以直接将代码拿过来,然后将数据改成自己的的数据就可以了,这里只用到了漏斗图,就拿漏斗图来举例
ECharts只能用原生JS的DOM对象,不能用jQuery对象
步骤:
- 通过标签方式直接引入构建好的 echarts 文件
- 在绘图前我们需要为 ECharts 准备一个具备高宽的 DOM 容器。(
<div></div>
) - 以通过
echarts.init
方法初始化一个echarts
实例,创建一个myChar对象 - 指定图表的配置项和数据(对于数据项中的某些数据不知道是干啥的,可以查文档,或者改一下这个数据看看在图表上有啥变化)
- 通过刚创建的
myChar
对象的setOption()
方法,来生成图表
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
%>
<html>
<head>
<base href="<%=basePath%>">
<title>title</title>
<script src="jquery/jquery-1.11.1-min.js"></script>
<script src="ECharts/echarts.min.js"></script>
<script>
$(function () {
getTranChart();
})
function getTranChart() {
$.ajax({
url : "workbench/chart/transaction/getChartData.do",
type : "get",
dataType : "json",
success : function (data) {
/*
data
int max
List<Map<String,Object>> dataList
List<String> stageNameList
{
"max":100,
"dataList":[{value:100,name:"01资质审查"},{value:10,name:"02需求分析"}...],
"stageNameList" : ["01资质审查","02需求分析"....]
}
*/
//alert("绘制统计图表");
// 基于准备好的dom,初始化echarts实例
//myChart:绘图者
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
//option:我们要画的图
var option = {
title: {
text: '交易漏斗图',
subtext: '统计交易阶段数量的漏斗图'
},
legend: {
data: data.stageNameList
},
calculable: true,
series: [
{
name:'交易漏斗图',
type:'funnel',
left: '10%',
top: 60,
//x2: 80,
bottom: 60,
width: '80%',
// height: {totalHeight} - y - y2,
min: 0,//最小值
max: data.max, //最大值
minSize: '0%',
maxSize: '100%',
sort: 'descending',
gap: 2,
label: {
show: true,
position: 'inside'
},
labelLine: {
length: 10,
lineStyle: {
width: 1,
type: 'solid'
}
},
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
emphasis: {
label: {
fontSize: 20
}
},
//统计项,统计数量
/*
value:统计的数量
name:统计项
我们想要的数据
[{value:100,name:"01资质审查"},{value:10,name:"02需求分析"}...]
*/
data: data.dataList
/*[
{value: 60, name: '访问'},
{value: 40, name: '咨询'},
]*/
}
]
};
// 使用刚指定的配置项和数据显示图表。
//绘图者,调用一个画图的方法来绘制统计图表,参数就是我们要画的图
myChart.setOption(option);
}
})
}
</script>
</head>
<body>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 850px;height:400px;"></div>
</body>
</html>
三、打包
1. linux系统项目中乱码问题的解决
在jdbc的properties配置文件中,在url后加入如下参数:
jdbc.url=jdbc:mysql://localhost:3306/crm?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
2. 打包的问题
- 先clean将target干掉
- 再启动服务器将target创建
- 关闭服务
- 最后package打war包