1.数据库设计
1.1系统用户表
1.2客户信息表
1.3数据字典表
2.系统环境搭建
2.1准备需要的JAR包
由于本系统使用的是SSM框架开发,因此需要准备这三大框架的JAR包。除此之外,项目中还涉及数据库连接、JSTL标签等,所以还要准备其他JAR包。整个系统所需要准备的JAR共计35个,具体如下所示。
1.Spring框架所需的JAR包(10个)
主要包括4个核心模块JAR, AOP开发使用的JAR, JDBC和事务的JAR。
· aopalliance-1.0.jar
· aspectjweaver-1.8.10.jar
· spring-aop-4.3.6.RELEASE.jar
· spring-aspects-4.3.6.RELEASE.jar
· spring-beans-4.3.6.RELEASE.jar
· spring-context-4.3.6.RELEASE.jar
· spring-core-4.3.6.RELEASE.jar
· spring-expression-4.3.6.RELEASE.jar
· spring-jdbc-4.3.6.RELEASE.jar
· spring-tx-4.3.6.RELEASE.jar
2.Spring MVC框架所需要的JAR包(2个)
· spring-web-4.3.6.RELEASE.jar
· spring-webmvc-4.3.6.RELEASE.jar
3.MyBatis框架所需的JAR包(13个)主要包括核心包mybatis-3.4.2.jar,以及其解压文件夹中lib目录下的所有JAR。
· ant-1.9.6.jar
· ant-launcher-1.9.6.jar
· asm-5.1.jar· cglib-3.2.4.jar
· commons-logging-1.2.jar
· javassist-3.21.0-GA.jar
· log4j-1.2.17.jar
· log4j-api-2.3.jar
· log4j-core-2.3.jar
· mybatis-3.4.2.jar
· ognl-3.1.12.jar
· slf4j-api-1.7.22.jar
· slf4j-log4j12-1.7.22.jar
4.MyBatis与Spring整合的中间JAR(1个)
· mybatis-spring-1.3.1.jar
5.数据库驱动JAR包(1个)
· mysql-connector-java-5.1.40-bin.jar
6.数据源dbcp所需JAR包(2个)
· commons-dbcp2-2.1.1.jar
· commons-pool2-2.4.2.jar
7.JSTL标签库JAR包(2个)
· taglibs-standard-impl-1.2.5.jar
· taglibs-standard-spec-1.2.5.jar
8.Jackson框架所需JAR包(3个)
· jackson-annotations-2.8.6.jar
· jackson-core-2.8.6.jar
· jackson-databind-2.8.6.jar
9.Java工具类JAR(1个)
· commons-lang3-3.4.jar
2.2准备数据库资源
方法一:
(1)创建数据库。
create database boot_crm;
(2)选择所创建的数据库。
use boot_crm;
(3)导入数据库文件,这里假设该文件在C盘的根目录下,其导入命令如下。
source C:\boot_crm.sql;
方法二:
通过Navicat软件导入sql文件,创建boot_crm数据库,执行sql
3.3准备项目环境
1创建项目,引入JAR包
在Eclipse中,创建一个名称为boot-crm的Web项目,将系统所准备的全部JAR包复制到项目的lib目录中,并发布到类路径下。
2编写配置文件
(1)在项目目录下创建一个源文件夹config,并在config文件夹下分别创建数据库常量配置文件、Spring配置文件、MyBatis配置文件、log4j配置文件、资源配置文件以及Spring MVC配置文件。
mybatis-config.xml
jdbc.properties(配置数据库信息)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/crm?characterEncoding=utf-8
jdbc.username=root (ZPS)
jdbc.password=root (123456)
log4j.properties(配置日志信息)
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
applicationContext.xml
(需要配置:加载properties文件,数据源,SqlSessionFactory,Mapper扫描)
resource.properties
#客户来源
CUSTOMER_FROM_TYPE=002
#客户行业
CUSTOMER_INDUSTRY_TYPE=001
#客户级别
CUSTOMER_LEVEL_TYPE=006
上述配置代码分别表示客户来源、所属行业和客户级别,其值对应的是数据字典表中dict_type_code字段的值。
springmvc-config.xml
上述代码除配置了需要扫描的包、注解驱动和视图解析器外,还增加了加载属性文件和访问静态资源的配置。
(2)web.xml配置
配置Spring的监听器、编码过滤器和SpringMVC的前端控制器等信息
ssm
index.jsp
contextConfigLocation
classpath:spring/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
encoding
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
encoding
/*
crm
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring/springmvc.xml
1
crm
/
3.引入页面资源将项目运行所需要的CSS文件、字体、图片、JS、自定义标签文件和JSP文件按照图2-1中的结构引入到项目中。
以上步骤完成对于环境的搭建,访问http://localhost:8080/boot-crm/index.jsp进行测试验证,图2-2为项目首页。
3 用户登录模块
BOOT客户管理系统用户登录功能的实现流程如图4-1所示。
可以看出,用户登录过程中首先要验证用户名和密码是否正确,如果正确,可以成功登录系统,系统会自动跳转到主页;如果错误,则在登录页面给出错误提示信息给用户。
实现的具体步骤如下:
1创建持久化类
在src目录下,创建一个com.itheima.crm. pojo包,在包中创建用户持久化类User,并在User类中定义用户相关属性以及相应的getter/setter方法。
User.java
package com.itheima.core.pojo;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer user_id; // 用户id
private String user_code; // 用户账户
private String user_name; // 用户名称
private String use_password; // 用户密码
// getter/setter方法
}
2实现DAO
(1)创建用户DAO层接口。在src目录下,创建一个com.itheima.crm.dao包,在包中创建一个用户接口UserDao,并在接口中编写通过账号和密码查询用户的方法。
UserDao.java
public interface UserDao {
/**
* 通过账户和密码查询用户
* @param usercode
* @param password
* @return
*/
public User findUser(@Param("usercode") String usercode,@Param("password")String password);
}
在上述方法代码的参数中,@Param("usercode")表示为参数usercode命名,命名后,在映射文件的SQL中,使用#{usercode}就可以获取usercode的参数值。
(2)创建映射文件。
在com.itheima.core.dao包中,创建一个MyBatis映射文件UserDao.xml,并在映射文件中编写查询用户信息的执行语句。
上述代码通过映射查询语句来查询系统用户表中的可用用户。
3实现Service
(1)创建用户Service层接口。
在src目录下,创建一个com.itheima.core.service包,在包中创建UserService接口,并在该接口中编写一个通过账号和密码查询用户的方法。
UserService.java
public interface UserService {
/**
* 通过账号和密码查询用户
* @param usercode
* @param password
* @return
*/
public User findUser(String usercode,String password);
}
2)创建用户Service层接口的实现类。
在src目录下,创建一个com.itheima.core.service. impl包,并在包中创建UserService接口的实现类UserServiceImpl,在类中编辑并实现接口中的方法。
UserServiceImpl.java
@Service
@Transactional
public class UserServiceImpl implements UserService {
// 注入Userdao
@Autowired
private UserDao userdao;
@Override
public User findUser(String usercode, String password) {
User user=this.userdao.findUser(usercode, password);
return user;
}
}
在上述代码的findUser()方法中,调用了UserDao对象中的findUser()方法来查询用户信息,并将查询到的信息返回。
4实现Controller
在src目录下,创建一个com.itheima.core.web.controller包,在包中创建用户控制器类UserController。
UserController.java
public class UserController {
@Autowired
private UserService userService;
/**
* 用户登录
* @param usercode
* @param password
* @param model
* @param session
* @return
*/
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(String usercode,String password,Model model,HttpSession session) {
User user= userService.findUser(usercode,password);
if(user!=null) {
//将用户对象添加到Session
session.setAttribute("USER_SESSION", user);
// 跳转到主页面
return "customer";
}
model.addAttribute("msg", "账号或密码错误,请重新登录!");
// 返回到登录页面
return "login";
}
}
上述,首先通过@Autowired注解将UserService对象注入到了本类中,然后创建了一个用于用户登录的login()方法。由于在用户登录时,表单都会以POST方式提交,所以将@RequestMapping注解的method属性值设置为RequestMethod.POST。在login()方法中,首先通过页面中传递过来的账号和密码查询用户,然后通过if语句判断是否存在该用户。如果存在,就将用户信息存储到Session中,并跳转到系统主页面;如果不存在,则提示错误信息,并返回到登录页面。
5实现页面功能
(1)系统默认首页index.jsp主要实现了一个转发功能,在访问时会转发到登录页面。
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
(2)登录页面中,主要包含一个登录表单。
login.jsp
核心代码是用户登录操作的form表单,该表单在提交时会通过check()方法检查账户或密码是否为空,如果为空,则通过标签提示用户“账号或密码不能为空!”;如果账号和密码都已填写,则将表单提交到以“/login.action”结尾的请求中。
6启动项目,测试登录
将项目发布到Tomcat服务器并启动,成功访问登录页面后,即可输入账号和密码登录系统。在执行登录操作之前,先查看一下数据库中sys_user表中的数据。
表sys_user中包含4个账号(user_code)以m开头的用户信息。此时在登录页面中输入账号“m0001”和密码“123”,单击“登录”按钮后,浏览器的显示结果如图6-2所示。
4.2 实现登录验证
虽然在上文已经实现了用户登录功能,但是此功能还并不完善。假设在其他控制器类中也包含一个访问客户管理页面的方法,那么用户完全可以绕过登录步骤,而直接通过访问该方法的方式进入客户管理页面。为了验证上述内容,我们可以在用户控制器类UserController中编写一个跳转到客户管理页面的方法,其代码如下所示。
/**
* 模拟其他类中跳转到客户管理页面的方法
* @return
*/
@RequestMapping(value="/toCustomer.action")
public String toCustomer() {
return "customer";
}
此时,如果通过浏览器访问地址http://localhost:8080/boot-crm/toCustomer.action,浏览器就会直接显示客户管理页面
显然,让未登录的用户直接访问到客户管理页面,是十分不安全的。为了避免此种情况的发生,并提升系统的安全性,我们可以创建一个登录拦截器来拦截所有请求。只有已登录用户的请求才能够通过,而对于未登录用户的请求,系统会将请求转发到登录页面,并提示用户登录,其执行流程如图6-3所示。
实现用户登录验证的具体过程如下。
LoginInterceptor.java
public class LoginInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取请求的URL
String url=request.getRequestURI();
// URL:除了登录请求外,其他的URL都进行拦截控制
if(url.indexOf("/login.action")>=0) {
return true;
}
// 获取session
HttpSession session = request.getSession();
User user = (User)session.getAttribute("USER_SESSION");
// 判断Session中是否有用户数据,如果有,则返回true,继续向下执行
if(user!=null) {
return true;
}
// 不符合条件的给出提示信息,并转发到登录页面
request.setAttribute("msg", "您还没有登录,请先登录!");
request.getRequestDispatcher("/WEB_INF/jsp/login.jsp").forward(request, response);
return false;
}
}
在preHandle()方法中,首先获取了用户URL请求,然后通过请求来判断是否为用户登录操作,只有对用户登录的请求才不进行拦截。接下来获取了Session对象,并获取Session中的用户信息。如果Session中的用户信息不为空,则表示用户已经登录,拦截器将放行;如果Session中的用户信息为空,则表示用户未登录,系统会转发到登录页面,并提示用户登录。
2配置拦截器
在springmvc-config.xml文件中,配置登录拦截器信息,其配置代码如下。
上述配置代码会将所有的用户请求都交由登录拦截器来处理。至此,登录拦截器的实现工作就已经完成。
发布项目并启动Tomcat服务器后,再次通过浏览器访问地址http://localhost:8080/boot-crm/toCustomer.action时,浏览器的显示结果如图6-4所示。
从图6-4可以看出,未登录的用户在执行访问客户管理页面方法后,并没有成功跳转到客户管理页面,而是转发到了系统登录页面,同时在页面的登录窗口中也给出了提示信息。这也就说明用户登录验证功能已成功实现。
4.3退出登录
用户登录模块中还包含一个功能——退出登录。成功登录后的用户会跳转到客户管理页面,并且在页面中会显示已登录的用户名称,如图6-5所示。
实现“退出登录”功能
customer.jsp
从上述代码中可以看出,显示的登录用户名称是通过EL表达式从Session中获取的,而单击“退出登录”链接时,会提交一个以“/logout.action”结尾的请求。为了完成退出登录功能,我们需要在用户控制器类中编写一个退出登录的方法。在方法执行时,需要清除Session中的用户信息,并且在退出登录后,系统要返回到登录页面。因此,需要在用户控制器类UserController中编写退出登录和返回到登录页面的方法,这两个方法的实现代码如下。
/**
* 退出登录
* @param session
* @return
*/
@RequestMapping(value="/logout.action")
public String logout(HttpSession session) {
// 清除Session
session.invalidate();
// 重定向到登录页面的跳转方法
return "redirect:login.action";
}
/**
* 向用户登录页面跳转
* @return
*/
@RequestMapping(value="/logout.action",method= RequestMethod.GET)
public String tologin() {
return "login";
}
至此,“退出登录”的功能代码就已经编写完成。重启项目并登录系统后,单击图6-5中的“退出登录”即可退出系统。
5客户管理模块
客户管理模块是本系统的核心模块,该模块中实现了对客户的查询、添加、修改和下文将对这几个功能的实现进行详细讲解。
5.1 查询客户
在实际应用中,无论是企业级项目,还是互联网项目,使用最多的一定是查询操作。不管是在列表中展示所有数据的操作,还是对单个数据的修改或者删除操作,都需要先查询并展示出数据库中的数据。
查询操作通常可以分为按条件查询和查询所有,但在实际使用时,我们可以将这两种查询编写在一个方法中使用,即当有条件时,就按照条件查询;当没有条件时,就查询所有。同时,由于数据库中的数据可能有很多,如果让这些数据在一个页面中全部显示出来,势必会使页面数据的可读性变得很差,所以我们还需要考虑将这些数据进行分页查询显示。
综合上述分析以及客户页面的显示功能,BOOT客户管理系统的查询功能需要实现的功能如图5-1所示。
从图5-1可以看出,客户管理模块中的查询可分为按照条件查询和分页查询,这两种查询操作所查询出的数据都会显示在客户信息列表中。如果未选择任何条件,那么客户信息列表将分页查询显示出所有数据。
实现客户的条件查询和分页查询
分析:
前台发起请求,需要接收请求过来的查询条件数据,可以使用pojo接收数据,编写QueryVo,里面包含查询条件属性和分页数据。
前台需要分页显示,根据准备好的分页实现,应该返回分页类Page,而创建Page分页类需要数据总条数,所以也需要查询数据总条数的逻辑。
根据分析,DAO需要编写两个方法:
需要根据条件分页查询客户信息
需要根据条件查询数据总条数
1创建持久化类
在com.itheima.core.pojo包中,创建客户持久化类、数据字典持久化类、查询条件包装类。
Customer.java
public class Customer implements Serializable{
private static final long serialVersionUID = 1L;
private Long cust_id;// 客户编号
private String cust_name;// 客户名称
private Long cust_user_id;// 负责人id
private Long cust_create_id;// 创建人id
private String cust_source;// 客户信息来源
private String cust_industry;// 客户所属行业
private String cust_level;// 客户级别
private String cust_linkman;// 联系人
private String cust_phone;// 固定电话
private String cust_mobile;// 移动电话
private String cust_zipcode;// 邮政编码
private String cust_address;// 联系地址
private Date cust_createtime;// 创建时间
//getter setter方法
}
上文声明了与客户数据表对应的属性并定义了各个属性的getter/setter方法。
BaseDict.java
public class BaseDict implements Serializable {
private static final long serialVersionUID = 1L;
private String dict_id;// 数据字典id
private String dict_type_code;// 数据字典类别代码
private String dict_type_name;// 数据字典类别名称
private String dict_item_name; // 数据字典项目名称
private String dict_item_code;// 数据字典项目代码
private Integer dict_sort;// 排序字段
private String dict_enable;// 是否可用
private String dict_memo;// 备注
//getter setter方法
}
上文声明了与数据字典表对应的属性并定义了各个属性的getter/setter方法。
QueryVo.java
public class QueryVo {
private String custName;// 客户名称
private String custSource; // 客户来源
private String custIndustry;// 所属行业
private String custLevel;// 客户级别
private Integer page = 1;// 当前页码数 默认查询第1页
private Integer start;// 起始行 数据库从哪一条数据开始查
private Integer rows = 10; // 所取行数 每页显示数据条数
//getter setter方法
}
受请求参数的QueryVo,里面包含查询条件属性和分页数据。需要注意的是,属性中的star和rows用于执行分页操作,其中start表示分页操作中的起始行,而rows则表示分页中所选取的行数。
2实现DAO层
(1)创建客户DAO层接口和映射文件。
在com.itheima.core.dao包中,创建一个CustomerDao接口,并在接口中编写查询客户列表和客户总数的方法,然后创建一个与接口同名的映射文件。
CustomerDao.java
public interface CustomerDao {
/**
* 根据queryVo分页查询数据
*
* @param queryVo
* @return
*/
List queryCustomerByQueryVo(QueryVo queryVo);
/**
* 根据queryVo查询数据条数
*
* @param queryVo
* @return
*/
Integer queryCountByQueryVo(QueryVo queryVo);
}
CustomerDao.xml
AND a.cust_name LIKE '%${custName}%'
AND a.cust_source = #{custSource}
AND a.cust_industry = #{custIndustry}
AND a.cust_level = #{custLevel}
上文首先编写了一个SQL片段来作为映射查询客户信息的条件,然后编写了查询所有客户的映射查询方法。在方法的SQL中,分别通过左外连接的方式从数据字典表base_dict中的类别代码字段查询出了相应的类别信息,同时通过limit来实现数据的分页查询。最后编写了一个查询客户总数的映射查询语句用于分页使用。
(2)创建数据字典DAO层接口和映射文件。
在com.itheima.core.dao包中,创建一个BaseDictDao接口,并在接口中编写根据类别代码查询数据字典的方法,然后创建一个与接口同名的映射文件。
BaseDictDao.java
public interface BaseDictDao {
/**
* 根据类别代码查询数据
* @param dictTypecode
* @return
*/
public List queryBaseDictByDictTypeCode(String dictTypecode);
}
BaseDictDao.xml
3实现Service层
(1)引入分页标签类。
在src目录下,创建一个com.itheima.common.utils包,在包中引入分页时使用的标签类文件Page.java和NavigationTag.java。
Page.java
public class Page {
private int total;// 总条数
private int page; // 当前页
private int size; // 每页数
private List rows; // 结果集
// getter setter 方法
}
** NavigationTag.java**
/**
* 显示格式:首页 上一页 1 2 3 4 5下一页 尾页
*/
public class NavigationTag extends TagSupport {
static final long serialVersionUID = 2372405317744358833L;
/**
* request 中用于保存Page 对象的变量名,默认为“page”
*/
private String bean = "page";
/**
* 分页跳转的url地址,此属性必须
*/
private String url = null;
/**
* 显示页码数量
*/
private int number = 5;
@Override
public int doStartTag() throws JspException {
JspWriter writer = pageContext.getOut();
HttpServletRequest request =
(HttpServletRequest) pageContext.getRequest();
Page page = (Page) request.getAttribute(bean);
if (page == null)
return SKIP_BODY;
url = resolveUrl(url, pageContext);
try {
// 计算总页数
int pageCount = page.getTotal() / page.getSize();
if (page.getTotal() % page.getSize() > 0) {
pageCount++;
}
writer.print("");
} catch (IOException e) {
e.printStackTrace();
}
return SKIP_BODY;
}
private String append(String url, String key, int value) {
return append(url, key, String.valueOf(value));
}
/**
* 为url 参加参数对儿
*/
private String append(String url, String key, String value) {
if (url == null || url.trim().length() == 0) {
return "";
}
if (url.indexOf("?") == -1) {
url = url + "?" + key + "=" + value;
} else {
if (url.endsWith("?")) {
url = url + key + "=" + value;
} else {
url = url + "&" + key + "=" + value;
}
}
return url;
}
/**
* 为url 添加翻页请求参数
*/
private String resolveUrl(String url,
javax.servlet.jsp.PageContext pageContext) throws JspException {
Map params = pageContext.getRequest().getParameterMap();
for (Object key : params.keySet()) {
if ("page".equals(key) || "rows".equals(key)){
continue;
}
Object value = params.get(key);
if (value == null){
continue;
}
if (value.getClass().isArray()) {
url = append(url, key.toString(), ((String[]) value)[0]);
} else if (value instanceof String) {
url = append(url, key.toString(), value.toString());
}
}
return url;
}
public String getBean() {
return bean;
}
public void setBean(String bean) {
this.bean = bean;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void setNumber(int number) {
this.number = number;
}
}
(2)创建数据字典及客户的Service层接口。
在com.itheima.core.service包中创建一个名称为BaseDictService和CustomerService的接口。
BaseDictService.java
public interface BaseDictService {
/**
* 根据类别代码查询
*
* @param dictTypeCode
* @return
*/
List queryBaseDictByDictTypeCode(String dictTypeCode);
}
CustomerService.java
public interface CustomerService {
/**
* 根据条件分页查询客户
*
* @param queryVo
* @return
*/
Page queryCustomerByQueryVo(QueryVo queryVo);
}
3)创建数据字典及客户Service层接口的实现类。
在com.itheima.core.service.impl包中分别创建数据字典和客户Service层接口的实现类BaseDictServiceImpl和CustomerServiceImpl。
BaseDictServiceImpl.java
@Service
public class BaseDictServiceImpl implements BaseDictService{
@Autowired
private BaseDictDao baseDictDao;
@Override
public List queryBaseDictByDictTypeCode(String dictTypeCode) {
return baseDictDao.queryBaseDictByDictTypeCode(dictTypeCode);
}
}
** CustomerServiceImpl.java**
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerDao customerDao;
@Override
public Page queryCustomerByQueryVo(QueryVo queryVo) {
// 判断参数对象
if(null != queryVo) {
if(StringUtils.isNotBlank(queryVo.getCustName())) {
queryVo.setCustName(queryVo.getCustName());
}
if(StringUtils.isNotBlank(queryVo.getCustSource())) {
queryVo.setCustSource(queryVo.getCustSource());
}
if(StringUtils.isNotBlank(queryVo.getCustIndustry())) {
queryVo.setCustIndustry(queryVo.getCustIndustry());
}
if(StringUtils.isNotBlank(queryVo.getCustLevel())) {
queryVo.setCustLevel(queryVo.getCustLevel());
}
if(StringUtils.isNotBlank(queryVo.getCustName())) {
queryVo.setCustName(queryVo.getCustName());
}
if(StringUtils.isNotBlank(queryVo.getCustName())) {
queryVo.setCustName(queryVo.getCustName());
}
}
// 设置查询条件,从哪一条数据开始查 page和rows有初始值
queryVo.setStart((queryVo.getPage() - 1) * queryVo.getRows());
// 查询数据结果集
List list = this.customerDao.queryCustomerByQueryVo(queryVo);
// 查询到的数据总条数
int total = this.customerDao.queryCountByQueryVo(queryVo);
// 封装返回的page对象
Page page = new Page();
page.setPage(queryVo.getPage());// 当前页 和参数一样
page.setRows(list);// 结果集
page.setSize(queryVo.getRows());// 每页数 和参数一样
page.setTotal(total);// 总条数
return page;
}
在上文的实现方法中,首先判断参数是否为空,然后判断条件查询中的客户名称、信息来源、所属行业和客户级别是否为空,只有不为空时,才添加到参数对象中。接下来获取了页面传递过来的当前页page和每页数信息rows,由此得到起始行start。然后查询所有的客户信息以及客户总数。最后将查询出的所有信息封装到Page对象中并返回。
4实现Controller
在com.itheima.core.controller包中,创建客户控制器类CustomerController。
** CustomerController.java**
@Controller
public class CustomerController {
// 客户来源
@Value("${CUSTOMER_FROM_TYPE}")
private String CUSTOMER_FROM_TYPE;
// 客户行业
@Value("${CUSTOMER_INDUSTRY_TYPE}")
private String CUSTOMER_INDUSTRY_TYPE;
// 客户级别
@Value("${CUSTOMER_LEVEL_TYPE}")
private String CUSTOMER_LEVEL_TYPE;
@Autowired
private BaseDictService baseDictService;
@Autowired
private CustomerService customerService;
/**
* 显示用户列表
* @return
*/
@RequestMapping(value="/customer/list")
public String list(Model model,QueryVo queryVo) {
// 已在tomcat的server.xml中修改了uri的编码为UTF-8,此处代码可不写
// try {
// // 解决get请求乱码问题
// if (StringUtils.isNotBlank(queryVo.getCustName())) {
// queryVo.setCustName(new String(queryVo.getCustName().getBytes("ISO-8859-1"), "UTF-8"));
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// 客户来源
List fromType = baseDictService.queryBaseDictByDictTypeCode(CUSTOMER_FROM_TYPE);
// 所属行业
List industryType =baseDictService.queryBaseDictByDictTypeCode(CUSTOMER_INDUSTRY_TYPE);
// 客户级别
List levelType = baseDictService.queryBaseDictByDictTypeCode(CUSTOMER_LEVEL_TYPE);
// 把前端页面需要显示的数据放到模型中
model.addAttribute("fromType", fromType);
model.addAttribute("industryType", industryType);
model.addAttribute("levelType", levelType);
// 条件、分页查询数据
Page page = this.customerService.queryCustomerByQueryVo(queryVo);
// 把分页查询的结果放到模型中
model.addAttribute("page", page);
// 数据回显
model.addAttribute("custName", queryVo.getCustName());
model.addAttribute("custSource", queryVo.getCustSource());
model.addAttribute("custIndustry", queryVo.getCustIndustry());
model.addAttribute("custLevel", queryVo.getCustLevel());
return "customer";
}
在客户控制器类中,首先声明了customerService和baseDictService属性,并通过@Autowired注解将这两个对象注入到本类中;然后分别定义了客户来源、所属行业和客户级别属性,并通过@Value注解将resource.properties文件中的属性值赋给这3个属性;最后编写了查询客户列表的方法来执行查询操作,其中第1个参数page的默认值为1,表示从第1条开始,第2个参数的默认值为10,表示每页显示10条数据。
5实现页面显示
(1)自定义标签文件主要用于实现分页功能,其标签名称为commons.tld。
commons.tld
2.0
1.2
common
http://itheima.com/common/
Common Tag
Common Tag library
page
com.itheima.common.utils.NavigationTag
JSP
create navigation for paging
url
true
true
bean
true
number
true
在上文中,第13行代码就是我们在使用自定义标签时引入的URI,第23行代码指定了自定义标签的处理器类。
(2)在customer.jsp中,编写条件查询和显示客户列表以及分页查询的代码。
customer.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="itheima" uri="http://itcast.cn/common/"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort() + path + "/";
%>
客户管理-BootCRM
...
客户管理