1-Spring Boot 综合应用分析
1.1业务需求分析及设计
从数据库查询所有活动(Activity)信息,然后呈现在页面上(基于thymeleaf,标签应用参考官网thymeleaf.org)。并可以基于其活动信息进行关操作。对于软件开发人员在需求分析时通常会有这样的过程:
第一:需求调研 (与软件使用人之间的一个沟通,了解其业务)
第二:需求分析 (对需求调研内容的总结和细化)
第三:原型设计 (是对需求分析结果的更好呈现)
第四:需求评审 (签字确认,确认边界,确定业务模块)
简历:参与了需求调研,需求分析,原型设计,需求评审。
职位:需求分析师(咨询师)
1.2系统架构分析及设计
如何理解架构设计?(所有的架构设计必须以业务为前提,脱离业务谈架构就是耍流氓)
第一:架构模式?(CS/BS)
第二:单体架构,分布式架构,微服务架构?
第三:部署架构?(web服务器一台,数据库服务器一台,…)
第四:系统整体分层架构?(基础设施,操作系统,中间件,应用软件,接入层)
第五:软件应用的分层架构?(表示层,请求处理层,业务层,数据层)
职位:架构师
1.3系统架构分析及设计
第一步骤:原型设计(省略)
第二步骤:数据库及表设计并初始化。(基于source指令去实现 )
第三步骤:应用架构设计(MVC)
第四步骤:业务设计,API设计,时序设计?
第五步骤:POJO对象,数据层对象,业务层对象,控制层对象,表示层。
2-SpringBoot 综合实践实现
2.1搭建项目初始环境:
第一步:初始化数据库数据(命令行执行)
打开mysql控制台,然后按如下步骤执行goods.sql文件:
1)登录mysql
mysql -uroot -proot
2)设置客户端编码
set names utf8
3)执行activity.sql文件
source d:/activity.sql
第二步: 创建SpringBoot maven项目
第三步:添加项目依赖(MySql,Jdbc API,MyBatis,Spring Web,Thymeleaf)
第四步:修改application.properties文件,进行资源配置
1)添加数据源配置(使用内置的HikariCP连接池)
2)添加mybatis配置
3)添加thymeleaf配置
4)添加日志配置
代码如下:
server.port=80 spring.datasource.url=jdbc:mysql:///dbactivity?serverTimezone=GMT%2B8&characterEncoding = utf-8 spring.datasource.username=root spring.datasource.password=root mybatis.mapper-locations=classpath:/mapper/*/*.xml spring.thymeleaf.prefix=classpath:/templates/pages/ spring.thymeleaf.cache=false logging.level.com.cy=debug management.endpoints.web.exposure.include=*
第五步:启动项目,检测是否启动OK
2.2 活动模块API设计:
活动模块的API对象类型及业务关系设计,如图所示:
2.3 活动模块查询业务实:
2.3.1:业务时序分析
2.3.2 服务端实现:
第一步:定义pojo对象(com.cy.pj.activity.pojo.Activity)
@Data public class Activity { private Long id; private String title; private String category; //此注解用于描述属性或set方法,告诉spring mvc 按指定格式接收客户端数据 @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm") private Date startTime;//java.util.Date @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm") private Date endTime; private String remark; private Integer state; private Date createdTime; private String createdUser; //有登陆模块的话,是登陆用户 }
第二步:定义ActivityDao接口及方法
@Mapper public interface ActivityDao { /** * 基于活动id查询活动信息 * @param id * @return */ @Select("select * from tb_activity where id=#{id}") Activity findById(Long id); /** * 更新对象信息 * @param entity * @return */ int updateObject(Activity entity); int insertObject(Activity entity); @Delete("delete from tb_activity where id=#{id}") int deleteById(Long id); @Select("select * from tb_activity order by createdTime desc") List<Activity> findActivitys(); }
第三步:定义ActivityService接口及实现类
public interface ActivityService { Activity findById(Long id); int updateObject(Activity entity); int saveObject(Activity entity); int deleteById(Long id); List<Activity> findActivitys(); }
@Service public class ActivityServiceImpl implements ActivityService { @Autowired private ActivityDao activityDao; @Override public Activity findById(Long id) { return activityDao.findById(id); } @Override public int updateObject(Activity entity) { //.... return activityDao.updateObject(entity); } @Override public int saveObject(Activity entity) { //.... return activityDao.insertObject(entity); } @Override public int deleteById(Long id) { //.... return activityDao.deleteById(id); } @Override public List<Activity> findActivitys() { //..... return activityDao.findActivitys(); } }
第四步:定义ActivityController对象及url映射
Controller对象:
@Controller @RequestMapping("/activity/") public class ActivityController { @Autowired private ActivityService activityService; @RequestMapping("doUpdateObject") public String doUpdateObject(Activity entity) { System.out.println("controller.entity="+entity); activityService.updateObject(entity); return "redirect:activity.html"; } @RequestMapping("doFindById") public String doFindById(Long id,Model model) { Activity aty=activityService.findById(id); model.addAttribute("aty", aty); return "activity-edit"; } /** * 所有控制层方法都由spring mvc框架通过反射调用。 * 底层调用方法时会将http请求中的数据注入给方法参数 name="title" * @param entity * @return */ @RequestMapping("doSaveObject") public String doSaveObject(Activity entity) { System.out.println("controller.entity="+entity); activityService.saveObject(entity); return "redirect:activity.html"; } @RequestMapping("activity-add.html") public String doActivityAddUI() { return "activity-add"; } @RequestMapping("doDeleteById") public String doDeleteById(Long id) { activityService.deleteById(id); return "redirect:activity.html"; } @RequestMapping("activity.html") public String doFindActivitys(Model model) { List<Activity> list=activityService.findActivitys(); model.addAttribute("list",list); return "activity"; } }
url映射
<?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"> <update id="updateObject"> update tb_activity set title=#{title}, category=#{category}, startTime=#{startTime}, endTime=#{endTime}, remark=#{remark} where id=#{id} </update> <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>
客户端实现:
第一步:定义activity.html页面
第二步:通过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"> <h2>活动列表页面</h2> </div> <div class="container"> <button type="button" class="btn btn-primary" onclick="javascript:location.href='/activity/activity-add.html'">创建活动</button> <table class="table"> <thead> <tr> <th><input type="checkbox">全选</th> <th>名称</th> <th>开始时间</th> <th>结束时间</th> <th>状态</th> <th colspan="2">操作</th> </tr> </thead> <tbody> <tr th:each="a:${list}"> <td><input type="checkbox"></td> <td th:text="${a.title}">互动答疑</td> <td th:text="${#dates.format(a.startTime, 'yyyy/MM/dd HH:mm')}">2020/12/12</td> <td th:text="${#dates.format(a.endTime, 'yyyy/MM/dd HH:mm')}">2020/12/15</td> <td th:text="${a.state==1?'有效':'失效'}">有效</td> <td><button type="button" class="btn btn-danger btn-sm" th:onclick="doDelete([[${a.id}]])">delete</button> <button type="button" class="btn btn-warning btn-sm" th:onclick="doFindById([[${a.id}]])">update</button> </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> <script type="text/javascript"> function doDelete(id){ //confirm为window对象中的一个方法,此方法的返回值为true或false if(!confirm("确认删除吗"))return; //基于id执行记录的删除操作 location.href="/activity/doDeleteById?id="+id; } function doFindById(id){ location.href="/activity/doFindById?id="+id; } </script> </body> </html>0216