CRM项目开发【实操篇----市场活动模块】

CRM项目开发【实操篇----市场活动模块】

前言:本项目来源于B站动力节点视频,CRM项目开发
使用的后端技术栈主要是SSM框架,不涉及boot,老师讲的非常细致,推荐
关于流程图部分,由于是老师创作的,就不在这里贴出了,可以B站搜索动力节点的CRM项目,有下载链接,流程图的分析很到位,非常适合用于巩固SSM框架和熟悉业务流程。

01-项目配置文件

  1. 最重要的配置文件——web.xml

    Web项目的核心配置文件,在服务器启动的时候加载,在该文件中导入SSM的配置文件,可以认为是所有其他配置文件的父加载器。

  2. Spring配置文件——applicationContext.xml

    扫描service包下面的注解,导入MyBatis的配置文件

  3. SpringMVC配置文件——applicationContext-mvc.xml

    扫描controller包下面的注解,配置视图解析器,DispatcherServlet分发器

  4. MyBatis配置文件——applicationContext-datasource.xml

    扫描mapper包下面的注解,配置对应的数据源,与数据库连接

web.xml配置applicationContext-mvc.xmlapplicationContext.xml

``applicationContext.xml配置applicationContext-datasource.xml`

  1. pom.xml配置文件——指定maven想配置的文件。

    maven默认情况下只会配置src/main/java下的文件,通过配置maven可以指定目录下的配置文件

02-部署过程及目录结构

  1. 将静态网页放在webapp下面

  2. src\main\javasrc\main\resources两个文件夹中的内容在部署时会被idea生成为classes文件放到webapp\WEB-INF下面

  3. pom.xml的配置文件会被编译为lib文件夹放到webapp\WEB-INF下面

  4. 文件目录树

    webapps

    ​ |–crm(本项目)

    ​ |–WEB-INF

    ​ |–web.xml(web基础配置文件)

    ​ |–classes(项目文件)

    ​ |–lib(经由pom.xml编译得到的一些依赖的jar包)

    ​ |–pages(同样的也是HTML等页面资源,但是外界不可以直接访问)

    ​ |–HTML页面等资源(该目录下的页面外界可以直接访问,存在安全问题,通常存放一些css和img)

    ​ |–stucrm(其他的项目)

  5. webapps下的内容除了WEB-INF下的内容都是可以直接访问的,因此将一些图片和格式文件直接存放在这个目录下;

    webapps/WEB-INF下的内容都是要经过controller处理的,所以要经过一定的保护。

03-首页功能分析与设计

开发基本过程:

分析需求

分析与设计

编码实现

测试

  1. 分析需求

  2. 分析与设计

    controller的创建原则:

    如果两个页面不在同一个目录,新创建一个新的Controller

    一个独立的资源访问目录就代表一个新的Controller

  3. 编码实现

    controller中的方法为什么是public:如果不是最高级别,分发器无法访问。

    @RequestMapping("/")中的路径在理论上应该写全,但是为了简便统一规定必须省略。

    实现的时候使用请求转发?因为WEB-INF中的内容对用户不可见。

    idea对HTML和JSP的默认网页编码格式是不同的,HTML(ISO8859-1)、JSP(UTF-8),在HTML中要显式地指明。

    return的字段是字符串,交给视图解析器处理,视图解析器中已经配置了/,不需要再带/

    
     
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    @RequestMapping("/settings/qx/user/toLogin.do") // 路径有/ ,代表当前的项目
    public String toLogin(){
        // 转发
        return "settings/qx/user/login"; // 路径没有/ ,因为视图解析器中有了
    }
    
  4. 测试

  5. 基本流程图

    客户端发起请求,访问默认路径,默认路径要重定向到登陆页面。

先写底层,再写上层,先完成被调用的对象。

04-登录功能分析与设计

  1. 分析需求

    同步请求与异步请求

    同步请求:整个页面都刷新

    异步请求:局部页面刷新,也可以整个页面都刷新

    所以看情况决定是使用同步请求还是异步请求。

    局部刷新只能用异步,整个页面的刷新优先用同步。

  2. 分析与设计

    service类和Mappar的创建原则:

    与上述的Controller层不同,这两个类的创建原则是根据数据库中的表,如果查的表不同,那么使用的就不一样。

    前台Controller看资源访问路径

    后台serviceMappar看数据库中的表

  3. 编码实现

    流程:

    1. myBatis逆向工程

      导入pom.xml的插件

      添加配置文件

      执行逆向工程

    2. 根据已经生成的Mapper编写Service层

    3. 再反写Controller层

    想把控制层代码中处理好的数据,发送给页面上显示给用户看,一定考虑作用域

    作用域:

    pageContext:一个页面的不同标签之间传递数据,从一个标签中传数据到另一个标签中

    request:一个请求中有效(一次请求)

    session:一个会话中有效(同一个浏览器窗口中的不同请求之间传递数据)

    application:所有的用户都共享的数据,并且频繁使用的

    需要注意的是,逆向工程在执行时不能执行多次,针对同一个表仅仅执行一次,逆向工程默认的是覆盖方法,所以之前写的内容会被覆盖掉。

    BUGThe last packet successfully received from the server was x milliseconds ago

    问题描述:获取到的数据库连接超时

    产生原因: 程序启动时,在跟数据库首次交互时,获得了相应的数据库连接资源,从而进行正常的数据库读写操作。但是在下次进行数据库读写时(我的定时任务本身设置的时间间隔是24小时),应用程序认为这个连接是可以正常使用的(程序执行过一次之后没有退出,这个连接从来并没有被释放掉),但实际上,这个连接已经坏掉了,因为Mysql本身已经把这个连接标记为timeout了。于是,应用程序“傻乎乎”的在这个已经坏掉的数据通道上发起对数据库的读写请求,但是Mysql已经对这些请求不买账了。

    解决方案:在配置数据库连接的url后面加上

    ?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false

  4. 测试

  5. 基本流程图

05-记录密码功能实现和安全退出

  1. 记录密码的实现逻辑

    第一次决定记录密码,向浏览器写Cookie;决定不记录密码,将本地Cookie删除

    第二次后再访问时,判断有没有Cookie,有的话将Cookie一起传到服务器。

  2. 安全退出

06-登陆验证

  1. 路径问题

Controller的方法中,重定向不需要写全路径,这里的重定向借助SpringMVC框架,经过翻译后变成了response.sendRedirect("/crm/")

@RequestMapping("/settings/qx/user/logout.do")
    public String logout(HttpServletResponse response, HttpSession session){
        // 转发,跳转到登陆首页
        Cookie cookie = new Cookie("loginAct", "1");
        cookie.setMaxAge(0);
        response.addCookie(cookie);
        Cookie cookie1 = new Cookie("loginPwd", "1");
        cookie1.setMaxAge(0);
        response.addCookie(cookie1);
        // 销毁session对象
        session.invalidate();
        return "redirect:/";
    }

Interceptor(拦截器)中,重定向路径要写全,这里跟框架没关系了,要自己实现全部内容

public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    HttpSession session = httpServletRequest.getSession();
    User user = (User) session.getAttribute(Constant.SESSION_USER);
    if (user == null){
        httpServletResponse.sendRedirect(httpServletRequest.getContextPath()); // 自己重定向的时候要带上名字
        return false;
    } else {
        return true; // false表示拦截,true表示放行
    }
}
  1. 排除拦截在拦截器中优先级更高,拦截器和排除拦截同时生效的时候,一定是排除拦截优先生效并放行。

07-页面切割技术

  1. 早期技术:进行切割

    :用于切割界面,按照列进行切割,左边20%,中间60%,右边20%;行切割使用rows

    :显示页面,使用url对内容进行填充,显示的是其他页面的内容

    <frameset cols="20% 60% 20%">
    	<frame src="null" name="f1">
    	<frame src="null" name="f2">
    	<frame src="null" name="f3">
    frameset>
    

    每一个都是一个独立的浏览器窗口,只不过面积小一点,通过命名name属性,我们可以在其他超链接中指明在哪个浏览器中打开,是一种重量级的标签。

    
    <a href="url" target="f3">testa>
    
  2. 较新技术: