关于springboot:13SpringBoot工程下活动Activity模块设计及实现

39次阅读

共计 9354 个字符,预计需要花费 24 分钟才能阅读完成。

业务形容

基于 Spring,MyBatis,SpringBoot,Thymeleaf,Ajax 技术实现流动模块的查问, 增加等操作。

我的项目环境初始化

筹备工作

1. MySQL(5.7)
2. JDK (1.8)
3. Maven (3.6.3)
4. STS(4.7.1)

数据库初始化

关上 mysql 控制台, 而后按如下步骤执行 goods.sql 文件。
第一步: 登录 mysql。

mysql –uroot –proot

第二步: 设置控制台编码方式。

set names utf8;

第三步: 执行 activity.sql 文件(切记不要关上文件复制到 mysql 客户端运行)。

source d:/activity.sql

其中 activity.sql 文件内容如下:

drop database if exists dbactivity;
create database dbactivity default character set utf8;
use dbactivity;
create table tb_activity(
     id bigint primary key auto_increment,
     title varchar(100) not null,
     category varchar(100) not null,
     startTime datetime not null,
     endTime datetime not null,
     remark text,
     state tinyint,
     createdTime datetime not null,
     createdUser varchar(100)
)engine=InnoDB;
insert into tb_activity values (null,'ABS','cuoxiao','2020-02-02 15:00:00','2020-02-03 15:00:00','...',1,now(),'xiaoli');
insert into tb_activity values (null,'VALIDATE','cuoxiao','2020-02-02 15:00:00','2020-02-03 15:00:00','...',1,now(),'xiaoli');
insert into tb_activity values (null,'VALIDATE','cuoxiao','2020-02-02 15:00:00','2020-02-03 15:00:00','...',1,now(),'xiaoli');
insert into tb_activity values (null,'ABS','cuoxiao','2020-02-02 15:00:00','2020-02-03 15:00:00','...',1,now(),'xiaoli');
insert into tb_activity values (null,'ACCESS','cuoxiao','2020-02-02 15:00:00','2020-02-03 15:00:00','...',1,now(),'xiaoli');

创立我的项目并增加依赖

第一步:基于 start.spring.io 创立我的项目并设置根本信息。
第二步:创立我的项目时指定我的项目外围依赖。
第三步:我的项目创立当前剖析其构造。

我的项目配置文件内容初始化

#server
server.port=80
#server.servlet.context-path=/
#spring datasource
spring.datasource.url=jdbc:mysql:///dbactivity?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml

#spring logging
logging.level.com.cy=debug

#spring thymeleaf
spring.thymeleaf.prefix=classpath:/templates/modules/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false

我的项目 API 架构设计

其 API 架构设计,如图所示:

流动模块查问业务实现

业务形容

从数据库查问所有流动 (Activity) 信息,而后出现在页面上(基于 JS 形式进行出现), 如图所示:

业务时序剖析

在浏览器地址栏输出查问流动信息的 url 获取流动信息,其时序过程如图所示:

POJO 类设计及实现

创立 Activity 类, 基于此类对象封装从数据库获取的流动信息, 代码如下:

package com.cy.pj.activity.pojo;
import java.util.Date;
import lombok.Data;
@Data
public class Activity {
    private Integer id;
    private String title;
    private String category;
    private Date startTime;
    private Date endTime;
    private String remark;
    private Integer state;
    private Date createdTime;
    private String createdUser;
}

其中,@Data 注解为 Lombok 注解, 须要在 IDE 环境中曾经装置 lombok 插件, 我的项目中增加 lombok 依赖, 如果没有也能够本人增加 set/get 相干办法

Dao 接口办法及映射定义

定义流动模块数据层接口及查询方法,代码如下:

package com.cy.pj.activity.dao;
import com.cy.pj.activity.pojo.Activity;

@Mapper
public interface ActivityDao {@Select("select * from tb_activity order by createdTime desc")
     List<Activity> findActivitys();}

Service 接口办法定义及实现

定义 service 接口以及获取流动信息的办法,代码如下:

package com.cy.pj.activity.service;
import java.util.List;
import com.cy.pj.activity.pojo.Activity;
// 引入包中的类:ctrl+shift+o

public interface ActivityService {List<Activity> findActivitys();
}

定义 service 接口实现类,并重写接口办法,代码如下:

package com.cy.pj.activity.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cy.pj.activity.dao.ActivityDao;
import com.cy.pj.activity.pojo.Activity;
import com.cy.pj.activity.service.ActivityService;

@Service
public class ActivityServiceImpl implements ActivityService {
    @Autowired
    private ActivityDao activityDao;
    @Override
    public List<Activity> findActivitys() {return  activityDao.findActivitys();
    }
}

Controller 办法定义及实现

package com.cy.pj.activity.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.cy.pj.activity.pojo.Activity;
import com.cy.pj.activity.service.ActivityService;

@Controller
public class ActivityController {
     @Autowired
     private ActivityService activityService;
     
     @RequestMapping("/activity/doActivityUI")
     public String doActivityUI(){return "activity";}
     
     /** 查问所有流动信息 */
     @RequestMapping("/activity/doFindActivitys")
     @ResponseBody
     public List<Activity> doFindActivitys() {List<Activity>  list=activityService.findActivitys();
         return list;
     }
} 

Activity 列表页面设计及实现

本次页面款式基于 bootstrap(一个前端框架,官网为 bootcss.com)进行实现,首先在我的项目工程中增加动态资源,如图所示:
设计 activity.html 页面,引入 bootstrap,jquery 等相干资源,如图所示:
在 activity.html 页面中增加出现 Activity 数据的 html 元素:

<table class="table">
    <thead>
        <tr>
            <th>title</th>
            <th>Category</th>
            <th>StartTime</th>
            <th>EndTime</th>
            <th>State</th>
            <th>Operation</th>
        </tr>
    </thead>
    <tbody id="tbodyId">
        <tr><td colspan="6"> 数据正在加载中.......</td></tr>
    </tbody>
</table>

基于 Ajax 异步加载服务端流动数据并进行部分刷新

<script type="text/javascript"> function doFindActivitys(){
          var url="/activity/doFindActivitys"
          // 启动 ajax 技术, 基于 GET 申请形式获取服务端 json 数据
          //getJSON 函数默认会将服务端返回的 json 串转换为 js 对象
          $.getJSON(url,function(result){var tBody=$("#tbodyId");
              tBody.empty();// 清空原有 body 内容
              for(var i=0;i<result.length;i++){// 循环一次, 迭代一行
                  // 构建以后行对象
                  var tr=`<tr>
                          <td>${result[i].title}</td>
                          <td>${result[i].category}</td>
                          <td>${result[i].startTime}</td>
                          <td>${result[i].endTime}</td>
                          <td>${result[i].state==1?'无效':'有效'}</td>
                          <td><button type='button' class='btn btn-danger btn-sm'>delete</button></td>
                         </tr>`
                  // 将每一行的内容都追加 tbody 中
                  tBody.append(tr);
              }
          });
      };
      doFindActivitys(); </script>

启动 tomcat 服务器进行拜访测试剖析

启动我的项目,在浏览器中输出 activity 页面的拜访地址,出现流动信息,如图所示:
客户端断点调试剖析, 如图所示:
运行时断点设置, 如图所示:
进入断点办法外部, 如图所示:
查看响应数据在客户端的出现, 如图所示:

我的项目启动及运行过程中的 BUG 剖析

  • 数据库链接的 url 配置谬误,如图所示:
  • 空指针异样,如图所示:
  • JS 引入谬误,如图所示:
  • JS 语法错误,如图所示:

流动模块增加业务实现

业务形容

在流动列表页面,设计增加按钮,点击增加按钮时弹出模态框,在模态框中出现流动增加表单元素,其增加表单原型设计,
如图所示:

业务时序剖析

流动增加业务,其时序剖析,如图所示:

Dao 接口办法及映射定义

在 ActivityDao 接口中增加长久化流动信息的办法,代码如下:

int insertObject(Activity activity);

在 ActivityMapper 映射文件中增加映射元素,代码如下:

 <insert id="insertObject" parameterType="com.cy.pj.activity.pojo.Activity"
             useGeneratedKeys="true" keyProperty="id">
          insert into tb_activity
          (title,category,startTime,endTime,remark,state,createdUser,createdTime) 
          values    
          (#{title},#{category},#{startTime},#{endTime},
          #{remark},#{state},#{createdUser},now())
 </insert>

“#{}” 表达式数据获取剖析, 如图所示:
执行 insert 操作时获取数据库主键 id 值,如图所示:
当然,也能够以注解的形式进行 SQL 映射,如图所示:当流动创立好当前,如果到了完结工夫,动静更新流动的状态,代码如下:

@Update("update tb_activity set state=0 where id=#{id}")
int updateState(Long id);

Service 接口办法定义及实现

在 ActivityService 接口中,增加保留流动信息的办法,代码如下:

int saveActivity(Activity entity);

在 ActivityServiceImpl 实现类中增加,接口办法的实现,代码如下:

@Override
public int saveActivity(Activity entity) {int rows=activityDao.insertObject(entity);
        Timer timer=new Timer();
         // 此对象能够负责去执行一些工作(这个对象内置一个线程和一个工作队列)
         // 启动线程执行任务调度
        timer.schedule(new TimerTask() {//TimerTask 为工作
            @Override
            public void run() {
                // 一旦调用此工作的线程取得了 CPU 就会执行这个工作的 run 办法
                activityDao.updateState(entity.getId());
                timer.cancel();// 退出任务调度(后续线程也会销毁)
            }
        }, entity.getEndTime());// 按指定工夫执行工作.
        return rows;
}

Controller 办法定义及实现

在 ActivityController 中增加,解决增加申请的办法,代码如下:

@RequestMapping("/activity/doSaveActivity")
@ResponseBody
public String doSaveActivity(Activity activity) {activityService.saveActivity(activity);
 return "save ok";
} 

Activity 页面增加表单设计及实现

在 activity.html 页面中增加表单元素,用于实现与用户交互,首先在 activity 页面上增加一个增加按钮,代码如下:

<button type="button" class="btn btn-primary btn-sm"
            data-toggle="modal" data-target="#myModal"> 创建活动
</button>

在指定地位增加模态框(可参考 bootcss.com),代码如下:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog"
            aria-labelledby="myModalLabel">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal"
                                                aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                        <h4 class="modal-title" id="myModalLabel"> 创建活动 </h4>
                    </div>
                    <div class="modal-body">    
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default"data-dismiss="modal">Close</button>
                        <button type="button" class="btn btn-primary" onclick="doSaveObject()">
                        Save Changes</button>
                    </div>
                </div>
            </div>
</div> 

在模态框”modal-body”地位,增加 form 表单,代码如下:

<form class="form-horizontal" th:action="@{/activity/doSaveActivity}" method="post">
<div class="form-group">
    <label for="titleId" class="col-sm-2 control-label"> 题目 </label>
        <div class="col-sm-10">
         <input type="text" class="form-control"  name="title" id="titleId" placeholder="title">
        </div>
</div>
<div class="form-group">
<label for="categoryId" class="col-sm-2 control-label"> 类型 </label>
    <div class="col-sm-10">
        <select id="categoryId" name="category" class="form-control">
            <option value="教育培训"> 教育培训 </option>
            <option value="企业流动"> 企业流动 </option>
            <option value="交友流动"> 交友流动 </option>
        </select>
    </div>
</div>
<div class="form-group" >
<label for="startTimeId" class="col-sm-2 control-label"> 开始工夫 </label>
    <div class="col-sm-10">
       <input type="text" class="form-control form_datetime"
         name="startTime" id="startTimeId" placeholder="start time">
    </div>
</div>
<div class="form-group">
    <label for="endTimeId" class="col-sm-2 control-label"> 完结工夫 </label>
    <div class="col-sm-10">
           <input type="text" class="form-control form_datetime" 
            name="endTime" id="endTimeId" placeholder="end time">
    </div>
</div>
<div class="form-group">
    <label for="remarkId" class="col-sm-2 control-label"> 备注 </label>
        <div class="col-sm-10">
           <textarea type="text" class="form-control"  rows="5" name="remark" id="remarkId">
            </textarea>
    </div>
</div>
</form> 

增加 JS 代码,解决模态框 Save 按钮事件,代码如下:

function doSaveObject(){
        //1. 定义 url
        let url="/activity/doSaveObject";
        //2. 定义申请参数
        var params=
      $("#saveFormId").serialize();//serialize()为 jquery 中间接获取表单数据办法
        console.log("params",params);
        //3. 发送异步申请
        $.ajax({
            type:"post",
            url:url,
            data:params,
            success:function(result){alert(result);
                // 暗藏模态框
                $('#myModal').modal('hide');
                // 从新执行查问,部分刷新
                findActivitys();}
        });
        
    }

启动 tomcat 服务器进行拜访测试剖析

启动 tomcat,拜访流动列表页面,如图所示:
在流动列表页面,点击增加按钮,而后启动流动增加模块框,执行增加操作如图所示:
Spring MVC 为办法参数赋值剖析, 如图所示:
日历控件拓展实现(开始工夫和完结工夫通过抉择实现),成果展现,如图所示:
Bootstrap-datapicker 控件的实现过程,如图所示:

我的项目启动及运行过程中的 BUG 剖析

  • BindingException,如图所示:
  • 400 异样,如图所示:
  • 服务端日期格局设计,如图所示:
  • 完整性束缚异样, 如图所示:

总结(Summary)

本模块中解说了流动模块中类的设计,映射设计,交互设计以及实现,而后能够基于此模块的练习增强对业务和技术上的设计及是实现。

正文完
 0