目录:
day01:京淘项目-权限管理子系统-系统概述
day02:京淘项目-权限管理子系统-配置管理
day03:京淘项目-权限管理子系统-菜单模块
day04:京淘项目-权限管理子系统-角色模块
day05:京淘项目-权限管理子系统-用户模块
day06:京淘项目-权限管理子系统-Shiro安全框架
day07:京淘项目-权限管理子系统-Spring AOP
day08:京淘项目-权限管理子系统-Spring事务管理
day01:京淘项目-权限管理子系统-系统概述
1.系统需求概要
-
系统功能模块需求
2.系统非功能需求
![](https://img-blog.csdnimg.cn/ddd276bae24346dc82bcaac0bf8ccf65.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_18,color_FFFFFF,t_70,g_se,x_16)
2.系统架构设计
3.整体分层架构
![](https://img-blog.csdnimg.cn/9468bbe402c548d299cc82bf05fe689b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
-
开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行 网关安全控制、流量控制等。
-
终端显示层:各个端的模板渲染并执行显示的层。当前主要是 JS 渲染, JSP 渲染,移动端展示等。
-
Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
-
Service 层:相对具体的业务逻辑服务层。
-
Manager 层:通用业务处理层,它有如下特征:
-
对第三方平台封装的层,预处理返回结果及转化异常信息;
-
对 Service 层通用能力的下沉,如缓存方案、中间件通用处理;
-
与 DAO 层交互,对多个 DAO 的组合复用。
-
-
DAO 层:数据访问层,与底层 MySQL 、 Oracle 、 Hbase 等进行数据交互。
-
外部接口或第三方平台:包括其它部门 RPC 开放接口,基础平台,其它公司的 HTTP 接口
4.MVC架构实现
![](https://img-blog.csdnimg.cn/ace4cea14a454bd69db79bcdc4dd5c6c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
-
HTML,CSS,JS
-
Bootstrap,AdminLTE,JQuery,Ajax
-
CoreJava,Jdbc,Servlet
-
Spring,SpringMVC,MyBatis,Shiro,DRUID,FastJson,Jackson,Log4j,...
-
MySql
-
......
3.系统数据库设计
![](https://img-blog.csdnimg.cn/39a0bad3357f47b39d889e50e0236023.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_14,color_FFFFFF,t_70,g_se,x_16)
5.配置表设计
6.菜单表设计
7.角色表设计
8.组织表设计
9.用户表设计
10.角色菜单关系表设计
11.角色用户关系设计
12.日志表设计
4.系统环境初始化
13.创建Maven项目
-
创建Maven WEB项目(CGB-JT-SYS-V1.01)
![](https://img-blog.csdnimg.cn/9f11737a63524f9db79c78430a0d9661.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/9bee4bcd42fe4bcaa81344f6f7de164c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/3c98a40b6ef142fa8790e7a7354426c3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
2.配置Maven WEB 项目
-
添加两个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>
![](https://img-blog.csdnimg.cn/d9860c011512436db473fc07739c4e7f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/07402e1654334c55be3cbc0921d934dc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/8e7c284b479540ef849c867003317f26.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/f09432c076214961acc1f4cb4bf04069.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/5097e110ad7b4bc0b06b96aa8f226e44.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/c5d303f24bc8496a8ecbe462e8001e71.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
-
为什么要设置目标运行环境
-
. ..
14.项目技术整合
-
添加项目依赖
<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)
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"};
}
}
/**扫描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");
}
}
@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目录下
![](https://img-blog.csdnimg.cn/3ab64bed31d1420db6b3c04caefd3dc1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_14,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/eadb8011aea84b6392949495ea994bba.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/4e2fd01e4dba45288069017f013c2dfa.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
15.项目首页设计
-
创建Controller类
2.Controller类中添加方法返回首页页面.(starter.html)
@RequestMapping("/")
@Controller
public class PageController {
@RequestMapping("doIndexUI")
public String doIndexUI(){
return "starter";
}
}
![](https://img-blog.csdnimg.cn/f19952a4285e4157b23396365073d412.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/2a03418cc6e949f4b966be7d81f34c01.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_7,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/02d1dfa9e41e412594d7c4acdd55efee.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/ae5bf819a23e485090196f6dd98aaa3f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/3ffe3db69566488e9ee4b9485d11d099.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/e3a9b185781f482fac1610d276761b2d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/89e8095d1f024c679bad89965f108666.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/5941b2f24117423c93c5488f12c5358e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/41b28e0083aa4959b1bfb7603b93426a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
day02:京淘-项目权限管理子系统-配置管理
1.配置管理列表页面呈现
1.服务端实现
-
Controller实现
-
定义配置管理Controller处理配置管理的客户端请求
-
修改首页Controller添加pageUI方法返回page页面
-
配置管理Controller类的定义
2.配置管理Controller中方法定义(添加返回页面的相关方法)
@Controller
@RequestMapping("/config/")
public class SysConfigController {
@RequestMapping("doConfigListUI")
public String doConfigListUI(){
return "sys/config_list";
}
}
2.客户端实现
2.首页页面starter.html配置管理事件处理
-
准备配置列表页面( WEB-INF/pages/sys/config_list.html)
-
点击配置管理菜单时异步加载配置列表页面。
-
事件注册(被点击的元素上)
-
事件处理函数定义
$(function(){
$("#load-config-id").click(function(){
$("#mainContentId").load("config/doConfigListUI.do");
});
})
3.创建配置列表页面config_list.html
-
在 Page Controller中添加do P ageUI方法返回page页面
-
在config_list.html页面中异步加载page页面页面
$(function(){
$("#pageId").load("doPageUI.do");
});
2.配置管理列表数据呈现
3.服务端实现
4.Entity类实现
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接口实现
-
接收业务层参数数据
-
基于参数进行数据查询
-
将查询结果进行封装
-
将结果返回给业务层对象
-
D ao 接口定义
2.方法定义:负责基于条件查询当前页数据
3.方法定义:负责基于条件查询总记录数
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文件实现
-
基于Dao接口创建映射文件
-
基于Dao方法在映射文件中创建映射元素建映射元素
-
创建映射文件
2.创建映射元素实现翻页查询操作
3.创建映射元素实现查询统计操作
<?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接口及实现类
-
通过参数变量接收控制层数据
-
对数据进行合法验证
-
基于参数数据进行总记录数查询
-
基于参数数据进行当前页记录的查询
-
对数据进行封装
-
..........
-
业务值对象定义:(封装分页信息以及当前数据)
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.接口定义:为控制层请求提供服务
3.接口方法定义:
public interface SysConfigService {
/**
* 通过此方法实现分页查询操作
* @param name 基于条件查询时的参数名
* @param pageCurrent 当前的页码值
* @return 当前页记录+分页信息
*/
PageObject<SysConfig> findPageObjects(
String name,
Integer pageCurrent);
}
4.接口实现类的定义:
@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类的实现
-
接收客户端请求中的数据
-
基于请求调用业务方法进行请求处理
-
对处理结果进行封装(JsonResult)
-
将结果转换为json格式的字符串
-
将字符串通过服务器输出到客户端。
-
值对象定义:(封装控制层方法的返回结果)
2.Controller方法定义:(在SysConfigController中定义请求处理方法)
3.统一异常类的定义
4.异常类中方法定义(处理参数异常的方法)
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);
}
}
运行进行测试:
![](https://img-blog.csdnimg.cn/1161fbc504174d8eb0644f4bf773985f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
4.客户端实现
9.列表页面config_list.html配置信息呈现
-
页面加载完成发起异步请求加载配置信息
-
通过服务端返回的数据更新当前列表页面
-
定义doGetObjects()函数,通过此函数执行异步加载操作。
-
分页页面加载完成以后调用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);
}
/*设置表格内容*/
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);
}
}
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;
}
效果:
![](https://img-blog.csdnimg.cn/5ca40ea23aca4164b2b80f79ec8caa94.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
10.列表页面config_list.html分页信息呈现
-
配置信息异步加载完成以后初始化分页数据(调用setPagination函数)
-
点击分页元素时异步加载当前页(pageCurrent)数据(调用jumpToPage)
-
定义setPagination方法(实现分页数据初始化)
-
定义jumpToPage方法(通过此方法实现当前数据查询)
-
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);
}
![](https://img-blog.csdnimg.cn/7e613d6e65524b1daf9c51f53202f168.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_15,color_FFFFFF,t_70,g_se,x_16)
11.列表页面config_list.html信息查询实现
-
列表查询按钮事件注册
-
列表查询按钮事件处理函数定义
-
列表查询参数获取以及传递
-
在$ (function(){}) 回调函数中追加查询按钮的事件注册。
-
定义查询按钮的事件处理函数doQueryObjects
-
重用doGetObjects函数并添加查询参数name
/**
*查询按钮事件注册
*/
$(function (){
$(".input-group-btn").on("click",".btn-search",doQueryObjects);
});
查询按钮事件处理函数定义
/**
*查询按钮事件处理函数定义
*/
function doQueryObjects(){
//为什么要在此位置初始化pageCurrent的值为1?
//数据查询时页码的初始位置也应该是第一页
$("#pageId").data("pageCurrent",1);
//为什么要调用doGetObjects函数?
//重用js代码,简化jS代码编写。
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};
//为什么此位置要获取查询参数的值?
//一种冗余的应用方法,目的时让此函数在查询时可以重用。
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);
});
}
![](https://img-blog.csdnimg.cn/a897d1d713a0465e82810df61928ef78.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
3.配置管理删除操作实现
5.服务端的实现
12.Dao接口实现
-
接收业务层参数数据(String[] ids)
-
基于数据执行删除操作
-
方法名 deleteObjects
-
方法参数 (String[] ids)
-
方法返回值 int
int deleteObjects(@Param("ids")Integer... ids);
13.Mapper文件实现
<delete id="deleteObjects">
delete from sys_configs
where id in
<foreach collection="ids"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</delete>
14.Service接口实现
-
接收控制层数据并进行合法验证
-
基于业务层数据执行删除操作
-
对删除过程进行监控(先进行异常捕获)
-
对删除结果进行验证并返回
@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实现
-
接收客户端请求数据
-
调用业务层方法执行删除操作
-
封装结果并返回
-
方法名 doDeleteObjects
-
参数列表 String ids
-
返回值 JsonResult
-
映射 doDeleteObjects
@RequestMapping("doDeleteObjects")
@ResponseBody
public JsonResult doDeleteObjects(Integer... ids){
sysConfigService.deleteObjects(ids);
return new JsonResult("delete ok");
}
6.客户端的实现
16.配置列表页面实现
-
页面全选操作实现
-
页面删除按钮事件注册
-
页面删除操作事件处理函数定义
-
T head中全选checkbox元素事件注册及事件处理函数 doCheckAll 定义
-
T body中checkbox元素事件注册及事件处理函数 doChangeCheckAllState 定义
-
在$ (function(){}) 回调函数中追加删除按钮的事件注册操作。
-
定义事件处理函数d oDeleteObjects, 处理删除按钮的点击操作。
全选按钮注册
/**
*全选按钮注册
*/
$(function (){
$("thead").on("change","#checkAll",doCheackAll);
});
/**
*tbody中checkbox对象事件注册
*/
$(function (){
$("#tbodyId").on("change",".cBox",doChangeCheckAllState);
});
//当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);
}
});
}
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实现
/**
* 添加页面
*/
@RequestMapping("doConfigEditUI")
public String doConfigEditUI() {
return "sys/config_edit";
}
8.客户端实现
18.配置列表页面实现
-
添加按钮事件注册
-
添加按钮事件处理函数定义
-
在$ (function(){}) 事件处理函数内部追加事件注册
-
定义表页面中添加按钮的事件处理函数
$(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');
});
}
5.配置管理数据添加实现
9.服务端实现
10.Dao实现
-
接收业务层数据(SysConfig)
-
将数据写入到数据库(ORM)
-
方法名 insertObject
-
参数列表 SysConfig entity
-
返回值 int
int insertObject(SysConfig entity);
20.Mapper实现
<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实现
-
接收控制层数据(SysConfig对象)
-
对数据进行合法性验证(非空验证,..)
-
将对象通过Dao写入到数据库。
-
返回结果。
-
方法名 doSaveObject
-
参数列表 (SysConfig entity)
-
返回值 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实现
-
接收客户端请求数据并将数据封装到SysConfig对象
-
调用业务层方法将数据写入数据库
-
对控制层数据进行封装(JsonResult),并返回
-
方法名 doSaveObject
-
参数列表 (SysConfig entity)
-
方法映射 doSaveObject
@RequestMapping("doSaveObject")
@ResponseBody
public JsonResult doSaveObject(SysConfig entity){
sysConfigService.saveObject(entity);
return new JsonResult("save ok");
}
10客户端实现
23.配置管理编辑页面实现
-
模态框保存按钮点击事件注册
-
模态框隐藏事件注册
-
定义事件处理函数处理模态框的保存按钮事件。
-
在$ (function(){}) 的回调函数中追加事件注册
-
定义保存按钮对应的事件处理函数d oSaveOrUpdate
![](https://img-blog.csdnimg.cn/b00d94cbb31a4b50a5339c33739e846c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
$(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;
}
![](https://img-blog.csdnimg.cn/f0c5d0fdc7084bc2bf47d1bef818d6fc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_19,color_FFFFFF,t_70,g_se,x_16)
6.配置管理编辑页面数据呈现
11.服务端实现
24.Controller 实现
/**
* 添加页面
*/
@RequestMapping("doConfigEditUI")
public String doConfigEditUI() {
return "sys/config_edit";
}
12.客户端实现
25.配置列表页面
-
修改按钮上进行事件注册(借助on方法)
-
修改按钮事件处理函数定义(与页面上的添加按钮共用是一个事件处理函数)
-
修改tbody中数据呈现的方法,在每个tr上绑定当前行记录。
-
在$(function(){})的事件处理函数中追加update按钮的事件注册操作
-
修改showEditDialog方法,基于点击对象的不同执行不同业务操作
-
在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');
});
}
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.配置编辑页面
-
页面加载完成以后从模块框上获取绑定的数据。
-
通过模块框中绑定数据初始页页面表单。
-
在$(function(){})事件处理函数中追加获取绑定数据的操作
-
定义初始化页面表单数据的函数 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);
}
效果:
![](https://img-blog.csdnimg.cn/09fe3260981b4227ab41b8ec02cbb401.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/62be938210e1432d9c2e5ace8e1dd766.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
7.配置管理数据更新操作实现
13.服务端实现
27.Dao实现
-
接收业务层数据(SysConfig对象)
-
将对象更新到数据库。
/**
* 更新配置信息
* @param entity 封装配置信息
* @return 表示更新的行数
*/
int updateObject(SysConfig entity);
28.Mapper实现
<update id="updateObject">
update sys_configs
set
name=#{name},
value=#{value},
note=#{note},
modifiedTime=now(),
modifiedUser=#{modifiedUser}
where id=#{id}
</update>
29.Service实现
-
对参数进行合法验证
-
通过dao将数据更新到数据库
-
对结果进行验证并返回。
@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实现
-
接收客户端请求数据(借助SysConfig对象)
-
调用业务层方法更新数据
-
对结果进行封装(JsonResult)
-
将JsonResult对象转换为Json格式的字符串。
@RequestMapping("doUpdateObject")
@ResponseBody
public JsonResult doUpdateObject(SysConfig entity){
sysConfigService.updateObject(entity);
return new JsonResult("update ok");
}
14.客户端实现
31.编辑页面事件处理
/**
*模态框事件注册
*/
$(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);
}
});
}
![](https://img-blog.csdnimg.cn/11ead2a7b690414796491a3bcaa27d09.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/84b19cae67c24530a2b7b5e1a0e1c78b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/bf53b3fc2c7348dc82c64e1aeb9be3d6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
8.总结
15.重点和难点分析
-
配置管理整体架构业务分析及实现。
-
配置管理持久层映射文件中SQL元素的定义及编写。
-
配置管理业务层业务分析,数据封装,异常抛出。
-
配置管理控制层请求数据映射,响应数据的封装及转换。
-
配置管理客户端JS代码, ajax 异步请求响应的编写及调试。
16.常见FAQ
-
配置管理分页查询操作实现
-
配置管理分页数据加载的基本过程?(当前页数据获取,总记录数的获取)
-
映射文件中元素共性如何提取?(借助sql元素定义共性,使用include进行包含)
-
映射文件中参数的获取?(动态sql参数获取时,dao中的参数尽量使用@param修饰)
-
持久层只提供了Dao接口没有提供实现,请问实现类是谁创建的?(Spring)
-
配置管理中PageObject的作用是什么?(封装当前页面数据以及分页信息)
-
配置管理中JsonResult对象的作用是什么?(封装服务端的响应信息)
-
配置管理中的异常处理是如何实现的?(定义统一异常处理类,并对异常进行封装)
-
进行异常处理的目的是什么?(提高系统的容错能力,改善用户体验)
-
服务端控制层将对象转换为json串时使用的json库是什么?(jackson)
-
Jackson库中的对象将Date对象转换到json串时默认是怎样的存储的?(long)
-
假如将对象转换为json串时,希望日期类型的对象按照自己指定格式进行输出,如何实现?(客户端转换,服务端转换)
-
.....
-
多个异步请求的顺序问题?(两次异步请求需要有一定的先后顺序)
-
getJSON函数的应用?(Get方式的ajax请求)
-
JS对象的创建?(原生的,借助jquery)
-
JS中的循环?(for(var i in records){})
-
.....
2.配置管理删除操作实现?
-
服务端
1.删除方案?(业务层多次删除,数据层同时删除多个)
2.映射文件中动态Sql的编写(foreach)
3.....
2.客户端
-
Checkbox值的获取(获取所有checkbox,然后判定选中,最后取选中的值)
-
全选操作的实现(业务,change事件处理)
-
....
3.配置管理添加操作实现?
-
持久层数据添加操作的定义及实现
-
业务层数据保存业务的实现
-
控制层请求数据封装,处理,响应。
4.客户端
-
模态框的呈现及隐藏
-
模态框事件的绑定以及解绑
-
持久层数据修改映射操作的定义及实现
-
业务层数据修改的实现
-
控制请求数据封装,处理,响应。
6.客户端
-
列表页面修改时当前行记录的获取以及绑定
-
列表页面修改与添加按钮共用一个事件处理函数,在模态框加载编辑页面。
-
编辑页面数据的初始化,点击修改按钮时数据数据的获取以及异步提交操作
day03:京淘-权限管理子系统-菜单模块
1.菜单页面呈现
1.服务端实现
-
菜单Controller实现
-
定义 controller 对象处理客户端菜单访问请求
-
定义相关方法处理列表页面加载需求
-
包名 com.jt.sys.controller
-
类名 SysMenuController
-
映射 @RequestMapping("/menu/")
-
方法名 doMenuListUI
-
参数列表( )
-
返回值 String
-
映射 @RequestMapping("doMenuListUI")
@RequestMapping("doMenuListUI")
public String doMenuListUI(){
return "sys/menu_list";
}
2.客户端实现
2.定义菜单列表页面
3.首页页面菜单管理事件处理
$(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.服务端实现
4.DAO实现
-
定义菜单持久层对象,处理数据访问操作
-
定义菜单查询方法,查询所有菜单以及上一级菜单信息(只取id,名字)
-
包名: com.jt.sys.dao
-
类名 : SysMenuDao
-
方法名 findObjects ( 本查询不做分页)
-
参数列表()
-
返回值 List<Map<String,Object>> ( 一行记录对应一个map,多个map放list)
public interface SysMenuDao {
List<Map<String,Object>> findObjects();
}
5.Mapper实现
-
元素名 select
-
元素 id findObjects
-
结果类型 resultType =map
-
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实现
-
定义菜单业务接口,负责处理菜单模块业务
-
定义业务方法,访问 dao 层方法获取菜单信息
-
包名: com.jt.sys.service
-
类名 : SysMenuService
-
方法名 findObjects
-
参数列表()
-
返回值 List <Map<String,Object>>
public interface SysMenuService {
List<Map<String,Object>> findObjects();
}
-
包名: com.jt.sys.service.impl
-
类名 :SysMenuServiceImpl
@Service
public class SysMenuServiceImpl implements SysMenuService {
@Autowired
private SysMenuDao sysMenuDao;
@Override
public List<Map<String, Object>> findObjects() {
return sysMenuDao.findObjects();
}
}
7.Controller实现
-
方法名 doFindObjects
-
参数列表()
-
返回值 JsonResult
-
映射 @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.菜单列表页面实现
-
数据呈现时使用jquery中的treeGrid插件.
-
页面加载完成,异步加载数据,以树结构table形式呈现.
-
引入treeGrid相关 js 文件
-
定义方法异步加载数据
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();
}
![](https://img-blog.csdnimg.cn/3f5f14589e0b4eaba011b59ca58a8bdc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
3.菜单数据删除
-
查询此菜单有没有对应的子菜单,有则不允许删除
-
删除菜单 ( 市场有两种业务)
5.服务端实现
9.DAO实现
- 业务实现:
-
基于菜单id查询是否有子菜单(有子菜单则不能删除 )
-
根据菜单id删除菜单自身信息 .
-
根据菜单id删除角色菜单关系数据
-
在SysMenuDao接口中定义基于id查询是否有子菜单的方法)
2.在SysMenuDao接口中定义根据id删除菜单的方法
3.创建基于角色菜单关系表的DAO接口
4.在SysRoleMenuDao接口中创建基于菜单id删除记录的方法
/**
* 根据菜单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实现
-
SysMenuMapper中统计子菜单元素定义
2.SysMenuMapper根据id删除菜单的元素定义
3.创建基于SysRoleMenuDao的映射文件
4.SysRoleMenuMapper文件中定义基于菜单id删除记录的元素
<select id="getChildCount"
parameterType="int"
resultType="int">
select count(*)
from sys_menus
where parentId=#{id}
</select>
<delete id="deleteObject"
parameterType="int">
delete from sys_menus
where id=#{id}
</delete>
<delete id="deleteObjectsByMenuId"
parameterType="int">
delete from sys_role_menus
where menu_id=#{id}
</delete>
11.Service实现
-
接收控制数据(id),并对数据进行合法验证
-
基于id查询菜单子元素,并进行判定
-
删除菜单元素
-
删除角色菜单关系数据.
-
返回结果.
-
方法名 deleteObject
-
参数列表 (Integer id)
-
返回值 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实现
-
获取客户端请求数据(菜单 id)
-
调用业务层方法删除数据
-
封装并返回结果
-
方法名 doDeleteObject
-
参数列表 Integer id
-
返回值 JsonResult
-
映射 @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.列表页面删除按钮事件处理
-
删除按钮事件注册
-
删除按钮事件处理函数定义.
$(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);
}
});
}
function getCheckedId(){
//1.获取选中的记录
var selections=$("#menuTable")
//bootstrapTreeTable是treeGrid插件内部定义的jquery扩展函数
//getSelections为扩展函数内部要调用的一个方法
.bootstrapTreeTable("getSelections");
//2.对记录进行判定
if(selections.length==1)
return selections[0].id;
}
![](https://img-blog.csdnimg.cn/0676bf1ed3294e749d327390edbba4dc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
4.菜单添加页面呈现
7.服务端实现
14.菜单Controller方法定义
-
方法名 doMenuE ditUI
-
参数列表 ()
-
返回值 String
-
映射 @RequestMapping(" doMenuEditUI ")
@RequestMapping("doMenuEditUI")
public String doMenuEditUI(){
return "sys/menu_edit";
}
8.客户端实现
15.菜单编辑页面定义
16.菜单列表页面添加按钮事件处理
-
事件注册
-
事件处理函数定义
$(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);
})
}
![](https://img-blog.csdnimg.cn/aac2e1ff959445598f57f8a9d253ac47.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/93b4635d2f2d448dbe8952b6b8bb8bda.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
5.菜单编辑页面上级菜单呈现
-
点击编辑页面的上级菜单时向服务端发起异步请求
-
服务端基于请求获取菜单节点数据
-
客户端通过服务端返回数据异步刷新页面.
9.服务端实现
-
17.Node值对象
-
类名 Node
-
接口 实现序列化接口并添加版本id
-
字段 (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实现
-
方法名 findZtreeMenuNodes
-
参数列表()
-
返回值 List<Node>
List<Node> findZtreeMenuNodes();
19.Mapper实现
-
元素名 select
-
元素 id findZtreeMenuNodes
-
结果类型 com .jt.common.vo.Node
-
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实现
-
方法名 findZtreeMenuNodes
-
参数列表()
-
返回值 List<Node>
@Override
public List<Node> findZtreeMenuNodes() {
return sysMenuDao.findZtreeMenuNodes();
}
21.Controller实现
-
方法名 doFindZtreeMenuNodes
-
参数列表()
-
返回值 JsonResult
-
映射 @RequestMapping("doFindZtreeMenuNodes");
@RequestMapping("doFindZtreeMenuNodes")
@ResponseBody
public JsonResult doFindZtreeMenuNodes(){
return new JsonResult(
sysMenuService.findZtreeMenuNodes(),
"query ok");
}
10.客户端实现
22.菜单编辑页面事件处理
-
点击事件注册
-
事件处理函数定义
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();
}
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);
}
})
}
效果:
![](https://img-blog.csdnimg.cn/3b689743f02b4150853b51346fcac1cc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/9ea19fd0e19c44b0b3b401a36f0a782b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/c0d86c5947744dc5887d978943936809.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
6.菜单数据添加操作
11.服务端实现
23.Entity对象定义
-
包名:com.jt.sys.entity
-
类名:SysMenu
-
实现序列化接口并添加序列化版本id
-
属性与表(sys_menus)中字段有对应关系
-
提供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 实现
-
方法名 insertObject
-
返回值 int
-
参数列表 ( SysMenu entity)
int insertObject(SysMenu entity);
25.Mapper中元素定义
-
元素名 insert
-
元素id insertObject
-
参数类型 com.jt.sys.entity.SysMenu
-
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中方法定义
-
获取页面中数据,并对数据进行合法验证
-
将数据写入到数据库
-
判定结果,并返回
-
方法名saveObject
-
返回值 int
-
参数列表 (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实现
-
获取客户端请求数据
-
调用业务层方法将数据写入数据库
-
封装结果并返回
-
方法名 doSaveObject
-
返回值 JsonResult
-
参数列表(SysMenu entity)
-
url 映射( doSaveObject )
@RequestMapping("doSaveObject")
@ResponseBody
public JsonResult doSaveObject(SysMenu entity){
sysMenuService.saveObject(entity);
return new JsonResult("save ok");
}
12.客户端实现
28. 保存按钮事件处理
-
编辑页面save按钮事件注册及事件处理函数定义
-
编辑页面 Cancel 按钮事件注册及事件处理函数定义
-
按钮点击事件注册
-
事件处理函数定义
$(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);
});
function doCancel(){
$("#mainContentId").load("menu/doMenuListUI.do",function(){
$("#mainContentId").removeData();
$("#parentId").removeData();
});
}
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;
}
![](https://img-blog.csdnimg.cn/c5573499d88e491393764ae763193364.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/b73053feddb44d00b47ec4c34fca81fc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/09e71b203d62430a80b5850ab3f77b50.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/34922b7161724400b92fba01137cea0b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
7.菜单修改页面数据呈现
13.服务端实现
29.Controller实现
-
方法名 doMenuE ditUI
-
参数列表 ()
-
返回值 String
-
映射 @RequestMapping(" doMenuEditUI ")
@RequestMapping("doMenuEditUI")
public String doMenuEditUI(){
return "sys/menu_edit";
}
14.客户端实现
30.菜单列表页面修改按钮事件处理
-
事件注册
$(document).ready(function(){
doGetObjects();
$(".input-group-btn")
//绑定删除按钮
.on("click",".btn-delete",doDeleteObject)
//绑定添加按钮,绑定修改按钮
.on("click",".btn-add .btn-update",doLoadEditUI);
});
1.事件处理(绑定id,设置标题,异步加载页面)
-
页面加载方法定义
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);
})
}
![](https://img-blog.csdnimg.cn/f09540fa15534604a05214eff632e7e3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/cfe1d735b19647b08be863f83ecd726d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
function getCheckedItem(){
var tr=$("tbody input[type='radio']:checked")
.parents("tr");
return tr.data("rowData");
}
31.菜单编辑页面事件处理
-
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);
}
![](https://img-blog.csdnimg.cn/93db8f45a8ce4654bfa69090a76126bf.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/89f98a40996649eb87b838f48862cf0c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/7e53f69c45564b2484883500b06aa0d0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/30bea2ff66dc44d0a9e2b5b7c42924f7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/bf5e7993d8a94565a39bdf60079ad4ff.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/a3c64f42b6904a3c9c2f82b80e6bf8f1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/ecd056e83b6042c086af6433af2c301f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR0Mt5omr5Zyw5YOn,size_20,color_FFFFFF,t_70,g_se,x_16)
8.菜单数据更新
15.服务端实现
32.Dao 实现
-
方法名 updateObject
-
返回值 int
-
参数列表 (SysMenu entity)
int updateObject(SysMenu entity);
33.Mapper 实现
-
元素名 update
-
元素 id updateObject
-
参数 com.jt.sys.entity.SysMenu
-
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 实现
-
获取控制层数据,对数据进行合法性验证
-
通过持久层对象将数据更新到数据库
-
验证并返回结果
-
方法名 updateObject
-
返回值 int
-
参数列表(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实现
-
接收客户端数据
-
将数据通过业务层对象进行更新操作
-
封装结果并返回
-
方法名 doUpdateObjec t
-
参数列表 SysMenu entity
-
返回值 JsonResult
-
url 映射 doUpdateObject
@RequestMapping("doUpdateObject")
@ResponseBody
public JsonResult doUpdateObject(SysMenu entity){
sysMenuService.updateObject(entity);
return new JsonResult("update ok");
}
16.客户端实现
36.编辑页面保存按钮事件处理
-
保存按钮事件注册
-
事件处理函数定义(与添加方法共用一个函数)
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.重点和难点分析
-
菜单管理在整个系统的中的角色定位
-
菜单管理表设计以及自关联查询设计
-
多表查询结果的映射问题
-
菜单数据的客户端展示( zTree,TreeGrid)