基于Java+jsp的CRM客户关系管理系统的实现

系统的详细设计和实现

根据上文的功能分析和数据库的分析,在系统的实现阶段上采用当今开源的SSH(Struts+Hibernate+Spring)整合框架实现。其目的是降低个模块间的耦合度,使各个模块之间的功能相互独立、模块内部结构清晰。

系统架构如图所示。整个系统是有多个层次的,数据流动的顺序是从浏览器到数据库,再从数据库到浏览器,中间经过service层,action层和dao层。

图5.1系统架构

如图展示的是层次之间的走向是自左到右,每一个层次都是相互依赖的关系。

用户登录这个客户关系管理系统需要在自己的浏览器上访问特定的网址,然后点击某些功能键后系统在段时间内回复用户访问请求,调用逻辑业务层代码接收请求和妆发请求,在执行访问数据库底层代码,请求经过dao层查询数据库并取出数据一步一步返回给上一层,最终把结论呈现在原来的jsp网页给使用者看。

5.1持久层设计

持久层的功能就是接收其他层的请求并且响应其他层次的功能对数据库的进行访问得到数据,持久层的设计就需要设定应用程序和数据库交流的实体类和进行交流的方法。那么这一层就大致有实体对象的持久化类,以及数据访问层接口的实现类等结构。特别说明,持久层使用了开发程序经常使用的Hibernate框架,框架的使用能大大的减小关系型数据库与对象应用程序之间的不能一一对应的缺点,可以把需要处理的数据封装成对象。并且设计的实体类(持久化类),他的结构大概是对象的属性,构造方法(有参和无参),还有自动生成了get()和set()函数。如图为各个功能的类图。

产品管理功能的类图如下

图5.2 产品管理类图

如下为实体类对应的代码:

产品类别:

private Integer id;

private HrEmployee hrEmployee;

private String productCategory;

private Integer parentid;

产品信息:

private Integer productId;

private CrmProductCategory crmProductCategory;

private String productName;

private String specifications;

private String status;

private String unit;

private String remarks;

private Double price;

角色管理类图

图5.3 角色管理类图

角色实体类的代码:

private Integer roleid;

private String rolename;

private String roledscript;

private String childmenus;

private String rolesort;

登录管理和客户管理的类图设计

图5.4 登录管理类图

如下为实体类的代码:

部门类:

private Integer id;

private String DName;

private Integer parentid;

private String DTelephone;

private String DAddress;

private String DEmail;

private String DDescription;

private String DOrder;

职务类:

private Integer id;

private String positionName;

private String positionOrder;

岗位类:

private Integer postId;

private HrPosition hrPosition;

private HrDepartment hrDepartment;

private String postName;

private String positionOrder;

private String postDescript;

员工类:

private Integer id;

private SysRole sysRole;

private HrPost hrPost;

private String uid;

private String pwd;

private String name;

private String idcard;

private Date birthday;

private String email;

private String sex;

private String telephone;

private String status;

private Integer sort;

private Date entrydate;

private String address;

private String remarks;

private String education;

private String professional;

private String schools;

客户管理用例图如图所示:

图5.5 客户管理类图

省市类:

private Integer id;

private Integer parentid;

private String city;

客户类:

private Integer id;

private HrEmployee hrEmployeeByEmployeeId;

private ParamCity paramCityByCityId;

private ParamCity paramCityByProvincesId;

private String serialnumber;

private String customer;

private String address;

private String tel;

private String site;

private String descripe;

private String remarks;

创建关系映射

与数据库的连接

在web-inf下的application-contex。Xml配置文件里定义了连接数据库的数据源,通过数据源,可以将类和数据库中的表进行关联。

<bean id="dataSource"

class="org.apache.commons.dbcp.BasicDataSource">

<property name="driverClassName"

value="com.mysql.jdbc.Driver">

</property>

<property name="url"

value="jdbc:mysql://127.0.0.1:3306/mycrmdb">

</property>

<property name="username" value="root"></property>

<property name="password" value="123456"></property>

</bean>

在定义过程中,数据库的url为jdbc:mysql://127.0.0.1:3306/mycrmdb,用户名为root,数据库密码是123456,驱动类为com.mysql.jdbc.driver。

Hibernate的ORM映射

数据库表的存在和应用程序的java对象之间的一一对应采用的是Hibernate框架所拥有的关系对应(ORM)功能,java持久层组成的结构具有两个部分:Java实体类、数据库的表与实体类对象一一对照的关系映射Hibernate文件。这些事实体能够持久化的基础。

由于表比较多,就以一个crm_customer作为说明。

在MyCrm项目下的com.crm.info包下,存放着该项目的所有持久层对象文件。其中客户信息的实体对象持久类CrmCustomer.java的代码如下:

public CrmCustomer() {}//无参构造函数

public CrmCustomer(HrEmployee hrEmployeeByEmployeeId,

ParamSysparam paramSysparamByCustomertypeId,

ParamSysparam paramSysparamByCustomerlevelId,

HrEmployee hrEmployeeByCreateId, ParamCity paramCityByCityId,

ParamSysparam paramSysparamByCustomersourceId,

HrDepartment hrDepartment,

ParamSysparam paramSysparamByCustomerindustryId,

ParamCity paramCityByProvincesId, String serialnumber,

String customer, String address, String tel, String site,

String descripe, String remarks, String privatecustomer,

Date lastfollow, Date createDate, Integer isdelete,

Date deleteTime, Set crmContacts, Set crmContracts,

Set crmInvoices, Set crmReceives, Set crmFollows, Set crmOrders) {

this.hrEmployeeByEmployeeId = hrEmployeeByEmployeeId;

this.paramSysparamByCustomertypeId = paramSysparamByCustomertypeId;

this.paramSysparamByCustomerlevelId = paramSysparamByCustomerlevelId;

this.hrEmployeeByCreateId = hrEmployeeByCreateId;

this.paramCityByCityId = paramCityByCityId;

this.paramSysparamByCustomersourceId = paramSysparamByCustomersourceId;

this.hrDepartment = hrDepartment;

this.paramSysparamByCustomerindustryId = paramSysparamByCustomerindustryId;

this.paramCityByProvincesId = paramCityByProvincesId;

this.serialnumber = serialnumber;

this.customer = customer;

this.address = address;

this.tel = tel;

this.site = site;

this.descripe = descripe;

this.remarks = remarks;

this.privatecustomer = privatecustomer;

this.lastfollow = lastfollow;

this.createDate = createDate;

this.isdelete = isdelete;

this.deleteTime = deleteTime;

this.crmContacts = crmContacts;

this.crmContracts = crmContracts;

this.crmInvoices = crmInvoices;

this.crmReceives = crmReceives;

this.crmFollows = crmFollows;

this.crmOrders = crmOrders;

}//有参构造函数 ,是用来给变量赋值的

public Integer getId() {

return this.id;

}//对象的get方法

public void setId(Integer id) {

this.id = id;

}//对象的set方法

从代码可看出,持久层不包括任何的业务逻辑代码,只包含有变量定义和变量所拥有的get()、set()函数,是一个单纯的Java对象,目的是有很高的可移植性,提供代码的可重用性。

CrmCustomer.hbm.xml中重要代码如下:

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

//该文件采用的DTD标准

<class name="com.crm.info.CrmCustomer" table="crm_customer" catalog="mycrmdb">//mycrmdb数据库下表crm_customer和CrmCustomer对象对应

<id name="id" type="java.lang.Integer">

<column name="id" /> //主键id的类型是int类型

<generator class="native" />

</id>

<many-to-one name="hrEmployeeByEmployeeId" class="com.crm.info.HrEmployee" fetch="select">

<column name="employee_id">

<comment>负责员工ID FK</comment>

</column>

</many-to-one>//使用了外键

<property name="customer" type="java.lang.String">

<column name="customer" length="250">

<comment>公司名称</comment>

</column>

</property>// 一般的属性定义映射

<class>标签中name属性表示的是持久层类的java全限定名,table属性代表的意思是所使用的数据库表名。Catalog属性表现为使用的数据库的名字。<id>标签中name为实体类属性的名称,type是属性的类型,<column>的name定义该实体类对应数据库表的字段名字。<generator>的class属性表示数据库表之间的关联生产对策。

由此可见,实体类和数据库中的表名在配置文件中都有明确的逐个对应,Hibernate会根据映射文件将实体类转化为数据库表,或者将数据库字段转换为实体类。

在Hibernate中就有映射配置是这样的:

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="dataSource">

<ref bean="dataSource" />

</property>

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">

org.hibernate.dialect.MySQLDialect

</prop>

</props>

</property>

<property name="mappingResources">

<list>

<value>com/crm/info/ParamSysparamType.hbm.xml</value>

<value>com/crm/info/SysMenu.hbm.xml</value>

<value>com/crm/info/ParamCity.hbm.xml</value>

<value>com/crm/info/PersonalEvent.hbm.xml</value>

<value>com/crm/info/MailAttachment.hbm.xml</value>

<value>com/crm/info/CrmProductCategory.hbm.xml</value>

<value>com/crm/info/HrPost.hbm.xml</value>

<value>com/crm/info/HrDepartment.hbm.xml</value>

<value>com/crm/info/HrPosition.hbm.xml</value>

<value>com/crm/info/PersonalNotes.hbm.xml</value>

<value>com/crm/info/CrmProduct.hbm.xml</value>

<value>com/crm/info/CrmCustomer.hbm.xml</value>

<value>com/crm/info/PersonalChat.hbm.xml</value>

<value>com/crm/info/CrmContact.hbm.xml</value>

<value>com/crm/info/ParamSysparam.hbm.xml</value>

<value>com/crm/info/PersonalCalendar.hbm.xml</value>

<value>com/crm/info/SysLogin.hbm.xml</value>

<value>com/crm/info/CrmOrder.hbm.xml</value>

<value>com/crm/info/CrmFollow.hbm.xml</value>

<value>com/crm/info/CrmContract.hbm.xml</value>

<value>com/crm/info/PublicNotice.hbm.xml</value>

<value>com/crm/info/MailFlow.hbm.xml</value>

<value>com/crm/info/PublicNews.hbm.xml</value>

<value>com/crm/info/HrEmployee.hbm.xml</value>

<value>com/crm/info/CrmOrderDetails.hbm.xml</value>

<value>com/crm/info/CrmInvoice.hbm.xml</value>

<value>com/crm/info/CrmReceive.hbm.xml</value>

<value>com/crm/info/SysRole.hbm.xml</value>

<value>com/crm/info/PublicChatRoom.hbm.xml</value>

<value>com/crm/info/SysApp.hbm.xml</value></list>

</property>

</bean>

Struts的配置文件

Struts.xml文件的作用主要是对到来自JSP的请求的接收和跳转分配的作用,该struts的核心配置文件如下:

<package name="myapp" namespace="/" extends="struts-default">

<global-results>

<result name="error" type="redirect">/login.jsp</result>

<result name="ajax">/ajax.jsp</result>

</global-results>

<action name="hr_emp" class="hrEmployeeAction">

<result name="login" type="redirect">/index.jsp</result>

<result name="loginerr">/login.jsp</result>

</action>

</package>

<constant name="struts.ui.theme" value="simple"></constant>

<constant name="struts.multipart.maxSize" value="5242880"></constant>

<include file="com/crm/struts/crm-struts.xml"></include>

<include file="com/crm/struts/hr-struts.xml"></include>

<include file="com/crm/struts/mail-struts.xml"></include>

<include file="com/crm/struts/param-struts.xml"></include>

<include file="com/crm/struts/personal-struts.xml"></include>

<include file="com/crm/struts/public-struts.xml"></include>

<include file="com/crm/struts/sys-struts.xml"></include>

Spring 的配置文件

Spring框架的中心配置文件就是Web.xml,文件里根据自己的需要填写了一些注解文件。利用spring的注解方式进行实例化,action和dao层。

filter>

<filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

</filter>

<filter>

<filter-name>os</filter-name>

<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>os</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<welcome-file-list>

<welcome-file>login.jsp</welcome-file>

</welcome-file-list>

<login-config>

<auth-method>BASIC</auth-method>

</login-config>

</web-app>

DAO层设计

DAO层,原文翻译是Data Access Object,从字面上理解的意思是数据访问对象层次,dao的使用目的就是定义出与数据操作方法有关的逻辑代码,例如:增删改查这样的操作。

按照DAO的设计规则,DAO层里面必须要有操作数据的方法,在com.crm.dao包下存放所有的dao层对象。首要的是通过继承Hibernate框架下的HibernateDaoSupport这个支持类的setSessionFactory()方法并通过Spring的注解进行依赖注入,然后执行getHibernateTemolate()方法得到Hibernate框架的模板类数据,使得执行的速度加快了,方便了开发者。

CrmCustomerDao.java的重要代码。

public List<CrmCustomer> findAllByWhere(CrmCustomeVobj cy) {

if (cy == null) {

return findAll();

}

Criteria c = createCriter(this.getSession(), cy);

return c.add(Restrictions.eq("isdelete", 1)).list();

}

逻辑业务层设计

逻辑业务层是应用程序的业务中心所在,接收从表现层传来的数据,经过逻辑业务层的处理,由持久层存储下来。

业务逻辑类的实现

业务逻辑类的实现是业务逻辑层向上层提供服务的业务实现。只专注于具体的业务逻辑,满足客户多样化的需求。同时,业务逻辑层需要持久层的实例来调用持久层的服务,而持久层的实例可以通过Spring容器的动态注入完成。

@Transactional

@Service("crmCustomerBiz")//动态注入

private CrmCustomerDao crmCustomerDao;//属性的声明

public void setCrmCustomerDao(CrmCustomerDao crmCustomerDao) {

this.crmCustomerDao = crmCustomerDao;

}//构造函数

/**

* 新增对象

* @param customer

* @return

*/

public CrmCustomer addCustomer(CrmCustomer customer) {

customer.setIsdelete(1);

customer.setCreateDate(new Date());

try {

crmCustomerDao.save(customer);

return customer;

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

表现层设计

表现层是面对面和用户交互的,最外表的一层,接受用户数据,提交给模型进行处理,然后模型把结果回馈给用户。贯穿这个层次的是Struts framework。

模型层(M)

模型层是用来处理数据。在模型层里面没有对数据进行业务规格要求上的处理,只是控制流程和业务数据的检查,模型层的支撑代码就是使用业务逻辑层的各个实现类来规则数据。

重要的代码如下所示:

@Scope("prototype")

@Controller("crmCustomerAction")

public void setCrmCustomerBiz(CrmCustomerBiz crmCustomerBiz) {

this.crmCustomerBiz = crmCustomerBiz;

}

public String execute(){

Scopes.getRequestMap().put("bywhere", crmCustomerBiz.findAllByWhere(bwvobj));

return SUCCESS;

}

public String add(){

CrmCustomer newcust = crmCustomerBiz.addCustomer(customer);

contact.setCrmCustomer(newcust);

crmContactBiz.add(contact);

return "add";

}

这个类是处理客户信息的增加的时候的情况。承袭了Struts框架里的ActionSupport这个类,而且依照java的要求重写了execute()函数,该方法就是处理业务流程。在系统实现过程中,还需要spring框架的注解信息可以applicationContext.xml文件里面进行写入。

<aop:config proxy-target-class="true">

<aop:pointcut expression="execution(* com.crm.biz.*.*(..))" id="pc"/>

<aop:advisor advice-ref="adv" pointcut-ref="pc"/>

</aop:config>

视图层(V)

通过Struts的标签和jsp等进行实现的。这个界面直接面对用户,更直接影响用户对该系统的第一感觉,所以说这一层设计和重要。如模型层的代码,如果客户信息添加成功了就会回crm_cus_list.jsp上。

控制层(C)

控制层是是连接视图和模型的关键,两个分离的模块因为控制层而整合在一起,使代码更容易维护。用户请求经过控制层的处理,然后把请求提交给对应的模型层处理。

<action name="crm_cust" class="com.crm.action.CrmCustomerAction">

<result>crm_cus_list.jsp</result>

<result name="toupdate">crm_cus_update.jsp</result>

<result name="add" type="redirectAction">crm_cust</result>

<result name="update" type="redirectAction">crm_cust</result>

<result name="delete" type="redirectAction">crm_cust</result>

<result name="trash">/pages_sys/trash_cus_list.jsp</result>

</action>

系统主要功能模块的实现

登录功能的实现

登录功能所需的界面如图

图5.6 系统登录界面

前端JSP代码如下:

<form class="form-vertical login-form" action="hr_emp!login" method="post" >

<h3 class="form-title" style="text-align: center;">CRM管理系统登录</h3>

<div class="alert alert-error hide">

<button class="close" data-dismiss="alert"></button>

<span>请输入您的用户名和密码.</span>

</div>

<div class="control-group">

<!--ie8, ie9 does not support html5 placeholder, so we just show field title for that-->

<label class="control-label visible-ie8 visible-ie9">用户名</label>

<div class="controls">

<div class="input-icon left">

<i class="icon-user"></i>

<input class="m-wrap placeholder-no-fix" type="text" placeholder="用户名" name="name"/>

</div>

</div>

</div>

<div class="control-group">

<label class="control-label visible-ie8 visible-ie9">密码</label>

<div class="controls">

<div class="input-icon left">

<i class="icon-lock"></i>

<input class="m-wrap placeholder-no-fix" type="password" placeholder="密码" name="pwd"/>

</div>

</div>

</div>

<div class="control-group">

<label class="control-label visible-ie8 visible-ie9">验证码</label>

<div class="controls">

<div class="input-icon left">

<i class="icon-tag"></i>

<input class="m-wrap placeholder-no-fix" type="text" placeholder="验证码" name="inpcode" style="width:100px;"/>

<iframe src="<%=basePath%>hr_emp!ajaxValidateCode" id="iframecode" style="height:34px; width:85px; margin: 0px;" frameborder="0" scrolling="no" ></iframe>

<div style="float: right;" >

<a href="#" id="showcode" class="btn blue" style="width: 28px; height: 20px;"><i class="icon-refresh" style="margin:2px 8px;"></i></a>

</div>

</div>

</div>

</div>

<div class="form-actions">

<button type="submit" class="btn blue pull-right">

登录 <i class="m-icon-swapright m-icon-white"></i>

</button>

</div>

用户输入的账号,密码,验证码通过文本框的post方式提交给hr_struts(hr_rmp!login)下action类。

<action name="hr_emp" class="com.crm.action.HrEmployeeAction">

Hr_emp对应的action实现类为HrEmployAction。

HrEmployAction中的login方法如下:

public String login() {

if (inpcode.equalsIgnoreCase(ValidateCode.code)) {

// 登录

HrEmployee employee = hrEmployeeBiz.login(name, pwd);

if (employee != null) {

if (employee.getCanlogin() == 1) {

Scopes.getSessionMap().put("emp", employee);

List<SysMenuVobj> menuVobjs = sysMenuBiz.findShowMenusByRole(employee.getSysRole());

Scopes.getSessionMap().put("menus", menuVobjs);

sysLoginBiz.add(new SysLogin());

return "login";

} else {

Scopes.getRequestMap().put("err", "您没有权限登录,请联系管理员");

// 您没有权限登录

return "loginerr";

}

} else {

Scopes.getRequestMap().put("err", "您输入账号或密码错误");

// 账户密码错误

return "loginerr";

}

} else {

Scopes.getRequestMap().put("err", "您输入验证码错误");

// 验证码错误

return "loginerr";

}

在Action中,调用了业务逻辑层的biz类进行实例化,在HrEmployeeBiz中有

public HrEmployee login(String name, String pwd) {

return hrEmployeeDao.login(name,pwd);

}

调用了dao层的HrEmployeeDao类中的login方法进行取数据库中的数据,

public HrEmployee login(String name, String pwd) {

return (HrEmployee) this.getSession().createCriteria(HrEmployee.class).add(Restrictions.eq("uid", name))

.add(Restrictions.eq("pwd", pwd)).uniqueResult();

}

从数据库里取出的数据和Jsp传过来的数据进行比较,再把结果返回给action层,最后返回到JSP上显示。需要的效果图如下图所示

图5.7 用户名密码为必填

图5-8 账号和密码错误

图5.9 登录成功

登录管理的时序图

图5.10 登录时序图

客户管理的实现

客户管理时序图如下

图5.11客户管理时序图

前台JSP:

<div class="portlet-body form">

<form action="crm_cust!add" method="post" class="form-horizontal" id="submit_form">

<div class="form-wizard">

<div class="navbar steps">

<div class="navbar-inner">

<ul class="row-fluid">

<li class="span3">

<a href="#tab1" data-toggle="tab" class="step active">

<span class="number">1</span>

<span class="desc"><i class="icon-ok"></i>公司信息</span>

</a>

</li>

<li class="span3">

<a href="#tab2" data-toggle="tab" class="step">

<span class="number">2</span>

<span class="desc"><i class="icon-ok"></i> 主联系人</span>

</a>

</li>

<li class="span3">

<a href="#tab3" data-toggle="tab" class="step">

<span class="number">3</span>

<span class="desc"><i class="icon-ok"></i> 其他</span>

</a>

</li>

<li class="span3">

<a href="#tab4" data-toggle="tab" class="step">

<span class="number">4</span>

<span class="desc"><i class="icon-ok"></i> 确认完成</span>

</a>

</li>

</ul>

</div>

</div>

用户经过填入相关的客户信息,通过post方法,把表单提交到crm_cust上,

<action name="crm_cust" class="com.crm.action.CrmCustomerAction">

<result name="add" type="redirectAction">crm_cust</result>

找到crmcustomerAction的add方法

public String add(){

CrmCustomer newcust = crmCustomerBiz.addCustomer(customer);

contact.setCrmCustomer(newcust);

crmContactBiz.add(contact);

return "add";

}

调用crmcustomerBiz类和crmcustomerDao的add方法

public CrmCustomer addCustomer(CrmCustomer customer) {

customer.setIsdelete(1);

//customer.setHrEmployeeByCreateId((HrEmployee) Scopes.getSessionMap().get("emp"));

customer.setCreateDate(new Date());

// contact.setHrEmployee((HrEmployee)Scopes.getSessionMap().get("emp"));

try {

crmCustomerDao.save(customer);

return customer;

} catch (Exception e) {

e.printStackTrace();

return null;

}

直接调用crmcustomerDao的save方法(这个方法在hibernate里定义),这样客户的数据就保持好了,删除,更新,查询的流程都是这样的,就不一一的列举了。效果图如下

图5.12 客户信息增加界面

本章小结

这一章对系统的详细设计做了一个介绍,结合代码和ssh进行整合对登录和客户信息添加模块模块做了详细的介绍。

系统测试

系统测试综述

测试的目标有

  1. 测试系统登录

  2. 测试系统能正确添加客户信息

测试用例

用户登录模块

用户登录

功能测试

概述

测试编号

Test01

功能描述

用户登录

功能URL

用例目的

测试用户是否能登录成功

前提条件

测试操作

编号

输入/动作

期望的输出响应

实际情况

是否正确

错误编号

1

输入不存在的账号名,不填写密码,输入验证码

请输入您的账号名和密码

请输入您的账号和密码

正确

2

输入正确的账号名输入错误的密码,输入验证码

系统提示账号名或密码错误

系统提示账号名或密码错误

正确

3

输入错误的账号名输入正确的密码,输入验证码

系统提示账号名或密码错误

系统提示账号或密码错误

正确

4

不填写用户名及密码

请输入您的账号和密码

请输入您的账号和密码

正确

5

输入正确的用户名和密码,不输入验证码

验证码必填

验证码必填

正确

6

输入正确的账号和密码,输入验证码

成功登陆

成功登陆

正确

7

输入正确的账号和密码,错误的验证码

输入的验证码错误

您输入的验证码错误

正确

用户登录用例信息

表6-1 登录用例数据

测试内容

测试信息

账号

admin

密码

123

进入主界面,登录成功。

添加客户信息

添加客户信息用例

功能测试

概述

测试编号

Test02

功能描述

添加客户信息

功能URL

用例目的

测试是否能添加客户信息

前提条件

正确进入用户登录界面

测试操作

编号

输入/动作

期望的输出响应

实际情况

是否正确

错误编号

1

输入数据,并提交

能显示出已经提交的数据

显示提交的数据

正确

进入客户列表,测试新增客户功能。

测试用例

表 6-3 添加信息数据

测试内容

测试添加客户信息

公司名称

中国亚信上海分公司

公司网址

www.asiainfo.com

公司电话

13641928647

公司地址

上海市徐汇区漕河泾开发区

所属省市

上海徐汇区

行业

其他

联系人

费新文

联系人电话

18779117396

联系人手机

18779117396

性别

联系人邮箱

2376166307@qq.com

联系人爱好

电子竞技

联系人部门职务

维护部经理

联系人qq

2376166307

联系人地址

上海九亭

联系人备注

很强

公司客户类型

已成交A

公司归属业务员

信息部

公司来源

电话

公司序号

123

公司备注

哈哈

公司状态

公客

提交和能成功的显示在页面上,测试案例成功。

本章小结

这一章通过对CRM客户关系管理系统的两个小功能进行的测试,通过测试用例,成功的将所需要的功能目的展现出来。

总结和展望未来

结论

CRM系统是一个具有新思维的管理机制,通过CRM软件希望能够改变企业和客户之间的传统联系,达到有效的管理和利用企业的客户资源的目标,提高企

业对客户的服务水平,促进市场竞争力的形成,为公司和企业带来财富和效益,CRM客户关系管理系统的研究具备重要的理论目的和实践性。

本课题研究的是是基于java这门语言通过SSH框架结合使用实现的CRM企业客户关系管理系统。主要学到知识有:

  1. 对Struts、Spring、Hibernate三个framework有了初步的使用了解。特别是整合三优秀框架进行开发。

  2. 熟悉三层架构,有利于系统的维护。

  3. 能有效的利用测试原理对系统功能进行测试。

  4. 对jsp有一定的理解。

  5. 在整个系统中,运用到UML统一建模语言对系统的功能模型、对象模型进行设计,并根据系统的需求设计系统功能。在思考如何写入CRM系统代码时,需要严谨的逻辑思维,严格的要求,这篇论文在 MVC三层架构的基础上,采用 J2EE成熟的SSH 框架实现系统的开发。这种开发模式能快速的建立数据库与应用程序之间的联系,同时提高数据的安全性与系统的二次开发性、可重用性等性能。在系统的实现阶段中,应用了组件,很大程度的加强代码的使用效率,提高了开发效率,减少了维护工作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/57339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

听泉鉴宝在三个月前已布局商标注册!

近日“听泉鉴宝”以幽默的风格和节目效果迅速涨粉至2500多万&#xff0c;连线出现“馆藏文物”和“盗墓现场”等内容&#xff0c;听泉鉴宝早在几个月前已布局商标注册。 据普推知产商标老杨在商标局网站检索发现&#xff0c;“听泉鉴宝”的主人丁某所持股的江苏灵匠申请了三十…

视图库对接系列(GA-T 1400)十六-二、视图库对接系列(本级)查询订阅

说明 之前我们在本级中少写了一个查询订阅的接口,这里的话 我们给本级中补充一个功能,实现查询订阅功能。文档 这面我们是向下级发送查询订阅的功能,我们目前测试的话需要手动触发下这个功能, 我们就写一个接口就叫/custom/VIID/Subscribes ,和1400接口的区别是增加了一个…

ffmpeg视频滤镜:双边滤波-bilateral

滤镜简述 bilateral 官网链接 > FFmpeg Filters Documentation 双边滤波是一种图片去噪的方法&#xff0c;它会综合考虑像素的空间和像素值来优化图片&#xff0c;可以看一下如下效果&#xff1a; 左边是 原图&#xff0c;右边是优化后的&#xff0c;相当于磨皮了。 要…

打造高性能在线电子表格:WebGL 渲染引擎 Kola2d 自研之路

导读&#xff1a;本文主要阐述了 Docs 在线表格为打造极致渲染性能所做的关键优化和过程思考&#xff0c;作为首个在在线电子表格领域自研基于WebGL渲染引擎的「吃螃蟹」者&#xff0c;整个过程面临诸多不确定性与挑战&#xff0c;Kola2d 的整体设计在此期间也经历了几轮推倒重…

linux之网络子系统- 地址解析协议arp 源码分析和邻居通用框架

一、arp 的作用 ARP&#xff08;Address Resolution Protocol&#xff0c;地址解析协议&#xff09;是将IP地址解析为以太网MAC地址&#xff08;物理地址&#xff09;的协议。在局域网中&#xff0c;当主机或其他网络设备有数据要发送给另一个主机或设备时&#xff0c;它必须知…

酒店预订订房小程序源码系统 多酒店入驻+打造类似美团的酒店模式 带完整的安装代码包以及搭建部署教程

系统概述 随着移动互联网的普及&#xff0c;小程序因其轻量级、无需下载安装、即用即走的特点&#xff0c;迅速成为各行业的标配。对于酒店预订行业而言&#xff0c;小程序不仅能够有效提升用户体验&#xff0c;还能降低运营成本&#xff0c;提高转化率。本源码系统正是基于这…

企业数字化转型的理论指南:构建未来企业的关键策略与实践路径

数字化转型已经成为当今企业发展和市场竞争的核心驱动力&#xff0c;而在这一过程中&#xff0c;企业架构&#xff08;EA&#xff09;发挥着至关重要的作用。这本白皮书《世界级企业架构&#xff1a;建立和发展EA能力的领导者方法》提供了深入的理论指导&#xff0c;为企业如何…

ToolBox没有进行配置 Failed to initialize Toolboxlibrary

solidworks打开右侧提示 ToolBox没有进行配置跟Failed to initialize Toolboxlibrary 解决方法如下 使用xxclean的扩展功能 SW右侧栏是英文 toolbox配置无效 这个按钮

开源大模型项目,助你效率提高 10 倍

随着 AI 的普及&#xff0c;大家使用 AI 工具的时间越来越长了&#xff0c;尤其因为有了像 GPT-4o 和 Claude 这样强大的 LLM。 今天&#xff0c;我将介绍 21 个开源 LLM 项目&#xff0c;它们可以帮助你构建令人兴奋的内容&#xff0c;并将人工智能集成到你的项目中。 Vanna…

【华为HCIP实战课程十七】OSPF的4类及5类LSA详解,网络工程师

一、5类LSA详解 由ASBR产生,描述到AS外部的路由,通告到所有的区域(除了STUB区域和NSSA区域)。 我们在R6设备配置引入直连路由,R6的lo10 属于区域2 interface LoopBack10 ip address 6.6.6.6 255.255.255.255 ospf enable 1 area 0.0.0.2 [R6-ospf-1]import-route dire…

容灾与云计算概念

​​​​​​基础知识容灾备份——备份技术系统架构与备份网络方案-CSDN博客 SAN&#xff0c;是storage area network的简称&#xff0c;翻译过来就是存储区域网络。 顾名思义&#xff0c;SAN首先是一个网络&#xff0c;其次它是关于存储的&#xff0c;区域则是指服务器和存储资…

膜结构首次应用于国内游轮项目—轻空间

轻空间&#xff08;江苏&#xff09;膜科技有限公司近日成功中标一项国内游轮项目&#xff0c;这一成就标志着膜结构在游轮船舶行业的首次应用&#xff0c;开启了新的市场探索之旅。 作为行业先锋&#xff0c;轻空间始终致力于将创新技术融入多元化场景。本次游轮项目的成功中标…

基于Bert+Attention+LSTM智能校园知识图谱问答推荐系统

获取更多完整项目代码数据集&#xff0c;点此加入免费社区群 &#xff1a; 首页-置顶必看 1. 项目简介 本项目旨在实现基于ALBERT模型的命名实体识别&#xff08;NER&#xff09;任务。ALBERT&#xff08;A Lite BERT&#xff09;是谷歌提出的轻量级BERT模型&#xff0c;具有…

H5开发和微信小程序开发有什么区别

H5开发和微信小程序在开发语言、运行环境以及用户体验等方面存在区别。具体分析如下&#xff1a; 开发语言 H5&#xff1a;基于HTML5的标准&#xff0c;使用HTML、CSS、JavaScript等Web技术进行开发。微信小程序&#xff1a;采用微信自定义的WXML&#xff08;WeiXin Markup Lan…

Claude 3.5重大升级:Sonnet功能提升,Haiku推出在即,开发者抢先体验AI操控电脑新功能

就在今天&#xff0c;Anthropic公司发布了令人兴奋的升级内容&#xff0c;推出了Claude 3.5 Sonnet和全新的Claude 3.5 Haiku。这次更新不仅带来了功能上的重大突破&#xff0c;还引入了AI操控电脑的新功能&#xff0c;掀起了业界的讨论。本文将详细解读这次发布的亮点及其背后…

超详细JDK安装+环境配置教程

安装jdk 1.首先在JDK官网进行下载 JDK会默认安装在C盘 program file文件下 2.并且在JDK安装的过程中会提示安装JRE JDK和JRE会安装在同一目录下 JDK通过命令行进行使用 JDK的目录 以下是JDK对应的目录 bin:存放可执行程序 其中包含java javac命令 Include&#xff1a;本地…

Android摄像头Camera2和Camera1的一些总结

Android 系统对摄像头的同时使用有限制&#xff0c;不能同时使用摄像头进行预览或者录制音视频。 例如&#xff1a;界面上有两个SurfaceView, 这两个SurfaceView不能同时预览或者录制音视频&#xff0c;只能有一个正常工作&#xff08;一个SurfaceView预览前置摄像头&#xff…

H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)

LUA脚本的好处是用户可以根据自己注册的一批API&#xff08;当前TOOL已经提供了几百个函数供大家使用&#xff09;&#xff0c;实现各种小程序&#xff0c;不再限制Flash里面已经下载的程序&#xff0c;就跟手机安装APP差不多&#xff0c;所以在H7-TOOL里面被广泛使用&#xff…

UICollectionView 的UICollectionReusableView复用 IOS18报错问题记录

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 方法复用报错 报错详情&#xff1a; Terminating app due to uncaught exception NSInternal…

无人机电机运行算法

一、电机控制策略 无人机电机通常采用无刷直流电机&#xff08;BLDC&#xff09;或永磁同步电机&#xff08;PMSM&#xff09;&#xff0c;其控制策略主要包括以下几个方面&#xff1a; PID控制&#xff1a; PID&#xff08;Proportional Integral Derivative&#xff09;控…