当前位置: 首页 > 工具软件 > X2CRM > 使用案例 >

Java实现CRM项目过程中的细节记录(二)

仇正豪
2023-12-01

Java实现CRM项目过程中的细节记录(二)


上一篇:Java实现CRM项目过程中的细节记录(一)

一、线索模块

1. 服务器缓存

  1. 什么是服务器缓存?
    缓存:内存中的数据
    浏览器缓存:浏览器内存中保存的以前的服务器做出的响应
    服务器缓存:保存在服务器内存中的数据

  2. 服务器缓存通常都保存些什么?
    一般来讲,服务器缓存就是用来保存数据字典的,因为数据字典数据量大,而且值不是很容易发生变化。

  3. 处理服务器缓存的最佳时机?
    web开发三大组件:(Servletcontroller)、FilterListener),这3个组件对象,是由Tomcat服务器帮我们维护的,一般把这些类写在web包中,如监听器在包中的位置:com.company.crm.web.listener.Listener.java

    通过监听器,监听上下文(全局域)对象的创建,当application对象创建完毕后,监听器中的contextInitialized()方法就执行了,我们就可以在这个contextInitialized()方法中将所有的数据字典值取出,将他们保存到application域对象中。所谓的服务器缓存其实就是往application域对象中存值。

    将数据字典值保存到application域对象中的过程,就是将数据字典保存到服务器内存中,产生缓存的过程。

2. 监听器

  1. 在监听器中,我们需要使用到数据字典的业务层对象,而使用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();      
    }
}
  1. 我们需要使用WebApplicationContextUtils工具类,该工具类的作用是获取到spring容器的引用,进而获取到我们需要的bean实例
    WebApplicationContextUtils.getWebApplicationContext(application).getBean(DicService.class);
    
  2. 注意:配置监听器时的上下顺序:
    • Spring提供监听器(ContextLoaderListener)配置在上方,先由spring容器创建好service
    • 因为我们自定义的监听器(SysInitListener)要用到Spring,所以要配置在Spring监听器的下方,再由tomcat容器引用service对象
    • 扩展:web.xml中三大web组件的一般配置顺序:先Filter,然后是Listener,最后是Servlet。特殊:字符集过滤器(CharacterEncodingFilter)要放在最后

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对象

步骤:

  1. 通过标签方式直接引入构建好的 echarts 文件
  2. 在绘图前我们需要为 ECharts 准备一个具备高宽的 DOM 容器。(<div></div>)
  3. 以通过 echarts.init 方法初始化一个 echarts 实例,创建一个myChar对象
  4. 指定图表的配置项和数据(对于数据项中的某些数据不知道是干啥的,可以查文档,或者改一下这个数据看看在图表上有啥变化)
  5. 通过刚创建的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. 打包的问题

  1. 先clean将target干掉
  2. 再启动服务器将target创建
  3. 关闭服务
  4. 最后package打war包
 类似资料: