py-18-PROJECT4(上篇)

目录:

day01:京淘目-权限管理子系统-系统概述

day02:京淘项目-权限管理子系统-配置管理

day03:京淘项目-权限管理子系统-菜单模块

day04:京淘项目-权限管理子系统-角色模块

day05:京淘项目-权限管理子系统-用户模块

day06:京淘项目-权限管理子系统-Shiro安全框架

day07:京淘项目-权限管理子系统-Spring AOP

day08:京淘项目-权限管理子系统-Spring事务管理


 day01:京淘项目-权限管理子系统-系统概述

1.    系统需求概要                                             1
1.1.    系统功能模块需求                             1
1.2.    系统非功能需求                                2
2.    系统架构设计                                             2
2.3.    整体分层架构                                    2
2.4.    MVC架构实现                                   4
3.    系统数据库设计                                          4
3.5.    配置表设计                                        5
3.6.    菜单表设计                                        5
3.7.    角色表设计                                        5
3.8.    组织表设计                                        5
3.9.    用户表设计                                        5
3.10.    角色菜单关系表设计                       6
3.11.    角色用户关系设计                           6
3.12.    日志表设计                                      6
4.    系统环境初始化                                          6
4.13.    创建Maven项目                               6
4.14.    项目技术整合                                  8
4.15.    项目首页设计                                  9
5.    总结                                                          10
5.16.    重点和难点分析                             10
5.17.    常见FAQ                                        10

1.系统需求概要

  1. 系统功能模块需求

本权限管理子系统分为组织管理(部门管理),菜单管理(资源管理),角色管理,用户管理,日志管理,配置管理,系统权限管理(认证 , 授权),退出等.

2.系统非功能需求

非功能性需求是指依一些条件判断系统运作情形或其特性,而不是针对系统特定行为的需求。包括安全性、可靠性、互操作性、健壮性、易使用性、可维护性、可移植性、可重用性、可扩充性。
例如:

2.系统架构设计

3.整体分层架构

对于整个系统采用分层架构设计,目的是更好实现系统的可维护性以及可扩展性.
本项目中的设计采用分层架构思想实现.
  1. 开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行 网关安全控制、流量控制等。
  2. 终端显示层:各个端的模板渲染并执行显示的层。当前主要是 JS 渲染, JSP 渲染,移动端展示等。
  3. Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
  4. Service 层:相对具体的业务逻辑服务层。
  5. Manager 层:通用业务处理层,它有如下特征: 
    1. 对第三方平台封装的层,预处理返回结果及转化异常信息; 
    2. Service 层通用能力的下沉,如缓存方案、中间件通用处理;  
    3. DAO 层交互,对多个 DAO 的组合复用。
  6. DAO 层:数据访问层,与底层 MySQL Oracle Hbase 等进行数据交互。
  7. 外部接口或第三方平台:包括其它部门 RPC 开放接口,基础平台,其它公司的 HTTP 接口

4.MVC架构实现

项目代码基本架构
客户端技术:
  1. HTML,CSS,JS
  2. Bootstrap,AdminLTE,JQuery,Ajax
服务端技术:
  1. CoreJava,Jdbc,Servlet
  2. Spring,SpringMVC,MyBatis,Shiro,DRUID,FastJson,Jackson,Log4j,...
数据库 :
  1. MySql
  2. ......
常用网址:

3.系统数据库设计

数据库名:jtsys
数据库编码:utf-8
数据库表应用引擎:InnoDB
文件寻贴主获得

5.配置表设计

表名: sys_configs
引擎 : InnoDB
字段 :

6.菜单表设计

表名 :sys_menus
引擎 :InnoDB
字段 :

7.角色表设计

表名: sys_roles
引擎 : InnoDB
字段 :

8.组织表设计

表名 :sys_ o rgs
引擎 :InnoDB
字段 :

9.用户表设计

表名:sys_users
引擎 :InnoDB
字段 :

10.角色菜单关系表设计

表名 :sys_role_menus
引擎 :InnoDB
字段 :

11.角色用户关系设计

表名:sys_user_roles
引擎 :InnoDB
字段 :

12.日志表设计

表名:sys_logs
引擎 :InnoDB
字段 :

4.系统环境初始化

13.创建Maven项目

  1. 创建Maven WEB项目(CGB-JT-SYS-V1.01)

step01:
step02:

2.配置Maven WEB 项目

  1. 添加两个maven插件(war ,compile
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<failOnMissingWebXml>flase</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
项目报错需要强制更新Maven项目
3.设置目标运行环境(targeted runtimes)
4.设置编译版本(project facets)
5.设置项目编码(utf-8)
思考 :
  1. 为什么要设置目标运行环境
  2. . ..

14.项目技术整合

  1. 添加项目依赖
Spring-webmvc,jackson,mysql,druid,mybatis,mybatis-spring,
spring-jdbc,log4j,junit
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.23</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- 整合jackson依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

2.添加项目配置文件configs.properties,log4j.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///cgbmybatis
uname:root
password:root
log4j.rootLogger=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%-5p] %c - %m%n
log4j.logger.com.mybatis3=DEBUG
log4j.logger.com.jt=DEBUG

3.创建(3个配置类WebAppInitializer,AppServletConfig,AppRootConfig)

WebAppInitializer.java
public class JtWebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer{
/**
* 此方法负责加载service,dao等对象
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {AppRootConfig.class};
}
/***
* 此方法负责加载Controllers,ViewResolver,HandlerMapper
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return  new Class<?>[] { AppServletConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] {"*.do"};
}

}
AppServletConfig.java
/**扫描com.jt包及子包中使用
*Controller注解修饰的类,并进行加载
*1)includeFilters 用于设置相关加载条件
*/
@Configuration
@ComponentScan("com.jt")
@EnableWebMvc
public class AppServletConfig extends WebMvcConfigurerAdapter {


/**
* 视图解析器
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
super.configureViewResolvers(registry);
registry.jsp("/WEB-INF/pages/", ".html");
}


}
AppRootConfig.java
@Configuration
@PropertySource(value="classpath:config.properties")
public class AppRootConfig {

/**配置DRUID连接池*/
@Lazy(false)
@Bean(value="dataSource",initMethod="init",destroyMethod="close")
public DruidDataSource newDruidDataSource(
@Value("${driver}")  String driver,
@Value("${url}")     String url,
@Value("${uname}")   String username,
@Value("${password}")      String  password) {

DruidDataSource dds = new DruidDataSource();
dds.setDriverClassName(driver);
dds.setUrl(url);
dds.setUsername(username);
dds.setPassword(password);
return dds;
}

/**
* 配置sqlSessionFactory
*/
@Bean("sqlSessionFactory")
public SqlSessionFactoryBean newSqlSessionFactoryBean(
@Autowired DataSource dataSource) throws IOException{
SqlSessionFactoryBean fBean=new SqlSessionFactoryBean();
fBean.setDataSource(dataSource);
Resource[] mapperLocations=
new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/sys/*.xml");
fBean.setMapperLocations(mapperLocations);
return fBean;
}


}

4.拷贝AdminLTE 静态资源文件(CSS,JS,Images)到项目的webapp目录下

文件寻贴主获得
项目报错是因为Eclipse无法识别分散的js文件
5.拷贝 pages 页面文件到项目的WEB-INF目录下
6.部署项目启动运.行tomcat , 检测启动时是否有问题,假如没有问题,整合OK

15.项目首页设计 

业务描述: 创建首页Controller对象,通过此对象的方法呈现首页页面
  1. 创建Controller类
包名:com.jt.sys.controller
类名 : Page Controller
映射 :@RequestMapping("/")

 2.Controller类中添加方法返回首页页面.(starter.html)

方法名:indexUI
参数列表:()
返回值 :String
映射 :@RequestMapping("indexUI")
代码实现:
@RequestMapping("/")
@Controller
public class PageController {
@RequestMapping("doIndexUI")
public String doIndexUI(){
return "starter";
}
}
部署项目:访问
http://localhost:8080/CGB-JT -SYS-V1.01/doIndexUI.do
效果:
3.点击系统管理显示出下拉选项
4.点击配置管理显示右侧信息
代码实现:
5、在controller类中处理请求,相应页面:
6、实现以下效果:

day02:京淘-项目权限管理子系统-配置管理

1.    配置管理列表页面呈现                                                            2
1.1.    服务端实现                                                                     2
1.1.1.    Controller实现                                                       2
1.2.    客户端实现                                                                      3
1.2.2.    首页页面starter.html配置管理事件处理                 3
1.2.3.    创建配置列表页面config_list.html                         4
2.    配置管理列表数据呈现                                                            4
2.3.    服务端实现                                                                      4
2.3.4.    Entity类实现                                                          4
2.3.5.    Dao接口实现                                                         6
2.3.6.    Mapper文件实现                                                    7
2.3.7.    Service接口及实现类                                              9
2.3.8.    Controller类的实现                                                12
2.4.    客户端实现                                                                      15
2.4.9.    列表页面config_list.html配置信息呈现                  15
2.4.10.    列表页面config_list.html分页信息呈现                17
2.4.11.    列表页面config_list.html信息查询实现                19
3.    配置管理删除操作实现                                                             20
3.5.    服务端的实现                                                                   20
3.5.12.    Dao接口实现                                                        20
3.5.13.    Mapper文件实现                                                  21
3.5.14.    Service接口实现                                                   21
3.5.15.    Controller实现                                                      22
3.6.    客户端的实现                                                                   23
3.6.16.    配置列表页面实现                                                23
4.    配置管理添加页面呈现                                                              25
4.7.    服务端实现                                                                       25
4.7.17.    Controller实现                                                        25
4.8.    客户端实现                                                                         26
4.8.18.    配置列表页面实现                                                   26
5.    配置管理数据添加实现                                                                 27
5.9.    服务端实现                                                                          27
5.9.19.    Dao实现                                                                   27
5.9.20.    Mapper实现                                                              28
5.9.21.    Service实现                                                              28
5.9.22.    Controller实现                                                           29
5.10.    客户端实现                                                                          30
5.10.23.    配置管理编辑页面实现                                            30
6.    配置管理编辑页面数据呈现                                                            31
6.11.    服务端实现                                                                          31
6.11.24.    Controller 实现                                                         31
6.12.    客户端实现                                                                          32
6.12.25.    配置列表页面                                                           32
6.12.26.    配置编辑页面                                                           33
7.    配置管理数据更新操作实现                                                             34
7.13.    服务端实现                                                                           34
7.13.27.    Dao实现                                                                   34
7.13.28.    Mapper实现                                                              35
7.13.29.    Service实现                                                              35
7.13.30.    Controller实现                                                           36
7.14.    客户端实现                                                                            37
7.14.31.    编辑页面事件处理                                                      37
8.    总结                                                                                                   38
8.15.    重点和难点分析                                                                      38
8.16.    常见FAQ                                                                                 38

1.配置管理列表页面呈现

1.服务端实现

  1. Controller实现

业务描述
  1. 定义配置管理Controller处理配置管理的客户端请求
  2. 修改首页Controller添加pageUI方法返回page页面
业务实现
  1. 配置管理Controller类的定义
a.包名 com.jt.sys.controller
b.类名SysConfigController
c.映射 /config/

 2.配置管理Controller中方法定义(添加返回页面的相关方法)

a.方法名 doConfigL istUI
b.参数列表(无)
c.返回值类型:String
d.Url映射: doConfigL istUI
代码实现:
@Controller
@RequestMapping("/config/")
public class SysConfigController {
@RequestMapping("doConfigListUI")
public String doConfigListUI(){
return "sys/config_list";
}
}

2.客户端实现

2.首页页面starter.html配置管理事件处理

页面描述
  1. 准备配置列表页面( WEB-INF/pages/sys/config_list.html)
  2. 点击配置管理菜单时异步加载配置列表页面。
业务实现
  1. 事件注册(被点击的元素上)
  2. 事件处理函数定义
代码实现:
$(function(){
$("#load-config-id").click(function(){
$("#mainContentId").load("config/doConfigListUI.do");
});
})
load 函数为jquery中的ajax异步请求函数。

3.创建配置列表页面config_list.html

业务描述
1 ) 在WEB-INF/pages/sys目录下定义config_list.html页面.
2 ) 当页面加载完成以后异步加载分页页面(page .html )。
业务实现
  1. Page Controller中添加do P ageUI方法返回page页面
  2. 在config_list.html页面中异步加载page页面页面
关键代码实现:config_list.html
$(function(){
$("#pageId").load("doPageUI.do");
});

2.配置管理列表数据呈现

3.服务端实现

4.Entity类实现

业务描述:
定义实体封装从数据库查询的数据
业务实现
构建与sys_ configs 表对应的实体类型
a.包名 com.jt.sys.entity
b.类名 SysConfig (实现序列化接口,并定义序列化id)
c.属性 与表(sys_configs)中字段有对应关系
d.方法 set/get/toString
关键代码实现:
public class SysConfig implements Serializable{
private static final long serialVersionUID = 7179456199425880466L;
private Integer id;
private String name;
private String value;
private String note;
private Date createdTime;
private Date modifiedTime;
private String createdUser;
private String modifiedUser;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public Date getModifiedTime() {
return modifiedTime;
}
public void setModifiedTime(Date modifiedTime) {
this.modifiedTime = modifiedTime;
}
public String getCreatedUser() {
return createdUser;
}
public void setCreatedUser(String createdUser) {
this.createdUser = createdUser;
}
public String getModifiedUser() {
return modifiedUser;
}
public void setModifiedUser(String modifiedUser) {
this.modifiedUser = modifiedUser;
}
@Override
public String toString() {
return "SysConfig [id=" + id + ", name=" + name + ", value=" + value + ", note=" + note + ", createdTime="
+ createdTime + ", modifiedTime=" + modifiedTime + ", createdUser=" + createdUser + ", modifiedUser="
+ modifiedUser + "]";
}
}

说明:

通过此对象除了可以封装从数据库查询的数据,还可以封装客户端请求数据,实现层与层之间数据的传递。

5.Dao接口实现

业务描述:(核心-查询当前页显示的数据以及总记录数)
  1. 接收业务层参数数据
  2. 基于参数进行数据查询
  3. 将查询结果进行封装
  4. 将结果返回给业务层对象
代码实现:创建接口并定义相关方法。
  1. D ao 接口定义
a.包名: com.jt.sys.dao 
b.名字: SysConfigDao

 2.方法定义:负责基于条件查询当前页数据

a.方法名:findPageObjects
b.参数列表:(String name,Integer startIndex,Integer pageSize)
c.返回值:List<SysConfig>

 3.方法定义:负责基于条件查询总记录数

a.方法名:getRowCount
b.参数列表:(String name)
c.返回值:int
代码实现:
public interface SysConfigDao {
List<SysConfig> findPageObjects(
@Param("name")String name,
@Param("startIndex")Integer startIndex,
@Param("pageSize")Integer pageSize);
int getRowCount(@Param("name")String name);
}

6.Mapper文件实现

业务描述
  1. 基于Dao接口创建映射文件
  2. 基于Dao方法在映射文件中创建映射元素建映射元素
业务实现:
  1. 创建映射文件
a.包名: mapper.sys
b.文件名: SysConfigMapper.xml
c.命名空间 com.jt.sys.dao.S ys ConfigDao

 2.创建映射元素实现翻页查询操作

a.元素名  select
b.元素id  findPageObjects
c.参数类型 (不写)
d.结果类型 com.jt.sys.entity.Sys Config
e.S QL 定义 select * from sys_configs where name like ? limit ?,?

 3.创建映射元素实现查询统计操作

a.元素名  select
b.元素id  getRowCount
c.参数类型 (不写)
d.结果类型 int
e.S QL 定义 select count (*) from sys_configs where name like ?
代码实现:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jt.sys.dao.SysConfigDao">
<select id="findPageObjects"
resultType="com.jt.sys.entity.SysConfig">
select *
from sys_configs
<include refid="queryWhereId"/>
limit #{startIndex},#{pageSize}
</select>
<select id="getRowCount"
resultType="int">
select count(*)
from sys_configs
<include refid="queryWhereId"/>
</select>
<!-- 借助此元素对共性数据进行提取 -->
<sql id="queryWhereId">
<where>
<if test="name!=null and name!=''">
name like concat("%",#{name},"%")
</if>
</where>
</sql>
</mapper>

7.Service接口及实现类

业务描述:核心业务就是分页查询数据并对数据进行封装。
  1. 通过参数变量接收控制层数据
  2. 对数据进行合法验证
  3. 基于参数数据进行总记录数查询
  4. 基于参数数据进行当前页记录的查询
  5. 对数据进行封装
  6. ..........
业务实现:
  1. 业务值对象定义:(封装分页信息以及当前数据)
a.包名 com.jt.common.vo (封装值的对象)
b.类名 PageObject<T> (实现序列化接口并添加序列化id)
c.属性 (总行数,总页数,当前页码,页面大小,当前页记录信息)
d.方法 (set/get)
代码实现:
public class PageObject<T> implements Serializable {
private static final long serialVersionUID = 6780580291247550747L;//类泛型
/**当前页的页码值*/
private Integer pageCurrent=1;
/**页面大小*/
private Integer pageSize=3;
/**总行数(通过查询获得)*/
private Integer rowCount=0;
/**总页数(通过计算获得)*/
private Integer pageCount=0;
/**当前页记录*/
private List<T> records;
public Integer getPageCurrent() {
return pageCurrent;
}
public void setPageCurrent(Integer pageCurrent) {
this.pageCurrent = pageCurrent;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getRowCount() {
return rowCount;
}
public void setRowCount(Integer rowCount) {
this.rowCount = rowCount;
}
public Integer getPageCount() {
//计算总页数,为什么会在此方法进行计算
//将对象转换为json串时底层调用的是对象的get方法
pageCount=rowCount/pageSize;
if(rowCount%pageSize!=0){
pageCount++;
}
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
public List<T> getRecords() {
return records;
}
public void setRecords(List<T> records) {
this.records = records;
}
}

 2.接口定义:为控制层请求提供服务

a.包名 com.jt.sys.service
b.类名 SysConfigService

 3.接口方法定义:

a.方法名 findPageObjects
b.参数列表 (String name,Integer pageCurrent)
c.返回值 PageObject<SysConfig>
关键代码实现:
public interface SysConfigService {
/**
* 通过此方法实现分页查询操作
* @param name 基于条件查询时的参数名
* @param pageCurrent 当前的页码值
* @return 当前页记录+分页信息
*/
PageObject<SysConfig> findPageObjects(
String name,
Integer pageCurrent);
}

 4.接口实现类的定义:

a.包名 com.jt.sys.service.impl
b.类名 SysConfigServiceImpl
代码实现
@Service
public class SysConfigServiceImpl implements SysConfigService{
@Autowired
private SysConfigDao sysConfigDao;
@Override
public PageObject<SysConfig> findPageObjects(
String name, Integer pageCurrent) {
//1.验证参数合法性
//1.1验证pageCurrent的合法性,
//不合法抛出IllegalArgumentException异常
if(pageCurrent==null||pageCurrent<1)
throw new IllegalArgumentException("当前页码不正确");
//2.基于条件查询总记录数
//2.1) 执行查询
int rowCount=sysConfigDao.getRowCount(name);
//2.2) 验证查询结果,假如结果为0不再执行如下操作
if(rowCount==0)return null;
//3.基于条件查询当前页记录(pageSize定义为2)
//3.1)定义pageSize
int pageSize=2; 
//3.2)计算startIndex
int startIndex=(pageCurrent-1)*pageSize;
//3.3)执行当前数据的查询操作
List<SysConfig> records=
sysConfigDao.findPageObjects(name, startIndex, pageSize);
//4.对分页信息以及当前页记录进行封装
//4.1)构建PageObject对象
PageObject<SysConfig> pageObject=
new PageObject<>();
//4.2)封装数据
pageObject.setPageCurrent(pageCurrent);
pageObject.setPageSize(pageSize);
pageObject.setRowCount(rowCount);
pageObject.setRecords(records);
//5.返回封装结果。
return pageObject;
}
}

8.Controller类的实现

业务描述:核心业务是处理客户端请求
  1. 接收客户端请求中的数据
  2. 基于请求调用业务方法进行请求处理
  3. 对处理结果进行封装(JsonResult)
  4. 将结果转换为json格式的字符串
  5. 将字符串通过服务器输出到客户端。
业务实现:
  1. 值对象定义:(封装控制层方法的返回结果)
a.包名: com.jt.common.vo
b.类名: JsonResult
c.属性: (状态码- int state =1 ,状态信息- String message = "ok" ,正确数据- Object data )
d.方法: (set/get,构造方法)

 2.Controller方法定义:(在SysConfigController中定义请求处理方法)

a.方法名  doFindPageObjects
b.参数列表 (String  name,Integer pageCurrent)
c.返回值  JsonResult
d.映射  doFindPageObjects

 3.统一异常类的定义

b.类名 ControllerExceptionHandler
c.注解 @ControllerAdvice

 4.异常类中方法定义(处理参数异常的方法)

a.方法名 do H andleException
b.参数列表 Runtime Exception
c.返回值 JsonResult
d.注解描述(@ResponseBody,@ExceptionHandler)
关键代码实现:
封装控制层值的对象
public class JsonResult implements Serializable {
private static final long serialVersionUID = -856924038217431339L;//SysResult/Result/R
/**状态码*/
private int state=1;//1表示SUCCESS,0表示ERROR
/**状态信息*/
private String message="ok";
/**正确数据*/
private Object data;
public JsonResult() {
}
public JsonResult(String message){
this.message=message;
}
/**一般查询时调用,封装查询结果*/
public JsonResult(Object data) {
this.data=data;
}
/**出现异常时时调用*/
public JsonResult(Throwable t){
this.state=0;
this.message=t.getMessage();
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}

Controller方法定义

@RequestMapping("doFindPageObjects")
@ResponseBody
public JsonResult doFindPageObjects(String name,Integer pageCurrent){
PageObject<SysConfig> pageObject=
sysConfigService.findPageObjects(name,pageCurrent);
return new JsonResult(pageObject);
}

统一异常类及方法定义

@ControllerAdvice
public class ControllerExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public JsonResult doHandleException(RuntimeException e){
e.printStackTrace();
return new JsonResult(e);
}
}

运行进行测试:

出现以下数据表示成功

4.客户端实现

9.列表页面config_list.html配置信息呈现

业务描述:
  1. 页面加载完成发起异步请求加载配置信息
  2. 通过服务端返回的数据更新当前列表页面
业务实现
  1. 定义doGetObjects()函数,通过此函数执行异步加载操作。
  2. 分页页面加载完成以后调用doGetObjects().
关键代码实现:
 
$(function(){
//为什么要将doGetObjects函数写到load函数对应的回调内部。
$("#pageId").load("pageUI.do",function(){
doGetObjects();
});
}

分页查询函数定义

function doGetObjects(){
//debugger;//断点调试
//1.定义url和参数
var url="config/doFindPageObjects.do"
//? 请问data函数的含义是什么?(从指定元素上获取绑定的数据)
//此数据会在何时进行绑定?(setPagination,doQueryObjects)
var pageCurrent=$("#pageId").data("pageCurrent");
//为什么要执行如下语句的判定,然后初始化pageCurrent的值为1
//pageCurrent参数在没有赋值的情况下,默认初始值应该为1.
if(!pageCurrent) pageCurrent=1;
var params={"pageCurrent":pageCurrent};
//2.发起异步请求
//请问如下ajax请求的回调函数参数名可以是任意吗?可以,必须符合标识符的规范
$.getJSON(url,params,function(result){
//JsonResult->PageObject->List<SysConfigs>+...
//请问result是一个字符串还是json格式的js对象?对象
doSetResponseResult(result);
}
);
}
设置异步响应结果
function doSetResponseResult(result){
if(result.state==1){//ok
//服务端返回的数据为空时,初始化页面内容
if(!result.data){
doInitElementContent();
return;
}
//更新table中tbody内部的数据
setTableBodyRows(result.data.records);//将数据呈现在页面上
//更新页面page.html分页数据
setPagination(result.data);
}else{
alert(result.msg);
} 
}
假如没有记录则初始化当前页面为空,并给出提示
function doInitElementContent(){
//初始化表格tbody中数据
doInitTableBody();
//初始化表格分页信息
doInitPagination();
}
function doInitTableBody(){
var tBody=$("#tbodyId");
tBody.empty();
var tr="<tr><td align='center' colspan=6>没有找到对应记录</td></tr>"
tBody.append(tr);
}
将异步响应结果呈现在table的tbody位置
/*设置表格内容*/
function setTableBodyRows(records){
//1.获取tbody对象,并清空对象
var tBody=$("#tbodyId");
tBody.empty();
//2.迭代records记录,并将其内容追加到tbody
for(var i in records){
//2.1 构建tr对象
var tr=$("<tr></tr>");
//2.2 构建tds对象
var tds=createdTds(records[i]);
//2.3 将tds追加到tr中
tr.append(tds);
//2.4 将tr追加到tbody中
tBody.append(tr);
}
}
创建当前行的td元素
 
function createdTds(row){
var tds="<td><input type='checkbox' class='cBox' name='cItem'
value='"+row.id+"'></td>"+
"<td>"+row.name+"</td>"+
"<td>"+row.value+"</td>"+
"<td>"+new Date(row.createdTime).toLocaleDateString()+"</td>"+
"<td>"+new Date(row.modifiedTime).toLocaleDateString()+"</td>"+
"<td><button type='button' class='btn btn-default
btn-update'>update</button></td>";
return tds;
}

效果:


10.列表页面config_list.html分页信息呈现

业务描述
  1. 配置信息异步加载完成以后初始化分页数据(调用setPagination函数)
  2. 点击分页元素时异步加载当前页(pageCurrent)数据(调用jumpToPage)
业务实现 (page.html页面中定义JS函数)
  1. 定义setPagination方法(实现分页数据初始化)
  2. 定义jumpToPage方法(通过此方法实现当前数据查询)
  3. Page.html页面加载完成以后在对应元素上注册click事件
关键代码实现:
$(function(){
//事件注册
$("#pageId").on("click",".first,.pre,.next,.last",jumpToPage);
});
function jumpToPage(){

//1.获取点击对象的class值
var cla = $(this).prop("class");
//2.基于点击的对象执行pageCurrent值的修改
//2.1获取pageCurrent(当前页码),pageCount(总页数)的当前值
var pageCurrent = $("#pageId").data("pageCurrent");
var pageCount = $("#pageId").data("pageCount");
//2.2修改pageCurrent的值
if(cla=="first"){
pageCurrent = 1;
}else if(cla == "pre"&& pageCurrent>1){
pageCurrent--;
}else if(cla == "next" && pageCurrent<pageCount ){
pageCurrent++;
}else if(cla =="last"){
pageCurrent=pageCount;
}
//3.对pageCurrent值进行重新绑定
$("#pageId").data("pageCurrent",pageCurrent);
//4.基于新的pageCurrent的值进行当前页数据查询
doGetObjects();

}
/**
*页面数据按钮上的文字绑定
*/
function  doInitPagination(){
$(".rowCount").html("总记录数(0)");
$(".pageCount").html("总页数(0)");
$(".pageCurrent").html("当前页(1)");
}
/**
*更新页面page.html分页数据
*/
function setPagination(page){
//1.初始化数据
$(".rowCount").html("总记录数("+page.rowCount+")");
$(".pageCount").html("总页数("+page.pageCount+")");
$(".pageCurrent").html("当前页("+page.pageCurrent+")");
//2.绑定数据(为后续对此数据的使用提供服务)
$("#pageId").data("pageCount",page.pageCount);
$("#pageId").data("pageCurrent",page.pageCurrent);
}
效果:

11.列表页面config_list.html信息查询实现

业务说明
  1. 列表查询按钮事件注册
  2. 列表查询按钮事件处理函数定义
  3. 列表查询参数获取以及传递
业务实现:
  1. 在$ (function(){}) 回调函数中追加查询按钮的事件注册。
  2. 定义查询按钮的事件处理函数doQueryObjects
  3. 重用doGetObjects函数并添加查询参数name
关键代码实现:
查询按钮事件注册
/**
*查询按钮事件注册
*/
$(function (){
$(".input-group-btn").on("click",".btn-search",doQueryObjects);
});

查询按钮事件处理函数定义

/**
*查询按钮事件处理函数定义
*/
function doQueryObjects(){
//为什么要在此位置初始化pageCurrent的值为1?
//数据查询时页码的初始位置也应该是第一页
$("#pageId").data("pageCurrent",1);
//为什么要调用doGetObjects函数?
//重用js代码,简化jS代码编写。
doGetObjects();
}
在分页查询函数中追加name参数定义
/**
*分页查询函数定义
*/
function doGetObjects(){
//debugger;//断点调试
//1.定义url和参数
var url = "config/doFindPageObjects.do";
//? 请问data函数的含义是什么?(从指定元素上获取绑定的数据)
//此数据会在何时进行绑定?(setPagination,doQueryObjects)
var pageCurrent = $("#pageId").data("pageCurrent");
//为什么要执行如下语句的判定,然后初始化pageCurrent的值为1
//pageCurrent参数在没有赋值的情况下,默认初始值应该为1.
if(!pageCurrent) pageCurrent=1;
var params={"pageCurrent":pageCurrent};

//为什么此位置要获取查询参数的值?
//一种冗余的应用方法,目的时让此函数在查询时可以重用。
var name = $("#searchNameId").val();
//将输入框输入的数据绑定到数据(params)上
if(name) params.name=name;
//2.发起异步请求
//请问如下ajax请求的回调函数参数名可以是任意吗?可以,必须符合标识符的规范
$.getJSON(url,params,function(result){
//JsonResult->PageObject->List<SysConfigs>+...
//请问result是一个字符串还是json格式的js对象?对象
doSetResponseResult(result);
});

}
效果图:

3.配置管理删除操作实现

5.服务端的实现

12.Dao接口实现

业务描述
  1. 接收业务层参数数据(String[] ids)
  2. 基于数据执行删除操作
业务实现
在SysConfigDao接口中定义删除方法
  1. 方法名 deleteObjects
  2. 方法参数 (String[] ids)
  3. 方法返回值 int
关键代码实现:
int deleteObjects(@Param("ids")Integer... ids);

13.Mapper文件实现

业务描述
基于SysConfigDao中方法的定义,编写删除元素。
业务实现:
在SysConfigMapper.xml文件中定义删除元素
a.元素名  delete
b.元素id deleteObjects
c.Sql定义 : delete from sys_configs where id in (?,?,?)
关键代码实现:
<delete id="deleteObjects">
delete from sys_configs
where id in
<foreach collection="ids"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</delete>

14.Service接口实现

业务描述
  1. 接收控制层数据并进行合法验证
  2. 基于业务层数据执行删除操作
  3. 对删除过程进行监控(先进行异常捕获)
  4. 对删除结果进行验证并返回
业务实现
在SysConfigService接口及实现类中添加方法
a.方法名 DeleteObjects
b.参数列表  Integer... ids
c.返回值 int
关键代码实现:
 
@Override
public int deleteObjects(Integer... ids) {
//1.验证合法性
if(ids ==null || ids.length ==0) {
throw new IllegalArgumentException("必须要选中删除的内容");
}
//3.执行删除操作
int rows;
try {
rows = sysConfigDao.deleteObjects(ids);
} catch (Throwable e) {
e.printStackTrace();
//发出报警信息(例如给运维人员发短信)
throw new ServiceException("系统故障,正在恢复中...");
}

//4.对结果进行验证
if(rows ==0) {
throw new ServiceException("记录可能已经不存在");
}

return rows;
}

15.Controller实现

业务描述
  1. 接收客户端请求数据
  2. 调用业务层方法执行删除操作
  3. 封装结果并返回
业务实现
在SysConfigController中定义删除方法
  1. 方法名 doDeleteObjects
  2. 参数列表 String ids
  3. 返回值 JsonResult
  4. 映射 doDeleteObjects
关键代码实现:
   
@RequestMapping("doDeleteObjects")
@ResponseBody
public JsonResult doDeleteObjects(Integer... ids){
sysConfigService.deleteObjects(ids);
return new JsonResult("delete ok");
}

6.客户端的实现

16.配置列表页面实现

业务描述:
  1. 页面全选操作实现
  2. 页面删除按钮事件注册
  3. 页面删除操作事件处理函数定义
业务实现:
  1. T head中全选checkbox元素事件注册及事件处理函数 doCheckAll 定义
  2. T body中checkbox元素事件注册及事件处理函数 doChangeCheckAllState 定义
  3. 在$ (function(){}) 回调函数中追加删除按钮的事件注册操作。
  4. 定义事件处理函数d oDeleteObjects, 处理删除按钮的点击操作。
关键代码实现

全选按钮注册

/**
*全选按钮注册
*/
$(function (){
$("thead").on("change","#checkAll",doCheackAll);
});

/**
*tbody中checkbox对象事件注册
*/
$(function (){
$("#tbodyId").on("change",".cBox",doChangeCheckAllState);
});
Tbody中checkbox的状态影响thead中全选元素的状态
  
//当tbody中checkbox的状态发生变化以后
//修改thead中全选元素的状态值。
function doChangeCheckAllState(){
//1.设定默认状态值
var flag=true;
//2.迭代所有tbody中的checkbox值并进行与操作
$("#tbodyId input[name='cItem']")
.each(function(){
flag=flag&$(this).prop("checked")
});
//3.修改全选元素checkbox的值为flag
$("#checkAll").prop("checked",flag);
}
Thead中全选元素的状态影响tbody中checkbox对象状态
/*实现全选操作*/
function doCheckAll(){
//1.获取当前点击对象的checked属性的值
var flag=$(this).prop("checked");//true or false
//2.将tbody中所有checkbox元素的值都修改为flag对应的值。each:元素迭代
//第一种方案
/* $("#tbodyId input[name='cItem']")
.each(function(){
$(this).prop("checked",flag);
}); */
//第二种方案
$("#tbodyId input[name='cItem']")
.prop("checked",flag);
}
删除按钮事件处理函数定义
/**
*查询、删除、按钮事件注册
*/
$(function (){
$(".input-group-btn")
.on("click",".btn-search",doQueryObjects)
.on("click",".btn-delete",doDeleteObjects);
});
/*执行删除操作*/
function doDeleteObjects(){
//1.获取选中的id值
var ids=doGetCheckedIds();
if(ids.length==0){
alert("至少选择一个");
return;
}
//2.发异步请求执行删除操作
var url="config/doDeleteObjects.do";
var params={"ids":ids.toString()};
console.log(params);
$.post(url,params,function(result){
if(result.state==1){
alert(result.message);
doGetObjects();
}else{
alert(result.message);
}
});
}
获取用户选中的记录id并存储到数组
function doGetCheckedIds(){
//定义一个数组,用于存储选中的checkbox的id值
var array=[];//new Array();
//获取tbody中所有名字为cItem的input元素
$("#tbodyId input[name=cItem]").
//迭代这些元素,每发现一个元素都会执行如下回调函数
each(function(){
//假如此元素的checked属性的值为true
if($(this).prop("checked")){
//调用数组对象的push方法将选中对象的值存储到数组
array.push($(this).val());
}
});
return array;
}

4.配置管理添加页面呈现

7.服务端实现

17.Controller实现

业务描述
基于客户端请求返回一个页面
业务实现:
在SysConfigController中添加返回编辑页面的方法
a.方法名 editUI
b.参数列表 ()
c.返回值 String
d.方法映射 editUI
关键代码实现
/**
* 添加页面
*/
@RequestMapping("doConfigEditUI")
public String doConfigEditUI() {
return "sys/config_edit";
}

8.客户端实现

18.配置列表页面实现

业务描述
  1. 添加按钮事件注册
  2. 添加按钮事件处理函数定义
业务实现:
  1. 在$ (function(){}) 事件处理函数内部追加事件注册
  2. 定义表页面中添加按钮的事件处理函数
关键代码实现
列表页面中添加按钮事件注册
/WEB-INF/pages/sys/config_list.html
$(function(){
…
$(".input-group-btn").on("click",".btn-add",doShowEditDialog);
}
点击添加按钮时调用此函数在模态框中动态加载配置管理编辑页面
 
/*以模态框的形式显示编辑页面*/
function doShowEditDialog(){
var url="config/editUI.do";
$("#myModal .modal-body")
.load(url,function(){
$("#myModalLabel").html("添加参数");
//show 显示
$("#myModal").modal('show');
});
}
说明:模态框添加在starter .html 页面

5.配置管理数据添加实现

9.服务端实现

10.Dao实现

业务描述:
  1. 接收业务层数据(SysConfig)
  2. 将数据写入到数据库(ORM)
业务实现:在SysConfigDao接口中定义方法
  1. 方法名 insertObject
  2. 参数列表 SysConfig entity
  3. 返回值 int
关键代码实现:
int insertObject(SysConfig entity);

20.Mapper实现

业务描述
基于SysConfigDao中方法的定义编写SQL元素。
业务实现:
在SysConfigMapper文件中定义insert元素
a.元素名 insert
b.元素id insertObject
c.Sql定义: insert into sys_configs (...) values(?,?,....)
关键代码实现:
 
<insert id="insertObject">
insert into sys_configs
(name,value,note,createdTime,
modifiedTime,createdUser,modifiedUser)
values
(#{name},#{value},#{note},now(),now(),
#{createdUser},#{modifiedUser})
</insert>

21.Service实现

业务描述
  1. 接收控制层数据(SysConfig对象)
  2. 对数据进行合法性验证(非空验证,..)
  3. 将对象通过Dao写入到数据库。
  4. 返回结果。
业务实现:在SysConfigService接口及实现类中定义保存方法
  1. 方法名 doSaveObject
  2. 参数列表 (SysConfig entity)
  3. 返回值 int
关键代码实现:
@Override
public int saveObject(SysConfig entity) {
//1.合法验证
if(entity==null)
throw new IllegalArgumentException("保存对象不能为空");
if(StringUtils.isEmpty(entity.getName()))
throw new IllegalArgumentException("参数名不能为空");
if(StringUtils.isEmpty(entity.getValue()))
throw new IllegalArgumentException("参数值不能为空");
//2.将数据写入到数据库
int rows;
try{
rows=sysConfigDao.insertObject(entity);
}catch(Throwable t){
t.printStackTrace();
//报警....
throw new ServiceException("系统故障,正在恢复");
}
//3.返回结果
return rows;
}

22.Controller实现

业务描述
  1. 接收客户端请求数据并将数据封装到SysConfig对象
  2. 调用业务层方法将数据写入数据库
  3. 对控制层数据进行封装(JsonResult),并返回
业务实现:在SysConfigController类定义保存数据方法
  1. 方法名 doSaveObject
  2. 参数列表 (SysConfig entity)
  3. 方法映射 doSaveObject
关键代码实现:
@RequestMapping("doSaveObject")
@ResponseBody
public JsonResult doSaveObject(SysConfig entity){
sysConfigService.saveObject(entity);
return new JsonResult("save ok");
}

10客户端实现

23.配置管理编辑页面实现

业务描述
  1. 模态框保存按钮点击事件注册
  2. 模态框隐藏事件注册
  3. 定义事件处理函数处理模态框的保存按钮事件。
业务实现:
  1. 在$ (function(){}) 的回调函数中追加事件注册
  2. 定义保存按钮对应的事件处理函数d oSaveOrUpdate
关键代码实现
模态框事件注册
在WEB-INF/pages/ sys/config_edit.html中
$(function(){
$("#myModal").on("click",".btn-save",doSaveOrUpdate);
//注册模态框隐藏时的事件监听
$('#myModal').on('hidden.bs.modal', function (e) {
//移除myMoal对象上绑定的事件
//假如不移除有可能会重现表单重复提交
$("#myModal").off();
});
});
保存按钮的事件处理函数定义
  
function doSaveOrUpdate(){
//1.获取表单数据
var params=doGetFormData();
//2.定义url
var url="config/doSaveObject.do";
//2.将表单数据异步提交到服务端
$.post(url,params,function(result){
if(result.state==1){
alert(result.message);
$("#myModal").modal('hide');
doGetObjects();
} else{
alert(result.message);
}
});
}
点击保存按钮时获取表单数据的函数定义
function doGetFormData(){
var params={
"name":$("#nameId").val(),
"value":$("#valueId").val(),
"note":$("#noteId").val()
};
return params;
}
效果:

6.配置管理编辑页面数据呈现

11.服务端实现

24.Controller 实现

业务描述: 与添加操作共用显示编辑页面的方法。
关键代码:
/**
* 添加页面
*/
@RequestMapping("doConfigEditUI")
public String doConfigEditUI() {
return "sys/config_edit";
}

12.客户端实现

25.配置列表页面

业务描述:
  1. 修改按钮上进行事件注册(借助on方法)
  2. 修改按钮事件处理函数定义(与页面上的添加按钮共用是一个事件处理函数)
  3. 修改tbody中数据呈现的方法,在每个tr上绑定当前行记录。
业务实现:
  1. 在$(function(){})的事件处理函数中追加update按钮的事件注册操作
  2. 修改showEditDialog方法,基于点击对象的不同执行不同业务操作
  3. 在setTableBodyRows方法内部的tr对象上绑定当前行数据
关键代码实现
页面加载完成以后的事件处理
 
$(function(){
....     
//tbody中checkbox对象的事件注册
$("#tbodyId")
.on("click",".btn-update",doShowEditDialog)
});

修改按钮事件处理,在模态框中异步加载编辑页面。

function doShowEditDialog(){
var title;
//基于点击对象的类选择器判定是添加还是修改
if($(this).hasClass("btn-add")){
title="添加参数";
}else if($(this).hasClass("btn-update")){
title="修改参数";
//获取修改按钮对应的当前行记录
var rowData=
$(this).parents("tr").data("rowData");
//将当前行记录绑定到模态框上
//为什么要绑定到此对象?后续编辑页面可以直接从此对象直接获取数据
$("#myModal").data("rowData",rowData);
}
//异步加载编辑页面。
var url="config/editUI.do";
$("#myModal .modal-body").load(url,function(){
$("#myModalLabel").html(title);
$("#myModal").modal('show');
});
}
在列表页面数据呈现时的t r 对象上绑定当前行记录对象。
function setTableBodyRows(records){
//1.获取tbody对象,并清空对象
var tBody=$("#tbodyId");
tBody.empty();
//2.迭代records记录,并将其内容追加到tbody
for(var i in records){
//2.1 构建tr对象
var tr=$("<tr></tr>");
tr.data("rowData",records[i]);
//2.2 构建tds对象
var tds=createdTds(records[i]);
//2.3 将tds追加到tr中
tr.append(tds);
//2.4 将tr追加到tbody中
tBody.append(tr);
}
}

26.配置编辑页面

业务描述
  1. 页面加载完成以后从模块框上获取绑定的数据。
  2. 通过模块框中绑定数据初始页页面表单。
业务实现:
  1. 在$(function(){})事件处理函数中追加获取绑定数据的操作
  2. 定义初始化页面表单数据的函数 doInitFormData();
关键代码实现:
$(function(){
....
//获取模态框绑定的数据
var rowData=$("#myModal").data("rowData");
if(rowData)doInitFormData(rowData);
});
function doInitFormData(rowData){
$("#nameId").val(rowData.name);
$("#valueId").val(rowData.value);
$("#noteId").val(rowData.note);
}

效果:


7.配置管理数据更新操作实现

13.服务端实现

27.Dao实现

业务描述
  1. 接收业务层数据(SysConfig对象)
  2. 将对象更新到数据库。
业务实现
1)在SysConfigDao接口中定义更新方法
a) 方法名 doUpdateObject
B) 参数列表 (SysConfig entity)
C) 返回值 int
关键代码实现:
/**
* 更新配置信息
* @param entity 封装配置信息
* @return 表示更新的行数
*/
int updateObject(SysConfig entity);

28.Mapper实现

业务描述
基于Dao中更新方法的定义编写sql更新元素
业务实现
在SysConfigMapper文件中定义更新元素
a.元素名 update
b.元素id updateObject
c.参数类型 (可选)
d.Sql定义 update sys_configs set .... where id=?
关键代码实现
<update id="updateObject">
update sys_configs
set
name=#{name},
value=#{value},
note=#{note},
modifiedTime=now(),
modifiedUser=#{modifiedUser}
where id=#{id}
</update>

29.Service实现

业务描述
  1. 对参数进行合法验证
  2. 通过dao将数据更新到数据库
  3. 对结果进行验证并返回。
业务实现:
在SysConfigService接口及实现类中定义业务处理方法
a.方法名 updateObject
b.参数列表 SysConfig entity
c.返回值 int
关键代码实现
@Override
public int updateObject(SysConfig entity) {
//1.合法性验证
if(entity==null)
throw new IllegalArgumentException("对象不能为空");
if(StringUtils.isEmpty(entity.getName()))
throw new IllegalArgumentException("参数名不能为空");
if(StringUtils.isEmpty(entity.getValue()))
throw new IllegalArgumentException("参数值不能为空");
//2.将数据更新到数据库
int rows=sysConfigDao.updateObject(entity);
//3.对结果进行验证
if(rows==0)
throw new ServiceException("此记录可能已经不存在");
//4.返回结果(会返回给谁?调用者)
return rows;
}

30.Controller实现

业务描述
  1. 接收客户端请求数据(借助SysConfig对象)
  2. 调用业务层方法更新数据
  3. 对结果进行封装(JsonResult)
  4. 将JsonResult对象转换为Json格式的字符串。
业务实现:
在SysConfigController中添加更新请求对应的处理方法
a.方法名 doUpdateObject
b.参数列表 (SysConfig entity)
c.返回值 JsonResult
d.方法映射 doUpdateObject
关键代码实现:
@RequestMapping("doUpdateObject")
@ResponseBody
public JsonResult doUpdateObject(SysConfig entity){
sysConfigService.updateObject(entity);
return new JsonResult("update ok");
}

14.客户端实现

31.编辑页面事件处理

业务描述
1 ) 编辑页面上点击save按钮时异步更新数据
2) 数据更新完成给出提示信息,隐藏模态框,刷新页面。
业务实现
修改doSaveOrUpdate函数,此函数内部基于模态框绑定的数据判定是添加还是修改。
关键代码实现:
更新操作事件处理函数定义。
/**
*模态框事件注册
*/
$(function(){
$("#myModal").on("click",".btn-save",doSaveOrUpdate);
//注册模态框隐藏时的事件监听
$('#myModal').on('hidden.bs.modal', function (e) {
//移除myMoal对象上绑定的事件
//假如不移除有可能会重现表单重复提交
$("#myModal").off();
//移除模太框绑定的数据
$("#myModal").removeData();
});
//获取模态框绑定的数据
var rowData = $("#myModal").data("rowData");
if(rowData) doInitFormData(rowData);
});
function doSaveOrUpdate(){
//1.获取表单数据
var params=doGetFormData();
var rowData=$("#myModal").data("rowData");
if(rowData)params.id=rowData.id;//修改时需要
//2.定义url
var insertUrl="config/doSaveObject.do";
var updateUrl="config/doUpdateObject.do";
var url=rowData?updateUrl:insertUrl;
//2.将表单数据异步提交到服务端
$.post(url,params,function(result){
if(result.state==1){
alert(result.message);
$("#myModal").modal('hide');
doGetObjects();
} else{
alert(result.message);
}
});
}
效果:
添加:
更新:
避免添加时有数据

 8.总结

15.重点和难点分析

  1. 配置管理整体架构业务分析及实现。
  2. 配置管理持久层映射文件中SQL元素的定义及编写。
  3. 配置管理业务层业务分析,数据封装,异常抛出。
  4. 配置管理控制层请求数据映射,响应数据的封装及转换。
  5. 配置管理客户端JS代码, ajax 异步请求响应的编写及调试。

16.常见FAQ

  1. 配置管理分页查询操作实现
1.1 服务端实现
  1. 配置管理分页数据加载的基本过程?(当前页数据获取,总记录数的获取)
  2. 映射文件中元素共性如何提取?(借助sql元素定义共性,使用include进行包含)
  3. 映射文件中参数的获取?(动态sql参数获取时,dao中的参数尽量使用@param修饰)
  4. 持久层只提供了Dao接口没有提供实现,请问实现类是谁创建的?(Spring)
  5. 配置管理中PageObject的作用是什么?(封装当前页面数据以及分页信息)
  6. 配置管理中JsonResult对象的作用是什么?(封装服务端的响应信息)
  7. 配置管理中的异常处理是如何实现的?(定义统一异常处理类,并对异常进行封装)
  8. 进行异常处理的目的是什么?(提高系统的容错能力,改善用户体验)
  9. 服务端控制层将对象转换为json串时使用的json库是什么?(jackson)
  10. Jackson库中的对象将Date对象转换到json串时默认是怎样的存储的?(long)
  11. 假如将对象转换为json串时,希望日期类型的对象按照自己指定格式进行输出,如何实现?(客户端转换,服务端转换)
  12. .....
1.2 客户端实现
  1. 多个异步请求的顺序问题?(两次异步请求需要有一定的先后顺序)
  2. getJSON函数的应用?(Get方式的ajax请求)
  3. JS对象的创建?(原生的,借助jquery)
  4. JS中的循环?(for(var i in records){})
  5. .....

 2.配置管理删除操作实现?

  1. 服务端

 1.删除方案?(业务层多次删除,数据层同时删除多个) 

 2.映射文件中动态Sql的编写(foreach)

 3.....

 2.客户端

  1. Checkbox值的获取(获取所有checkbox,然后判定选中,最后取选中的值)
  2. 全选操作的实现(业务,change事件处理)
  3. ....

 3.配置管理添加操作实现?

3.服务端
  1. 持久层数据添加操作的定义及实现
  2. 业务层数据保存业务的实现
  3. 控制层请求数据封装,处理,响应。

 4.客户端

  1. 模态框的呈现及隐藏
  2. 模态框事件的绑定以及解绑
4.配置管理修改操作实现?
5.服务端
  1. 持久层数据修改映射操作的定义及实现
  2. 业务层数据修改的实现
  3. 控制请求数据封装,处理,响应。

 6.客户端

  1. 列表页面修改时当前行记录的获取以及绑定
  2. 列表页面修改与添加按钮共用一个事件处理函数,在模态框加载编辑页面。
  3. 编辑页面数据的初始化,点击修改按钮时数据数据的获取以及异步提交操作

day03:京淘-权限管理子系统-菜单模块

1.    菜单页面呈现                                                            2
1.1.    服务端实现                                                      3
1.1.1.    菜单Controller实现                                3
1.2.    客户端实现                                                       3
1.2.2.    定义菜单列表页面                                   3
1.2.3.    首页页面菜单管理事件处理                     3
2.    菜单页面数据呈现                                                      4
2.3.    服务端实现                                                        4
2.3.4.    DAO实现                                                 4
2.3.5.    Mapper实现                                             5
2.3.6.    Service实现                                              6
2.3.7.    Controller实现                                           7
2.4.    客户端实现                                                          7
2.4.8.    菜单列表页面实现                                     7
3.    菜单数据删除                                                              10
3.5.    服务端实现                                                         10
3.5.9.    DAO实现                                                   10
3.5.10.    Mapper实现                                             11
3.5.11.    Service实现                                              13
3.5.12.    Controller实现                                          14
3.6.    客户端实现                                                           15
3.6.13.    列表页面删除按钮事件处理                       15
4.    菜单添加页面呈现                                                          16
4.7.    服务端实现                                                            16
4.7.14.    菜单Controller方法定义                             16
4.8.    客户端实现                                                             17
4.8.15.    菜单编辑页面定义                                       17
4.8.16.    菜单列表页面添加按钮事件处理                 17
5.    菜单编辑页面上级菜单呈现                                             18
5.9.    服务端实现                                                              18
5.9.17.    Node值对象                                                 18
5.9.18.    Dao实现                                                        19
5.9.19.    Mapper实现                                                   19
5.9.20.    Service实现                                                    20
5.9.21.    Controller实现                                                 20
5.10.    客户端实现                                                                21
5.10.22.    菜单编辑页面事件处理                                  21
6.    菜单数据添加操作                                                                23
6.11.    服务端实现                                                                23
6.11.23.    Entity对象定义                                               23
6.11.24.    Dao 实现                                                        23
6.11.25.    Mapper中元素定义                                         24
6.11.26.    Service中方法定义                                          24
6.11.27.    Controller实现                                                 25
6.12.    客户端实现                                                                 26
6.12.28.    保存按钮事件处理                                          26
7.    菜单修改页面数据呈现                                                          27
7.13.    服务端实现                                                                 27
7.13.29.    Controller实现                                                 27
7.14.    客户端实现                                                                  28
7.14.30.    菜单列表页面修改按钮事件处理                      28
7.14.31.    菜单编辑页面事件处理                                    29
8.    菜单数据更新                                                                         30 
8.15.    服务端实现                                                                 30
8.15.32.    Dao 实现                                                         30
8.15.33.    Mapper 实现                                                    30
8.15.34.    Service 实现                                                     31
8.15.35.    Controller实现                                                   32
8.16.    客户端实现                                                                   32
8.16.36.    编辑页面保存按钮事件处理                              32
9.    总结                                                                                        33
9.17.    重点和难点分析                                                           33
9.18.    常见FAQ                                                                      34

1.菜单页面呈现

核心业务
点击系统首页中的菜单管理, 在对应的一个div中
异步加载菜单页面.

1.服务端实现

  1. 菜单Controller实现

业务描述
  1. 定义 controller 对象处理客户端菜单访问请求
  2. 定义相关方法处理列表页面加载需求
业务实现(定义一个Controller类)
  1. 包名 com.jt.sys.controller
  2. 类名 SysMenuController
  3. 映射 @RequestMapping("/menu/")
业务实现(基于 Controller 类定义页面响应方法)
  1. 方法名 doMenuListUI
  2. 参数列表( )
  3. 返回值 String
  4. 映射 @RequestMapping("doMenuListUI")
代码实现:
@RequestMapping("doMenuListUI")
public String doMenuListUI(){
return "sys/menu_list";
}

2.客户端实现

2.定义菜单列表页面

WEB-INF / pages/sys 目录下定义menu_list.html页面 .

3.首页页面菜单管理事件处理

业务描述
1 ) 在starter .html 页面中注册菜单管理的点击事件
2 ) 在starter .html 页面中定义事件处理函数,异步加载菜单列表页面
代码实现:
$(function(){
doLoadUI("#load-menu-id"," menu/doMenuListUI.do");
});
function doLoadUI (domId,url){
$(domId).click(function(){
//异步加载url对应的资源,并将资源插入到.container-fluid位置
$("#mainContentId").load(url,function(){
$("#mainContentId").removeData();
});
});
}

2.菜单页面数据呈现

3.服务端实现

核心业务
从数据库查询菜单以及上一级的菜单信息,
并数据信息进行封装(本模块封装到map),传递 .

4.DAO实现

业务描述
  1. 定义菜单持久层对象,处理数据访问操作
  2. 定义菜单查询方法,查询所有菜单以及上一级菜单信息(只取id,名字)
业务实现:(持久层接口定义 )
  1. 包名: com.jt.sys.dao
  2. 类名 : SysMenuDao
业务实现:(接口方法定义)
  1. 方法名 findObjects  ( 本查询不做分页)
  2. 参数列表()
  3. 返回值 List<Map<String,Object>> ( 一行记录对应一个map,多个map放list)
代码实现:
public interface SysMenuDao {
List<Map<String,Object>> findObjects();
}

5.Mapper实现

业务描述
基于 SysMenuDao 创建 SysMenuMapper 文件,并在文件中
基于 SysMenuDao 的查询方法定义SQL映射元素
业务实现( )
  1. 元素名  select
  2. 元素 id  findObjects
  3. 结果类型 resultType =map
  4. SQL 定义 ( 关联查询本菜单以及上一级菜单相关信息)
代码实现:
<select id="findObjects"
resultType="map">
<!-- 方案1
select c.*,p.name parentName
from sys_menus c left join sys_menus p
on c.parentId=p.id
-->
<!-- 方案2 -->
select c.*,(
select p.name
from sys_menus p
where c.parentId=p.id
) parentName
from sys_menus c
</select>

6.Service实现

业务描述
  1. 定义菜单业务接口,负责处理菜单模块业务
  2. 定义业务方法,访问 dao 层方法获取菜单信息
业务实现 ( 菜单接口定义)
  1. 包名: com.jt.sys.service
  2. 类名 : SysMenuService
业务实现(菜单业务接口方法定义)
  1. 方法名 findObjects
  2. 参数列表()
  3. 返回值 List <Map<String,Object>>
代码实现:
public interface SysMenuService {
List<Map<String,Object>> findObjects();
}
业务实现(菜单业务实现类定义 )
  1. 包名: com.jt.sys.service.impl
  2. 类名 :SysMenuServiceImpl
代码实现:
@Service
public class SysMenuServiceImpl implements SysMenuService {
@Autowired
private SysMenuDao sysMenuDao;
@Override
public List<Map<String, Object>> findObjects() {
return sysMenuDao.findObjects();
}
}

7.Controller实现

业务描述
1 )基于客户端请求,借助业务层对象访问菜单信息
2) 对菜单信息进行封装,并返回.
业务实现( SysMenuController 中方法定义 )
  1. 方法名 doFindObjects
  2. 参数列表()
  3. 返回值 JsonResult
  4. 映射 @RequestMapping("doFindObjects")
代码实现:
@Controller
@RequestMapping("/menu/")
public class SysMenuController {
@Autowired
private SysMenuService sysMenuService;
@RequestMapping("doFindObjects")
@ResponseBody
public JsonResult doFindObjects(){
return new JsonResult(sysMenuService.findObjects());
}
}

4.客户端实现

8.菜单列表页面实现

业务描述
  1. 数据呈现时使用jquery中的treeGrid插件.
  2. 页面加载完成,异步加载数据,以树结构table形式呈现.
业务实现
  1. 引入treeGrid相关 js 文件
  2. 定义方法异步加载数据
代码实现 menu_list.html文件
var columns = [
{
field : 'selectItem',
radio : true
},
{
title : '菜单ID',
field : 'id',
visible : false,
align : 'center',
valign : 'middle',
width : '80px'
},
{
title : '菜单名称',
field : 'name',
align : 'center',
valign : 'middle',
sortable : true,
width : '130px'
},
{
title : '上级菜单',
field : 'parentName',
align : 'center',
valign : 'middle',
sortable : true,
width : '130px'
},
{
title : '类型',
field : 'type',
align : 'center',
valign : 'middle',
sortable : true,
width : '70px',
formatter : function(item, index) {
if (item.type == 1) {
return '<span class="label label-success">菜单</span>';
}
if (item.type == 2) {
return '<span class="label label-warning">按钮</span>';
}
}
},
{
title : '排序号',
field : 'sort',
align : 'center',
valign : 'middle',
sortable : true,
width : '70px'
},
{
title : '菜单URL',
field : 'url',
align : 'center',
valign : 'middle',
sortable : true,
width : '160px'
},
{
title : '授权标识',
field : 'permission',
align : 'center',
valign : 'middle',
sortable : true
} ];
$(document).ready(function(){
doGetObjects();
}
定义页面数据加载方法
function doGetObjects(){
//构建table对象
var table=new TreeTable(
"menuTable", //tableId
"menu/doFindObjects.do", //url
columns);//columns
//设置从哪一列展开内容(默认是第一列)
table.setExpandColumn(2);//可以不写
//初始化table对象(底层发ajax异步请求访问服务端)
table.init();
}
效果:

3.菜单数据删除

核心业务
  1. 查询此菜单有没有对应的子菜单,有则不允许删除
  2. 删除菜单 ( 市场有两种业务)
a.有角色菜单关系数据,则不允许删除
b.有角色菜单关系数据 , 将关系数据一起删除.(本次策略)

5.服务端实现

9.DAO实现

  1. 业务实现:
  2. 基于菜单id查询是否有子菜单(有子菜单则不能删除 )
  3. 根据菜单id删除菜单自身信息 .
  4. 根据菜单id删除角色菜单关系数据
业务实现
  1. 在SysMenuDao接口中定义基于id查询是否有子菜单的方法)
a.方法名 getChildCount
b.参数列表 (Integer id)
c.返回值 int

 2.在SysMenuDao接口中定义根据id删除菜单的方法

a.方法名 deleteObject
b.参数列表 (Integer id)
c.返回值 int

 3.创建基于角色菜单关系表的DAO接口

a.包名: com.jt.sys.dao
b.接口名: SysRoleMenuDao

 4.在SysRoleMenuDao接口中创建基于菜单id删除记录的方法

a.方法名 : deleteObjectsByMenuId
b.参数列表 ( Integer menuId)
c.返回值 int
关键代码实现
SysMenuDao 接口方法定义
 
/**
* 根据菜单id统计子菜单的个数
* @param id
* @return
*/
int getChildCount(Integer id);
/**
* 根据id 删除菜单
* @param id
* @return
*/
int deleteObject(Integer id);

SysRoleMenuDao接口及方法定义

public interface SysMenuDao {
int deleteObjectsByMenuId(Integer menuId);
}

10.Mapper实现

业务描述
基于 SysMenuDao 中方法定义映射元素.
业务实现:
  1. SysMenuMapper中统计子菜单元素定义
a.元素名 select
b.元素 id getChildCount
c.参数类型 int
d.结果类型 int
e.SQL定义 (select count(*) from sys_menus where parentId=#{id})

 2.SysMenuMapper根据id删除菜单的元素定义

a.元素名 delete
b.元素 id deleteObject
c.参数类型 int
d.SQL 定义 (delete from sys_menus where id=#{id})

 3.创建基于SysRoleMenuDao的映射文件

a.包名: mapper.sys
b.文件名SysRoleMenuMapper

 4.SysRoleMenuMapper文件中定义基于菜单id删除记录的元素

a.元素名 delete
b.元素 id deleteObject sByMenuId
c.参数类型 int
d.SQL 定义 (delete from sys_role_menus where menu_id=#{menuId})
关键代码实现
S ysMenuDao 根据 id 统计子菜单
<select id="getChildCount"
parameterType="int"
resultType="int">
select count(*)
from sys_menus
where parentId=#{id}       
</select>
S ysMenuDao 根据 id 删除菜单
<delete id="deleteObject"
parameterType="int">
delete from sys_menus
where id=#{id}
</delete>
S ysRoleMenuDao 根据菜单id删除记录
    
<delete id="deleteObjectsByMenuId"
parameterType="int">
delete from sys_role_menus
where menu_id=#{id}
</delete>

11.Service实现

业务描述
  1. 接收控制数据(id),并对数据进行合法验证
  2. 基于id查询菜单子元素,并进行判定
  3. 删除菜单元素
  4. 删除角色菜单关系数据.
  5. 返回结果.
业务实现(在 SysMenuService 及实现类中定义方法)
  1. 方法名 deleteObject
  2. 参数列表 (Integer id)
  3. 返回值 int
代码实现
接口及方法定义
public interface SysMenuService {
int deleteObject(Integer id);
}
实现类中方法实现
@Service
public class SysMenuServiceImpl implements SysMenuService {
@Autowired
private SysMenuDao sysMenuDao;
@Autowired
private SysRoleMenuDao sysRoleMenuDao;
@Override
public int deleteObject(Integer id) {
//1.验证数据的合法性
if(id==null||id<=0)
throw new ServiceException("请先选择");
//2.基于id进行子元素查询
int count=sysMenuDao.getChildCount(id);
if(count>0)
throw new ServiceException("请先删除子菜单");
//3.删除菜单元素
int rows=sysMenuDao.deleteObject(id);
if(rows==0)
throw new ServiceException("此菜单可能已经不存在");
//4.删除角色,菜单关系数据
sysRoleMenuDao.deleteObjectsByMenuId(id);
//5.返回结果
return rows;
}
}

12.Controller实现

业务描述
  1. 获取客户端请求数据(菜单 id)
  2. 调用业务层方法删除数据
  3. 封装并返回结果
业务实现(在 SysMenuController 中定义相关方法)
  1. 方法名 doDeleteObject
  2. 参数列表 Integer id
  3. 返回值 JsonResult
  4. 映射 @RequestMapping("doDeleteObject")
代码实现
@Controller
@RequestMapping("/menu/")
public class SysMenuController {
@Autowired
private SysMenuService sysMenuService;
@RequestMapping("doDeleteObject")
@ResponseBody
public JsonResult doDeleteObject(Integer id){
sysMenuService.deleteObject(id);
return new JsonResult("delete OK");
}
......
}

6.客户端实现

13.列表页面删除按钮事件处理

业务描述
点击删除按钮时向服务端提交异步请求,删除用户选中的菜单记录.
业务实现:
  1. 删除按钮事件注册
  2. 删除按钮事件处理函数定义.
  /WEB-INF/pages/sys/menu_list.html 代码实现:
$(document).ready(function(){
....
$(".input-group-btn")
.on("click",'.btn-delete',doDeleteObject)
});
执行删除操作
function doDeleteObject(){
//1.获取选中的记录id
var id=getCheckedId();
if(!id){
alert("请先选择");
return;
}
//2.异步提交请求删除数据
var url="menu/doDeleteObject.do";
var params={"id":id};
$.post(url,params,function(result){
if(result.state==1){
alert(result.message);
doGetObjects();
}else{
alert(result.message);
}
});
}
获取选中记录的id值
function getCheckedId(){
//1.获取选中的记录
var selections=$("#menuTable")
//bootstrapTreeTable是treeGrid插件内部定义的jquery扩展函数
//getSelections为扩展函数内部要调用的一个方法
.bootstrapTreeTable("getSelections");
//2.对记录进行判定
if(selections.length==1)
return selections[0].id;
}
效果:

4.菜单添加页面呈现

7.服务端实现

14.菜单Controller方法定义

业务描述
基于客户端的添加请求返回一个响应页面
业务实现(在 SysMenuController 中添加相关方法)
  1. 方法名 doMenuE ditUI
  2. 参数列表 ()
  3. 返回值 String
  4. 映射 @RequestMapping(" doMenuEditUI ")
代码实现:
@RequestMapping("doMenuEditUI")
public String doMenuEditUI(){
return "sys/menu_edit";
}

8.客户端实现

15.菜单编辑页面定义

WEB-INF/pages/sys 目录中添加menu _edit.html.
说明 : 已有就不用添加了.

16.菜单列表页面添加按钮事件处理

业务描述
点击添加按钮异步访问服务器,加载对应菜单编辑页面.
业务实现
  1. 事件注册
  2. 事件处理函数定义
代码实现
/WEB-INF/pages/sys/menu_list.html 事件注册
$(document).ready(function(){
...   
$(".input-group-btn")
.on("click",".btn-add",doLoadEditUI);
});
加载页面
function doLoadEditUI(){
var title;
if($(this).hasClass("btn-add")){
title="添加菜单"
}
var url="menu/doMenuEditUI.do";
$(“ #mainContentId").load(url,function(){
$(".box-title").html(title);
})
}
效果:

5.菜单编辑页面上级菜单呈现

核心业务
  1. 点击编辑页面的上级菜单时向服务端发起异步请求
  2. 服务端基于请求获取菜单节点数据
  3. 客户端通过服务端返回数据异步刷新页面.

  9.服务端实现

  1. 17.Node值对象

业务描述
定义一个Node对象,借助此对象封装从数据库查询到的数据
业务实现 ( 类的定义)
  1. 类名 Node
  2. 接口 实现序列化接口并添加版本id
  3. 字段 (Integer id,String name,Integer parentId) 提供 set/get 方法
代码实现:
public class Node implements Serializable{
private static final long serialVersionUID = -6577397050669133046L;
private Integer id;
private String name;
private Integer parentId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
@Override
public String toString() {
return "Node [id=" + id + ", name=" + name + ", parentId=" + parentId + "]";
}
}

 18.Dao实现

业务描述
基于请求获取数据库对应的菜单表中的所有菜单信息(id,name,parentId)
业务实现( SysMenuDao 中方法定义)
  1. 方法名 findZtreeMenuNodes
  2. 参数列表()
  3. 返回值 List<Node>
代码实现:
List<Node> findZtreeMenuNodes();

19.Mapper实现

业务描述
基于Sys MenuDao 中方法定义菜单节点查询元素.
业务实现(SysMenuMapper中元素定义)
  1. 元素名 select
  2. 元素 id findZtreeMenuNodes
  3. 结果类型 com .jt.common.vo.Node
  4. SQL 定义 (select id,name,parentId from sys_menus)
代码实现:
  
<select id="findZtreeMenuNodes" resultType="com.jt.common.vo.Node">
select id,name,parentId
from sys_menus
</select>

 20.Service实现

业务描述
基于客户端请求,借助dao对象,访问菜单节点信息,并返回 .
业务实现(SysMenuService接口及实现类中方法定义)
  1. 方法名 findZtreeMenuNodes
  2. 参数列表()
  3. 返回值 List<Node>
代码实现.
@Override
public List<Node> findZtreeMenuNodes() {
return sysMenuDao.findZtreeMenuNodes();
}

21.Controller实现

业务描述
基于客户端请求,访问业务层对象方法,获取菜单节点对象,并封装返回.
业务实现( SysMenuController 中方法定义)
  1. 方法名 doFindZtreeMenuNodes
  2. 参数列表()
  3. 返回值 JsonResult
  4. 映射 @RequestMapping("doFindZtreeMenuNodes");
代码实现:
    
@RequestMapping("doFindZtreeMenuNodes")
@ResponseBody
public JsonResult doFindZtreeMenuNodes(){
return new JsonResult(
sysMenuService.findZtreeMenuNodes(),
"query ok");
}

10.客户端实现

22.菜单编辑页面事件处理

业务描述
点击上级菜单时,异步加载菜单节点信息,并进行数据呈现 .
业务实现
  1. 点击事件注册
  2. 事件处理函数定义
 WEB-INF/pages/sys/menu_edit.html
代码实现:
var zTree;
//初始化zTree时会用到
var setting = {
data : {
simpleData : {
enable : true,
idKey : "id",  //节点数据中保存唯一标识的属性名称
pIdKey : "parentId",  //节点数据中保存其父节点唯一标识的属性名称
rootPId : null  //根节点id
}
}
}
页面加载完成,异步加载数据,事件注册
 
$(document).ready(function(){
$(".form-horizontal")
.on("click",".load-sys-menu",doLoadZtreeNodes);//初始化树结构
$("#menuLayer")
.on("click",".btn-confirm",doSetSelectNode)//确定 获取选中的节点
.on("click",".btn-cancel",doHideTree)//取消
});
设置选中的节点对象 (这里坑过)
function doSetSelectNode(){
//1.获取选中的节点对象
var nodes=zTree.getSelectedNodes();
if(nodes.length==0) {
alert("请选中"); 
return;
}
var node=nodes[0];
console.log(node);
//2.将对象中内容,填充到表单
$("#parentId").data("parentId",node.id);
$("#parentId").val(node.name);
//3.隐藏树对象
doHideTree();
}
点击树div的确定和取消按钮时隐藏树对象
function doHideTree(){
$("#menuLayer").css("display","none");
}
加载树节点信息,并初始化树结构 
function doLoadZtreeNodes(){
//显示div
$("#menuLayer").css("display","block");
var url="menu/doFindZtreeMenuNodes.do";
//异步加载数据,并初始化数据
$.getJSON(url,function(result){
if(result.state==1){
//使用init函数需要先引入ztree对应的js文件
zTree=$.fn.zTree.init(
$("#menuTree"),
setting,
result.data);
}else{
alert(result.message);
}
})
}

效果:


6.菜单数据添加操作

11.服务端实现

核心业务描述
点击页面保存按钮时,获取菜单表单数据,异步提交到服务器端。

 23.Entity对象定义

业务描述
创建实体类封装客户端请求中的的菜单数据
类的定义
  1. 包名:com.jt.sys.entity
  2. 类名:SysMenu
类中属性及方法定义
  1. 实现序列化接口并添加序列化版本id
  2. 属性与表(sys_menus)中字段有对应关系
  3. 提供set/get方法,无参数构造方法,重写toString方法
public class SysMenu extends BaseEntity implements Serializable{
private static final long serialVersionUID = -5259265803332215029L;
/**菜单id*/
private Integer id;
/**菜单名*/
private String name;
/**菜单对应的url*/
private String url;
/**菜单类型*/
private Integer type;
/**菜单的排序号*/
private Integer sort;
/**备注*/
private String note;
/**菜单的父id*/
private Integer parentId;
/**权限标识*/
private String permission;
private Date createdTime;
private Date modifiedTime;
private String createdUser;
private String modifiedUser;

}

 24.Dao 实现

业务描述
SysMenuDao 中添加插入数据的方法,用于将菜单信息写入到数据库
业务实现:
SysMenuDao 接口方法定义
  1. 方法名 insertObject
  2. 返回值 int
  3. 参数列表 ( SysMenu entity)
方法定义
int insertObject(SysMenu entity);

 25.Mapper中元素定义

业务描述
基于SysMenuDao中方法定义SQL映射元素。
业务实现
在Sys MenuMapper 中定义 insert 元素
  1. 元素名 insert
  2. 元素id insertObject
  3. 参数类型 com.jt.sys.entity.SysMenu
  4. Sql 定义 insert into …
关键代码实现 
<insert id="insertObject"    
parameterType="com.jt.sys.entity.SysMenu">
insert into sys_menus
(name,url,type,sort,note,parentId,permission,
createdTime,modifiedTime,createdUser,modifiedUser)
values
(#{name},#{url},#{type},#{sort},#{note},#{parentId},
#{permission},now(),now(),#{createdUser},
#{modifiedUser})
</insert>

26.Service中方法定义

业务描述
  1. 获取页面中数据,并对数据进行合法验证
  2. 将数据写入到数据库
  3. 判定结果,并返回
业务实现:
在SysMenuService接口及实现类添加相关方法)
  1. 方法名saveObject
  2. 返回值 int
  3. 参数列表 (Sys Menu entity
关键代码实现
@Override
public int saveObject(SysMenu entity) {
//1.合法验证
if(entity==null)
throw new ServiceException("保存对象不能为空");
if(StringUtils.isEmpty(entity.getName()))
throw new ServiceException("菜单名不能为空");
int rows;
//2.保存数据
try{
rows=sysMenuDao.insertObject(entity);
}catch(Exception e){
e.printStackTrace();
throw new ServiceException("保存失败");
}
//3.返回数据
return rows;
}

 27.Controller实现

业务描述
  1. 获取客户端请求数据
  2. 调用业务层方法将数据写入数据库
  3. 封装结果并返回
方法定义(在SysMenuController中添加相关方法)
  1. 方法名 doSaveObject
  2. 返回值 JsonResult
  3. 参数列表(SysMenu entity)
  4. url 映射( doSaveObject )
代码实现
 
@RequestMapping("doSaveObject")
@ResponseBody
public JsonResult doSaveObject(SysMenu entity){
sysMenuService.saveObject(entity);
return new JsonResult("save ok");
}

 12.客户端实现

28. 保存按钮事件处理

业务描述
  1. 编辑页面save按钮事件注册及事件处理函数定义
  2. 编辑页面 Cancel 按钮事件注册及事件处理函数定义
业务实现
  1. 按钮点击事件注册
  2. 事件处理函数定义
$(document).ready(function(){
//初始化树结构  
$(".form-horizontal")
.on("click",".load-sys-menu",doLoadZtreeNodes);
//表单提交按钮和取消按钮        
$(".box-footer")
.on("click",".btn-cancel",doCancel)
.on("click",".btn-save",doSaveOrUpdate);
//选择菜单的确定和取消按钮的注册
$("#menuLayer")
.on("click",".btn-cancel",doHideTree)
.on("click",".btn-confirm",doSetSelectNode)
//获取#mainContentId上绑定的数据
var rowData=$("#mainContentId").data("rowData");
if(rowData)doInitEditFormData(rowData);
});
代码实现
C ancel 按钮事件处理函数定义
 
function doCancel(){
$("#mainContentId").load("menu/doMenuListUI.do",function(){
$("#mainContentId").removeData();
$("#parentId").removeData();
});
}
Save按钮事件处理函数定义
 
function doSaveOrUpdate(){
//1.获取表单数据
var params= doGetEditFormData();
//2.定义url
var url="menu/doSaveObject.do";
//3.异步提交数据
$.post(url,params,function(result){
if(result.state==1){
alert(result.message);
//加载列表页面
doCancel();
}else{
alert(result.message);
}
});
}
获取表单数据
function doGetEditFormData(){
var params={
type:$("form input[name='typeId']:checked").val(),
name:$("#nameId").val(),
url:$("#urlId").val(),
sort:$("#sortId").val(),
permission:$("#permissionId").val(),
parentId:$("#parentId").data("parentId")
}
return params;
}
效果:
点击添加:

 7.菜单修改页面数据呈现

13.服务端实现

29.Controller实现

业务描述
基于客户端的添加请求返回一个响应页面(与添加操作共用一个页面)
业务实现(在 SysMenuController 中添加相关方法)
  1. 方法名 doMenuE ditUI
  2. 参数列表 ()
  3. 返回值 String
  4. 映射 @RequestMapping(" doMenuEditUI ")
代码实现:
@RequestMapping("doMenuEditUI")
public String doMenuEditUI(){
return "sys/menu_edit";
}

14.客户端实现

30.菜单列表页面修改按钮事件处理

业务描述
点击列表页面修改按钮时加载编辑页面
WEB-INF/pages/sys/menu_list.html
业务实现
  1. 事件注册
$(document).ready(function(){
doGetObjects();
$(".input-group-btn")
//绑定删除按钮
.on("click",".btn-delete",doDeleteObject)
//绑定添加按钮,绑定修改按钮
.on("click",".btn-add .btn-update",doLoadEditUI);
});

 1.事件处理(绑定id,设置标题,异步加载页面)

代码实现:
  1. 页面加载方法定义
function doLoadEditUI(){
var title;
if($(this).hasClass("btn-add")){
title="添加菜单"
}else if($(this).hasClass("btn-update")){
title="修改菜单"
//获取选中的记录数据
var rowData=getCheckedItem();
if(!rowData){
alert("请选择一个");
return;
}
$(" #mainContentId").data("rowData",rowData);
}
var url="menu/doMenuEditUI.do";
$("#mainContentId").load(url,function(){
$(".box-title").html(title);
})
}
获取tr对象上绑定的数据(需要修改源代码找到treegridtr对象创建的地方然后追加绑定数据的操作。)
jquery源码:
function getCheckedItem(){
var tr=$("tbody input[type='radio']:checked")
.parents("tr");
return tr.data("rowData");
}

 31.菜单编辑页面事件处理

WEB-INF/pages/ sys /menu_edit.html
页面描述
页面加载完成,从div中获取绑定的对象,通过对象数据初始化页面表单
方法定义
  1. doInitEditForm(data); 通过查找获取的数据初始化表单
代码实现:
页面加载完成时获取绑定的数据
$(document).ready(function(){
//初始化树结构
$(".form-horizontal").on("click",".load-sys-menu",doLoadZtreeNodes);
//选择菜单的确定和取消按钮的注册
$("#menuLayer")
.on("click",".btn-cancel",doHideTree)
.on("click",".btn-confirm",doSetSelectNode);
//表单提交按钮和取消按钮
$(".box-footer")
.on("click",".btn-cancel",doCancel)
.on("click",".btn-save",doSaveOrUpdate);     
//获取#mainContentId上绑定的数据
var data=$("#mainContentId").data("rowData");
if(data) doInitFormData(data);  
});
编辑页面加载完成执行此方法
function doInitFormData(data){
/*   $("input[type='radio']").each(function(){
if($(this).val()==data.type){
$(this).prop("checked",true);
}
}) */
$("#form").data("id",data.id);
$(".typeRadio input[value='"+data.type+"']").prop("checked",true);
$("#nameId").val(data.name);
$("#sortId").val(data.sort);
$("#urlId").val(data.url);
$("#permissionId").val(data.permission);
$("#parentId").val(data.parentName);
$("#parentId").data("parentId",data.parentId);
}
效果
此处当时的bug
巨坑啊,老齐居然改了jQuery源代码
渲染行将item的值绑定到 tr 上的rowData上

8.菜单数据更新

15.服务端实现

32.Dao 实现

业务描述
SysMenuDao 中添加修改菜单方法,用于实现数据库中菜单信息的修改
方法定义
  1. 方法名 updateObject
  2. 返回值 int
  3. 参数列表 (SysMenu entity)
代码实现
int updateObject(SysMenu entity);

33.Mapper 实现

业务描述
Sys MenuMapper 中添加修改菜单数据的元素
元素定义
  1. 元素名 update
  2. 元素 id updateObject
  3. 参数 com.jt.sys.entity.SysMenu
  4. Sql 定义 update sys_menus set  where ….
代码实现:
<update id="updateObject"
parameterType="com.jt.sys.entity.SysMenu">
update sys_menus
set
name=#{name},
type=#{type},
sort=#{sort},
url=#{url},
parentId=#{parentId},
permission=#{permission},
modifiedUser=#{modifiedUser},
modifiedTime=now()
where id=#{id}
</update>

34.Service 实现

业务描述
  1. 获取控制层数据,对数据进行合法性验证
  2. 通过持久层对象将数据更新到数据库
  3. 验证并返回结果
方法定义
  1. 方法名 updateObject
  2. 返回值 int
  3. 参数列表(SysMenu entity)
代码实现
@Override
public int updateObject(SysMenu entity) {
//1.合法验证
if(entity==null)
throw new ServiceException("保存对象不能为空");
if(StringUtils.isEmpty(entity.getName()))
throw new ServiceException("菜单名不能为空");
//2.更新数据
int rows=sysMenuDao.updateObject(entity);
if(rows==0)
throw new ServiceException("记录可能已经不存在");
//3.返回数据
return rows;
}


 35.Controller实现

业务描述(SysMenuController)
  1. 接收客户端数据
  2. 将数据通过业务层对象进行更新操作
  3. 封装结果并返回
方法定义
  1. 方法名 doUpdateObjec t
  2. 参数列表 SysMenu entity
  3. 返回值 JsonResult
  4. url 映射 doUpdateObject
@RequestMapping("doUpdateObject")
@ResponseBody
public JsonResult doUpdateObject(SysMenu entity){
sysMenuService.updateObject(entity);
return new JsonResult("update ok");
}

 16.客户端实现

36.编辑页面保存按钮事件处理

业务描述
  1. 保存按钮事件注册
  2. 事件处理函数定义(与添加方法共用一个函数)
代码实现:
function doSaveOrUpdate(){
//1.获取表单数据
var params=getEditFormData();
var id=$("#form").data("id");
//2.定义url
var insertUrl="menu/doSaveObject.do";
var updateUrl="menu/doUpdateObject.do";
var url=id?updateUrl:insertUrl;
if(id)params.id=id;
//3.异步提交数据
$.post(url,params,function(result){
if(result.state==1){
alert(result.message);
doCancel();
}else{
alert(result.message);
}
});
}
function getEditFormData(){
var params={
type:$("form input[name='typeId']:checked").val(),
name:$("#nameId").val(),
url:$("#urlId").val(),
sort:$("#sortId").val(),
permission:$("#permissionId").val(),
parentId:$("#parentId").data("parentId")
}
return params;
}
效果:
(略)

9.总结

17.重点和难点分析

  1. 菜单管理在整个系统的中的角色定位
  2. 菜单管理表设计以及自关联查询设计
  3. 多表查询结果的映射问题
  4. 菜单数据的客户端展示( zTree,TreeGrid)

18.常见FAQ

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
java笔记...........................................................................................1. 程序员职业发展: 1.一线程序员 2.一直走技术 3.管理层 4.泛IT、讲师、运维、项目经理和产品经理 5.自己开公司 2. JAVA的优缺点: 优点:需求量大,做项目广 缺点:应聘者多,项目慢,成本高 3. Sublime text的用法: 1.新建一个文件:Ctrl+N 2.给文件命名,由英语、数字或英语+数字组成 3.后缀名".html" 4.保存Ctrl+S(注意保存的路径) 5.删除刚刚的命名,然后输入英文状态的“!”,再点一下Tab键 4. HTML做网页的,中文名字叫超文本标记语言 5. 潜规则: 1.命名时,不要用中文。 2.能用键盘搞定的事情,就不用鼠标。 3.所有符号,都是英文状态下。 6. <!DOCTYPE html>:文档类型是html 7. <html lang="en">:lang:语言;en:英语;zh-cn:汉语 8. <head>:网页的头部 9. <meta charset="UTF-8">:charset:编码;UTF-8:国际标准编码 10. <title>Document</title>:网页的标题 11. </head> <body> 网页的主题 </body> </html> 12. <hn>...</hn>(n:1-6):随着数字的增大,字体越来越小,粗细越来越细 13. 段落标记:<p>...</p> 14. 横线标记:<hr> 15. 强制换行:<br> 16. 根据个数分类: 单标记:<meta/> 、<br/>、 <hr/> 、<img> 双标记:<hn>...</hn> 、<p>...</p>、 <a>...</a> 、<video>...</video> 17. 超链接:<a href="">xxx</a> 18. 注释(html:<!--xxxxx-->):ctrl+/,对代码或代码块的解释和说明,计算机遇到注释,就自动忽略不执行,提高代码的可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从码农到码到成功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值