Spring Boot 综合应用分析
1.1 业务需求分析及设计
从数据库查询所有活动(Activity)信息,然后呈现在页面上(基于thymeleaf,标签应用参考官网thymeleaf.org)。并可以基于其活动信息进行关操作。对于软件开发人员在需求分析时通常会有这样的过程:
第一:需求调研 (与软件使用人之间的一个沟通,了解其业务)
第二:需求分析 (对需求调研内容的总结和细化)
第三:原型设计 (是对需求分析结果的更好呈现)
第四:需求评审 (签字确认,确认边界,确定业务模块)
简历:参与了需求调研,需求分析,原型设计,需求评审。
1.2 系统架构分析及设计
如何理解架构设计?(所有的架构设计必须以业务为前提,脱离业务谈架构就是耍流氓)
第一:架构模式?(CS/BS)
第二:单体架构,分布式架构,微服务架构?
第三:部署架构?(web服务器一台,数据库服务器一台,…)
第四:系统整体分层架构?(基础设施,操作系统,中间件,应用软件,接入层)
第五:软件应用的分层架构?(表示层,请求处理层,业务层,数据层)
1.3 业务代码分析及设计
第一步骤:原型设计(省略)
第二步骤:数据库及表设计并初始化。(基于source指令去实现 )
第三步骤:应用架构设计(MVC)
第四步骤:业务设计,API设计,时序设计?
第五步骤:POJO对象,数据层对象,业务层对象,控制层对象,表示层。
SpringBoot 综合实践实现
搭建项目初始环境
2.1 搭建项目初始环境
第一步:初始化数据库数据(命令行执行)
打开mysql控制台,然后按如下步骤执行activity.sql文件:
1)登录mysql
mysql -uroot -p1234
2)设置客户端编码
set names utf8
3)执行activity.sql文件
source c:/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');
......
第二步: 创建SpringBoot maven项目
第三步:添加项目依赖(MySql,Jdbc API,MyBatis,Spring Web,Thymeleaf)
第四步:修改application.properties文件,进行资源配置
1)添加数据源配置(使用内置的HikariCP连接池)
2)添加mybatis配置
3)添加thymeleaf配置
4)添加日志配置
具体配置代码如下:
#spring datasource
spring.datasource.url=jdbc:mysql:///dbactivity?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=1234
#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml
#spring web
spring.thymeleaf.prefix=classpath:/templates/pages/
#Spring log
logging.level.com.cy=debug
活动模块API设计
活动模块的API对象类型及业务关系设计:
活动模块查询业务实现
服务端实现
第一步:定义pojo对象(com.cy.pj.activity.pojo.Activity)
package com.cy.pj.activity.pojo;
import java.util.Date;
public class Activity {
private Long 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;//有登录模块,需要用登录人员
@Override
public String toString() {
return "Activity [id=" + id + ", title=" + title + ", category=" + category + ", startTime=" + startTime
+ ", endTime=" + endTime + ", remark=" + remark + ", state=" + state + ", createdTime=" + createdTime
+ ", createdUser=" + createdUser + "]";
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public String getCreatedUser() {
return createdUser;
}
public void setCreatedUser(String createdUser) {
this.createdUser = createdUser;
}
}
第二步:定义ActivityDao接口及方法
package com.cy.pj.activity.dao;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.cy.pj.activity.pojo.Activity;
@Mapper
public interface ActivityDao {
@Select("select * from tb_activity")
List<Activity> findActivitys();
}
第三步:定义ActivityService接口及实现类
package com.cy.pj.activity.service;
import java.util.List;
import com.cy.pj.activity.pojo.Activity;
public interface ActivityService {
List<Activity> findActivitys();
}
实现类
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() {
List<Activity> list = activityDao.findActivitys();
return list;
}
}
第四步:定义ActivityController对象及url映射
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
@RequestMapping("/activity")
public class ActivityController {
@Autowired
private ActivityService activityService;
@RequestMapping("/doFindActivitys")
public String doFindActivitys(Model model) {
List<Activity> list = activityService.findActivitys();
model.addAttribute("list", list);
return "activity";
}
}
客户端实现
第一步:定义activity.html页面,在templates/pages/下定义改页面
第二步:通过Thymeleaf模板引擎将活动数据呈现在页面上。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="../bootstrap/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<button type="button" class="btn btn-primary" onclick="javascript:location.href='/activity/activity-add.html'">创建活动 </button>
<table class="table table-striped">
<thead>
<td><input type="checkbox">全选</td>
<th>id</th>
<th>标题</th>
<th>类型</th>
<th>开始时间</th>
<th>结束时间</th>
<th>备注</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</thead>
<tbody>
<tr th:each="lists,status:${list}">
<td><input type="checkbox"></td>
<td th:text="${lists.id}" id="id">1</td>
<td th:text="${lists.title}"></td>
<td th:text="${lists.category}"></td>
<td th:text="${#dates.format(lists.startTime, 'yyyy/MM/dd HH:mm')}"></td>
<td th:text="${#dates.format(lists.endTime, 'yyyy/MM/dd HH:mm')}"></td>
<td th:text="${lists.remark}"></td>
<td th:text="有效" th:if="${lists.state==1}"></td>
<td th:text="无效" th:if="${lists.state==0}"></td>
<td th:text="${#dates.format(lists.createdTime, 'yyyy/MM/dd HH:mm')}"></td>
</tr>
</tbody>
</table>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../jquery/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
活动模块添加业务实现
服务端实现
第一步:在ActivityDao中定义insertObject(Activity activity)方法以及SQL映射
int insertObject(Activity activity);
<?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.cy.pj.activity.dao.ActivityDao">
<insert id="insertObject" >
insert into tb_activity
(title,category,startTime,endTime,remark,state,createdTime,createdUser)
values
(#{title},#{category},#{startTime},#{endTime},#{remark},1,now(),#{createdUser})
</insert>
</mapper>
第二步:在ActivityService接口及实现类中添加saveActivity(Activity entity)
int insertObject(Activity activity);
实现类
@Override
public int insertObject(Activity activity) {
int rows = activityDao.insertObject(activity);
return rows;
}
第三步:在ActivityController对象中添加doSaveActivity方法并定义url映射
@RequestMapping("/activity-add.html")
public String doActivityAddUI() {
return "activity_add";
}
@RequestMapping("/doSaveObject")
public String doSaveObject(Activity activity) {
System.out.println(activity);
activityService.insertObject(activity);
return "redirect:doFindActivitys";
}
添加活动的页面activity_add.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>活动添加页面</title>
<!-- Bootstrap -->
<link href="../bootstrap/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h2>活动添加页面</h2>
<div class="container">
<form action="doSaveObject" method="post">
<div class="form-group">
<label for="title">活动标题</label> <input
type="text" class="form-control" id="title" name="title"
placeholder="please input title">
</div>
<div class="form-group">
<label for="category">活动类型</label> <input
type="text" class="form-control" id="category" name="category"
placeholder="please input title">
</div>
<div class="form-group">
<label for="startTime">开始时间</label> <input
type="text" class="form-control" id="startTime" name="startTime"
placeholder="please input title">
</div>
<div class="form-group">
<label for="endTime">结束时间</label> <input
type="text" class="form-control" id="endTime" name="endTime"
placeholder="please input title">
</div>
<div class="form-group">
<label for="remark">备注</label> <textarea row="5" cols="100"
type="text" class="form-control" id="remark" name="remark"
placeholder="please input title"></textarea>
</div>
<button type="submit" class="btn btn-default">保存</button>
</form>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../jquery/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
活动模块删除操作实现
服务端实现
第一步:ActivityDao中定义基于id删除记录的方法 deleteById(Integer id);
@Delete("delete from tb_activity where id =#{id}")
int deleteById(Integer id);
第二步:ActivityService及实现类中定义deleteById(Integer id)方法用于执行记录删除
int deleteById(Integer id);
实现类
@Override
public int deleteById(Integer id) {
int rows = activityDao.deleteById(id);
return rows;
}
第三步:ActivityController中定义doDeleteById(Integer id)方法用于处理删除请求
@RequestMapping("/doDeleteById")
public String doDeleteById(Integer id,Model model) {
activityService.deleteById(id);
// List<Activity> list = activityService.findActivitys();
// model.addAttribute("list", list);
return "redirect:doFindActivitys";
}
客户端实现
第一步:Activity.html中删除按钮事件注册以及事件处理函数定义
<button type="button" class="btn btn-danger" id="delete" th:onclick="doDelete([[${lists.id}]])" >删除</button>
第二步:在删除事件处理函数内部向服务端发请求执行删除操作。
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../jquery/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript">
function doDelete(id){
//confirm 为window的一个方法,此方法的返回值是一个boolean
if(!confirm("确认删除吗?"))return;
{//基于id执行删除操作
window.location.href="http://localhost:8080/activity/doDeleteById?id="+id; }
}
</script>