1. 学习目标
2.CRM 基本概念
圈内存在这么⼀句话:
“
世上本来没有
CRM
,⼤家的⽣意越来越难做了,才有了
CRM
。
”
在同质化竞 争时代,顾客资产尤为重要,新时代在呼唤 CRM
。
CRM
系统即客户关系管理系统, 顾名思义就是管理公司与客户之间的关系。 是⼀种以
"
客户关系⼀对 ⼀理论"
为基础,旨在改善企业与客户之间关系的新型管理机制。客户关系管理的定义是:企业为提⾼核⼼竞争⼒,利⽤相应的信息技术以及互联⽹技术来协调企业与顾客间在销售、营销和服务上的交互,从⽽提升其管理⽅式,向客户提供创新式的个性化的客户交互和服务的过程。 其最终⽬标是吸引新客户、保留⽼客户以及将已有客户转为忠实客户,增加公司市场份额。
CRM
的实施⽬标就是通过全⾯提升企业业务流程的管理来降低企业成本,通过提供更快速和周到的优质服务来吸引和保持更多的客户。作为⼀种新型管理机制,CRM
极⼤地改善了企业与客户之间的关系,应⽤于企业的市场营销、销售、服务与技术⽀持等与客户相关的领域。
CRM
分类
根据客户的类型不同,
CRM
可以分为
B to B CRM
及
B to C CRM
。
BtoB CRM
中管理的客户是企业客户,⽽ B to C CRM
管理的客户则是个⼈客户。提供企业产品销售和服务的企业需要的
B to B
的 CRM,也就是市⾯上⼤部分
CRM
的内容。⽽提供个⼈及家庭消费的企业需要的是
B to C
的
CRM
。
根据
CRM
管理侧重点不同⼜分为操作性和分析型
CRM。⼤
部分
CRM
为操作型
CRM
,⽀持
CRM
的⽇
常作业流程的每个环节,⽽分析型
CRM
则偏重于数据分析。
3.基础模块
包含系统基本的⽤户登录,退出,记住我,密码修改等基本操作。
4. CRM 系统数据库设计
CRM
系统根据产品的原型稿以及
UI
组的设计稿
,
接下来就要设计数据库, ⼀般在⼤公司通常会有专⻔的DBA
, 这时我们可以不要考虑数据库表设计, 但是也要能够读懂或者了解
DBA
的设计思路⽅便在程序开发阶段不会出现问题,⼀般关系型数据库表设计满⾜三范式的设计即可,表名设计做到⻅名知意最好。
5.项⽬环境搭建与测试
环境搭建与测试
1.新建项⽬
在
IDEA
中,新建
SpringBoot
项⽬,项⽬名设置为
crm
2.
引⼊坐标
&
插件
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<maven.compiler.source>
11
</maven.compiler.source>
<maven.compiler.target>
11
</maven.compiler.target>
</properties>
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-parent
</artifactId>
<version>
2.2.2.RELEASE
</version>
</parent>
<dependencies>
<!-- web
环境
-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<!-- aop -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-aop
</artifactId>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-freemarker
</artifactId>
</dependency>
<!--
测试环境
-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
<version>
2.1.1
</version>
</dependency>
<!--
分⻚插件
-->
<dependency>
<groupId>
com.github.pagehelper
</groupId>
<artifactId>
pagehelper-spring-boot-starter
</artifactId>
<version>
1.2.13
</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
<scope>
runtime
</scope>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>
com.mchange
</groupId>
<artifactId>
c3p0
</artifactId>
<version>
0.9.5.5
</version>
</dependency>
<!-- commons-lang3 -->
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<version>
3.5
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
</dependency>
<!-- DevTools
热部署
-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-devtools
</artifactId>
<optional>
true
</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<version>
2.3.2
</version>
<configuration>
<source>
11
</source>
<target>
11
</target>
<encoding>
UTF-8
</encoding>
</configuration>
</plugin>
<plugin>
<groupId>
org.mybatis.generator
</groupId>
<artifactId>
mybatis-generator-maven-plugin
</artifactId>
<version>
1.3.2
</version>
<configuration>
<configurationFile>
src/main/resources/generatorConfig.xml
</configurationFile>
<verbose>
true
</verbose>
<overwrite>
true
</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<configuration>
<!--
如果没有该配置,热部署的
devtools
不⽣效
-->
<fork>
true
</fork>
</configuration>
</plugin>
</plugins>
</build>
3.
添加配置⽂件
src/main/resources
⽬录下新建
application.yml
配置⽂件
4.
添加视图转发
新建
com.xxxx.crm.controller
包,添加系统登录,主⻚⾯转发代码 。
(
这⾥先引⼊
base
包,具体⽂件⻅相关⽬录)
5.
添加静态资源
在
src/main/resources
⽬录下新建
public
⽬录,存放系统相关静态资源⽂件,拷⻉静态⽂件内容到public ⽬录
6.
添加视图模板
在
src/main/resources
⽬录下新建
views
⽬录,添加
index.ftl
、
main.ftl
等⽂件。
(
具体视图⽂件详⻅相关⽬录)
7.
添加应⽤启动类
在
com.xxxx.crm
包下新建
Starter.java
,添加启动项⽬
8.
项⽬⽬录结构
9. 浏览器访问
Chrome
浏览器访问登录⻚地址:
http://localhost:8080/crm/index
6.⽤户登录功能实现
1.⼯具类与⾃定义异常类
将⼯具类与⾃定义异常类,拷⻉到项⽬中。
(
这⾥拷⻉
utils
包和
exceptions
包,具体⽂件⻅相关⽬录
)
2.⾃动⽣成代码
generatorConfig.xml
在
src/main/resources
⽬录下,添加
generatorConfig.xml
配置⽂件。(需要修改数据库驱动路径、数据库账号密码等信息。)
执⾏命令
使⽤
mybatis-generator
⽣成
Mybatis
代码。能够⽣成
vo
类、能⽣成
mapper
映射⽂件(其中包括基
本的增删改查功能)、能⽣成
mapper
接⼝。
2.
核⼼思路分析
⽤户登录
1.
验证参数
姓名 ⾮空判断
密码 ⾮空判断
2.
根据⽤户名,查询⽤户对象
3.
判断⽤户是否存在
⽤户对象为空,记录不存在,⽅法结束
4.
⽤户对象不为空
⽤户存在,校验密码
密码不正确,⽅法结束
5.
密码正确
⽤户登录成功,返回⽤户的相关信息 (定义
UserModel
类,返回⽤户某些信息)
3. 核⼼代码实现
1. UserModel
定义
UserModel
实体类,⽤来返回登录成功后的⽤户信息
2. UserService
⽤户登录具体的业务逻辑的实现
3. UserMapper
在
UserMapper
接⼝类中定义对应的查询⽅法
4. UserMapper.xml
配置查询对应的
SQL
语句
5. UserController
控制层定义接⼝,对接前台。
Controller
层调⽤
Servic
层
userLogin
⽅法,捕获
service
⽅法的异常, 获取登录结果,并将 ResultInfo
对象通过
JSON
格式响应给客户端。
6. Starter
修改启动类,在启动类上添加
@MapperScan
注解,设置扫描包范围。
7. PostMan
测试
利⽤
Postman
⼯具,对⽤户登录的接⼝进⾏测试
8.
前端登录功能实现
index.ftl
添加对应
index.js
,使⽤
layui
表单组件实现表单提交操作。登录成功后
9.
修改
Cookie
的数据
将
Cookie
中的
userId
的值加密存储。
修改
UserModel
中的属性字段,将
Integer
类型的
userId
属性改为
String
类型的
userIdStr
修改
UserService
中对应的⽅法,将
userId
的值加密
修改
index.js
中存储
cookie
的值
10. 主⻚⾯显示⽤户名信息
在
IndexController
控制器中,
main
⽅法转发时,查询登录⽤户信息并放置到
request
域。
11.
启动程序测试登录效果
使⽤测试账号执⾏登录操作。(⽤户名:
admin
,密码:
123
)
7.
密码修改功能实现
1.
核⼼思路分析
⽤户密码修改
1. 参数校验
userId ⾮空
⽤户对象必须存在
oldPassword ⾮空
与数据库中密⽂密码保持⼀致
newPassword ⾮空
与原始密码不能相同
confirmPassword ⾮空
与新密码保持⼀致
2. 设置⽤户新密码
新密码进⾏加密处理
3. 执⾏更新操作
受影响的⾏数⼩于1,则表示修改失败
2. UserService
updateUserPassword
⽅法实现
⽤户密码修改
1. 参数校验
⽤户ID:
userId
⾮空
⽤户对象必须存在
原始密码:oldPassword ⾮空
与数据库中密⽂密码保持⼀致
新密码:newPassword ⾮空
与原始密码不能相同
确认密码:confirmPassword ⾮空
与新密码保持⼀致
2. 设置⽤户新密码
新密码进⾏加密处理
3. 执⾏更新操作
受影响的⾏数⼩于1
,则表示修改失败
注:在对应的更新⽅法上,添加事务控制
验证⽤户密码修改参数
⽤户ID:userId
⾮空
⽤户对象必须存在
原始密码:oldPassword ⾮空
与数据库中密⽂密码保持⼀致
新密码:newPassword ⾮空
与原始密码不能相同
确认密码:confirmPassword
⾮空
与新密码保持⼀致
@param user
@param oldPassword
@param newPassword
@param confirmPassword
3. UserController
updateUserPassword
⽅法实现
⽤户密码修改
4. PostMan 测试
在
Postman
中添加
Cookie
输⼊域名,点击
"Add"
点击
"Add Cookie"
,添加对应的
Cookie
修改
Cookie
对应的名称和值,以及路径,点击
"Save"
保存
关闭
Cookie
窗⼝,重新发送请求测试
5. 前端核⼼代码
1. 添加视图⻚⾯
在
src/main/resources
⽬录的
views
⽬录下,新建
user
⽬录,将
password.ftl
⽂件拷⻉进去
2.
添加⻚⾯转发
在
layuimini
布局⻚⾯,通过点击
"
修改密码
"
,请求后端的
user/toPasswordPage
接⼝
在
UserController
控制层,添加对应的视图转发⽅法
进⼊⽤户密码修改⻚⾯
3.
前端核⼼
JS
准备密码修改⻚对应
JS
⽂件。添加表单提交代码,使⽤
ajax
对接后端密码修改接⼝实现密码修改
操作, 当密码修改后清除客户端
cookie
信息并跳转⾄登录⻚⾯。
4. 测试操作
原始密码:
123
,修改后密码:
123456
,点击保存按钮
8.
⽤户退出功能实现
1.
退出登录
找到
"
退出登录
"
的元素,并绑定点击事件。当⽤户点击退出时,清空
cookie
信息
在
main.js
中,通过类选择器绑定元素的点击事件
*
⽤户退出
*
删除
cookie
*/
$
(
".login-out"
).
click
(
function
() {
//
删除
cookie
$
.
removeCookie
(
"userIdStr"
, {
domain
:
"localhost"
,
path
:
"/crm"
});
$
.
removeCookie
(
"userName"
, {
domain
:
"localhost"
,
path
:
"/crm"
});
$
.
removeCookie
(
"trueName"
, {
domain
:
"localhost"
,
path
:
"/crm"
});
//
跳转到登录⻚⾯
(
⽗窗⼝跳转
)
window
.
parent
.
location
.
href
=
ctx
+
"/index"
;
});
9.全局异常统⼀处理
1. 全局异常实现思路
控制层的⽅法返回的内容两种情况
1.
视图
:
视图异常
2.
Json
:
⽅法执⾏错误 返回错误
json
信息
2.
全局异常拦截器实现
实现
HandlerExceptionResolver
接⼝ ,处理应⽤程序异常信息
3. 消除
try-catch
代码
系统引⼊全局异常,简化控制层
try-catch
代码
10.⾮法请求拦截
对于后端菜单资源,这⾥要求⽤户必须进⾏登录来保护
web
资源的安全性,此时引⼊⾮法请求拦截功能。
1.实现思路
判断⽤户是否是登录状态
获取
Cookie
对象,解析⽤户
ID
的值
如果⽤户ID
不为空,且在数据库中存在对应的⽤户记录,表示请求合法
否则,请求不合法,进⾏拦截,重定向到登录⻚⾯
2.
定义拦截器
在新建
interceptors
包,创建
NoLoginInterceptor
类,并继承
HandlerInterceptorAdapter
适配器,实现拦截器功能。
3.
全局异常类配置
在全局异常处理类中引⼊未登录异常判断
4.
拦截器⽣效配置
新建
config
包,添加拦截器⽣效的配置类
5. 拦截测试
6. 测试拦截效果
当
Cookie
中的⽤户
ID
不存在时,访问
main
⻚⾯,会⾃动跳转到登录⻚⾯
11.
记住我功能实现
记住我功能核⼼在于当⽤户上次登录时如果点击了记住我,下次在重新打开浏览器时可以不⽤选择
登录,此时可以借助拦截器
+ cookie
来实现,当⽤户在登录时,如果⽤户点击了记住我功能,默认设置cookie存储时间为
7
天即可。
1.
修改
index.ftl
在⽤户登录表单中添加记住密码的复选框
<
#
--
记住我
-->
<
div
class
=
"layui-form-item"
>
<
input
type
=
"checkbox"
name
=
"rememberMe"
id
=
"rememberMe"
value
=
"true"
lay
skin
=
"primary"
title
=
"
记住密码
"
>
<
/
div
>
2.
修改
index.js
如果⽤户在登录时,勾选了
"
记住我
"
的复选框,则在登录成功之后,设置
cookie
的有效期